很幸运又拿到了STM32的板子,周末用了下,发几篇贴子分享下.
首先还是不免俗地上几张图,虽说STM32的Nucleo144板子的图各位坛友早就有点"审美疲劳了", 不过拿到板子后我还是忍不住拍两张.
板子的主控是STM32U575ZIT6QU, 是主打低功耗应用的新的系列. 这个系列功能非常强大,同时兼顾低功耗和安全.
Cortex M33自带的Trust Zone, 其余常规外设也非常丰富.
除了以太网接口和无线接口之外,暂时想不到还缺少什么外设. Flash和SRAM更是高达2MB和784KB. 对于大多数的嵌入式应用来说,外设存储都不是问题了.
当然硬件这些都是基础, 本人对STM系列的产品感觉最靠谱的是开发生态. 以STM32CubeMX为代表的开发工具,让应用设计者开发起来非常便捷.
本篇分享一个使用片上硬件Hash加速单元的例子.
应用设计中,尤其是通信/安全相关的设计中, 计算Hash/HMAC的场景很多, 比如校验下载数据的完整性,正确性. 但是Hash/HMAC计算很吃CPU资源. 尤其是需要频繁计算的场景下, CPU资源的很大一部分都给这种计算占去了. 所以即使是非嵌入式的CPU, 近年来也纷纷把这种计算进行硬件加速. 原因无他, 即CPU做这种计算不是很合算, CPU适合处理变化复杂的运算, Hash/Hmac这种运算变化不大,但需要很多指令周期去完成.
参考:Intel的Hash扩展,
https://edc.intel.com/content/ww ... e%20a%20family%20of,processing%20SHA-1%20and%20SHA-256%20on%20Intel%20architecture-based%20processors.
说到Hash的硬件加速, 大家也可以想象 "+密 货B Wa 矿",那是典型的使用ASIC或者GPU对Hash进行加速的场景.
所以STM32的一些系列就带有这种硬件Hash加速单元, 将这种不适合软件运算的工作从CPU那里解放出来.而且这个硬件单元使用起来也非常简单, 还支持DMA.
首先创建一个STM32CubeMX的工程, 选择不需要TrustZone, 关于TrustZone的使用, 以后会另外发贴分享. 当不使用TrustZone时, Cortex M33和Cortex M7基本特性一致.
选择激活Hash加速单元
这个单元激活即可, 底下配置框内的设置都可以用通过代码在运行时修改的,现在不用太在意.
可以看到这个硬件加速单元支持这几种硬件加速运算:
SHA1
MD5
SHA224
SHA256
HMAC-SHA1
HMAC-MD5
HMAC-SHA224
HMAC-SHA256
值得注意的是, SHA1,MD5以及它们对应的HMAC算法现在已经被认为是不安全的了, 即攻击它们的成本现在并不高. 包含在这里, 可能还是为了兼容之前的数据和应用吧. 毕竟一下子淘汰SHA1,MD5还不现实. 如果大家设计新的应用,建议不要选择MD5,SHA1算法.反正都是通过硬件加速, MD5,SHA1运算的优势也没那么明显.
其余就都选默认即可, 生成代码框架.
主函数里分别对以上算法进行测试,即给一个输入,把计算结果打印出来.
printf("Core Freq:%u Hz ", SystemCoreClock); /****************************************************************************/ /*************************** HMAC-SHA1 **************************************/ /****************************************************************************/ if (HAL_HMAC_SHA1_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aHashDigest, 0xFF) != HAL_OK) { Error_Handler(); } printf("HMAC-SHA1 test passed. "); print_hex(aHashDigest, 20); /****************************************************************************/ /*************************** HMAC-MD5 ***************************************/ /****************************************************************************/ if (HAL_HASH_DeInit(&hhash) != HAL_OK) { Error_Handler(); } MX_HASH_Init(); if (HAL_HMAC_MD5_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aHashDigest, 0xFF) != HAL_OK) { Error_Handler(); } printf("HMAC-MD5 test passed. "); print_hex(aHashDigest, 16); /****************************************************************************/ /*************************** HMAC-SHA224 * ***************************************/ /****************************************************************************/ if (HAL_HASH_DeInit(&hhash) != HAL_OK) { Error_Handler(); } MX_HASH_Init(); if (HAL_HMACEx_SHA224_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aHashDigest, 0xFF) != HAL_OK) { Error_Handler(); } printf("HMAC-SHA224 test passed. "); print_hex(aHashDigest, 28); /****************************************************************************/ /*************************** HMAC-SHA256 * ***************************************/ /****************************************************************************/ if (HAL_HASH_DeInit(&hhash) != HAL_OK) { Error_Handler(); } MX_HASH_Init(); if (HAL_HMACEx_SHA256_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aHashDigest, 0xFF) != HAL_OK) { Error_Handler(); } printf("HMAC-SHA256 test passed. "); print_hex(aHashDigest, 32); /****************************************************************************/ /*************************** Hash-SHA1 * ***************************************/ /****************************************************************************/ if (HAL_HASH_DeInit(&hhash) != HAL_OK) { Error_Handler(); } MX_HASH_Init(); if (HAL_HASH_SHA1_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aHashDigest, 0xFF) != HAL_OK) { Error_Handler(); } printf("Hash-SHA1 test passed. "); print_hex(aHashDigest, 20); /****************************************************************************/ /*************************** Hash-MD5 ***************************************/ /****************************************************************************/ if (HAL_HASH_DeInit(&hhash) != HAL_OK) { Error_Handler(); } MX_HASH_Init(); if (HAL_HASH_MD5_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aHashDigest, 0xFF) != HAL_OK) { Error_Handler(); } printf("Hash-MD5 test passed. "); print_hex(aHashDigest, 16); /****************************************************************************/ /*************************** Hash-SHA224 * ***************************************/ /****************************************************************************/ if (HAL_HASH_DeInit(&hhash) != HAL_OK) { Error_Handler(); } MX_HASH_Init(); if (HAL_HASHEx_SHA224_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aHashDigest, 0xFF) != HAL_OK) { Error_Handler(); } printf("Hash-SHA224 test passed. "); print_hex(aHashDigest, 28); /****************************************************************************/ /*************************** Hash-SHA256 * ***************************************/ /****************************************************************************/ if (HAL_HASH_DeInit(&hhash) != HAL_OK) { Error_Handler(); } MX_HASH_Init(); if (HAL_HASHEx_SHA256_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aHashDigest, 0xFF) != HAL_OK) { Error_Handler(); } printf("Hash-SHA256 test passed. "); print_hex(aHashDigest, 32); printf("%u %u ", SystemCoreClock, HAL_GetTick());
其中打印Hex数据函数和测试数据:
#define INPUT_TAB_SIZE ((uint32_t) 261)/* The size of the input data "aInput" */ __ALIGN_BEGIN static const uint8_t pKeyHASH[261] __ALIGN_END = { 0x54,0x68,0x65,0x20,0x68,0x61,0x73,0x68,0x20,0x70, 0x72,0x6f,0x63,0x65,0x73,0x73,0x6f,0x72,0x20,0x69, 0x73,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x79,0x20, 0x63,0x6f,0x6d,0x70,0x6c,0x69,0x61,0x6e,0x74,0x20, 0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61, 0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68, 0x65,0x20,0x73,0x65,0x63,0x75,0x72,0x65,0x20,0x68, 0x61,0x73,0x68,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69, 0x74,0x68,0x6d,0x20,0x28,0x53,0x48,0x41,0x2d,0x31, 0x29,0x2c,0x20,0x74,0x68,0x65,0x20,0x4d,0x44,0x35, 0x20,0x28,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x2d, 0x64,0x69,0x67,0x65,0x73,0x74,0x20,0x61,0x6c,0x67, 0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x35,0x29,0x20, 0x68,0x61,0x73,0x68,0x20,0x61,0x6c,0x67,0x6f,0x72, 0x69,0x74,0x68,0x6d,0x20,0x61,0x6e,0x64,0x20,0x74, 0x68,0x65,0x20,0x48,0x4d,0x41,0x43,0x20,0x28,0x6b, 0x65,0x79,0x65,0x64,0x2d,0x68,0x61,0x73,0x68,0x20, 0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x20,0x61,0x75, 0x74,0x68,0x65,0x6e,0x74,0x69,0x63,0x61,0x74,0x69, 0x6f,0x6e,0x20,0x63,0x6f,0x64,0x65,0x29,0x20,0x61, 0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x73, 0x75,0x69,0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f, 0x72,0x20,0x61,0x20,0x76,0x61,0x72,0x69,0x65,0x74, 0x79,0x20,0x6f,0x66,0x20,0x61,0x70,0x70,0x6c,0x69, 0x63,0x61,0x74,0x69,0x6f,0x6e,0x73,0x2e,0x2a,0x2a, 0x2a,0x20,0x53,0x54,0x4d,0x33,0x32,0x20,0x2a,0x2a, 0x2a}; __ALIGN_BEGIN const uint8_t aInput[INPUT_TAB_SIZE] __ALIGN_END = {0x54,0x68,0x65,0x20,0x68,0x61,0x73,0x68, 0x20,0x70,0x72,0x6f,0x63,0x65,0x73,0x73, 0x6f,0x72,0x20,0x69,0x73,0x20,0x61,0x20, 0x66,0x75,0x6c,0x6c,0x79,0x20,0x63,0x6f, 0x6d,0x70,0x6c,0x69,0x61,0x6e,0x74,0x20, 0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e, 0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f, 0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x65, 0x63,0x75,0x72,0x65,0x20,0x68,0x61,0x73, 0x68,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69, 0x74,0x68,0x6d,0x20,0x28,0x53,0x48,0x41, 0x2d,0x31,0x29,0x2c,0x20,0x74,0x68,0x65, 0x20,0x4d,0x44,0x35,0x20,0x28,0x6d,0x65, 0x73,0x73,0x61,0x67,0x65,0x2d,0x64,0x69, 0x67,0x65,0x73,0x74,0x20,0x61,0x6c,0x67, 0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x35, 0x29,0x20,0x68,0x61,0x73,0x68,0x20,0x61, 0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d, 0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65, 0x20,0x48,0x4d,0x41,0x43,0x20,0x28,0x6b, 0x65,0x79,0x65,0x64,0x2d,0x68,0x61,0x73, 0x68,0x20,0x6d,0x65,0x73,0x73,0x61,0x67, 0x65,0x20,0x61,0x75,0x74,0x68,0x65,0x6e, 0x74,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e, 0x20,0x63,0x6f,0x64,0x65,0x29,0x20,0x61, 0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d, 0x20,0x73,0x75,0x69,0x74,0x61,0x62,0x6c, 0x65,0x20,0x66,0x6f,0x72,0x20,0x61,0x20, 0x76,0x61,0x72,0x69,0x65,0x74,0x79,0x20, 0x6f,0x66,0x20,0x61,0x70,0x70,0x6c,0x69, 0x63,0x61,0x74,0x69,0x6f,0x6e,0x73,0x2e, 0x2a,0x2a,0x2a,0x20,0x53,0x54,0x4d,0x33, 0x32,0x20,0x2a,0x2a,0x2a}; __ALIGN_BEGIN static uint8_t aHashDigest[32] __ALIGN_END; void print_hex(uint8_t* buf, uint32_t len) { for(uint32_t i=0; i<len; ++i) { printf("%02X", *(buf+i)); } printf(" "); }
构建, 获取计算结果:
计算起来很快的, 具体相对于软件计算的加速倍数跟优化选项和是否选择DMA有关, 之前在其他系列上测试过, 跟软件计算的速度相比至少是两个数量级. 感兴趣的同学可以做一个精确的Benchmark.
另外使用一个Python程序来验证运算的结果准确性:
import hmac import hashlib import sys import binascii import json def main_str(key, msg) -> None: print("key:%s msg:%s " % (key, msg)) bkey = bytes(key, 'utf-8') bmsg = bytes(msg, 'utf-8') main_bin(bkey, bmsg) return def main_bin(bkey, bmsg) -> None: print("bkey:%s bmsg:%s " % (binascii.hexlify(bkey), binascii.hexlify(bmsg))) result = hashlib.md5(bmsg).hexdigest() print("hash md5: " + result) result = hashlib.sha1(bmsg).hexdigest() print("hash sha1: " + result) result = hashlib.sha224(bmsg).hexdigest() print("hash sha224: " + result) result = hashlib.sha256(bmsg).hexdigest() print("hash sha256: " + result) result = hmac.new(bkey, bmsg, hashlib.md5).hexdigest() print("hmac md5: " + result) result = hmac.new(bkey, bmsg, hashlib.sha1).hexdigest() print("hmac sha1: " + result) result = hmac.new(bkey, bmsg, hashlib.sha224).hexdigest() print("hmac sha224: " + result) result = hmac.new(bkey, bmsg, hashlib.sha256).hexdigest() print("hmac sha256: " + result) return if __name__ == "__main__": read_mode='string' if 1 < len(sys.argv): if sys.argv[1] == 's': read_mode = 'string' test_key='The hash processor is a fully compliant implementation of the secure hash algorithm (SHA-1), the MD5 (message-digest algorithm 5) hash algorithm and the HMAC (keyed-hash message authentication code) algorithm suitable for a variety of applications.*** STM32 ***' test_msg='The hash processor is a fully compliant implementation of the secure hash algorithm (SHA-1), the MD5 (message-digest algorithm 5) hash algorithm and the HMAC (keyed-hash message authentication code) algorithm suitable for a variety of applications.*** STM32 ***' if 2 < len(sys.argv): test_key=sys.argv[2] if 3 < len(sys.argv): test_msg=sys.argv[3] main_str(test_key, test_msg) pass elif sys.argv[1] == 'f': read_mode = 'file' test_hex_input_file='hexInput.json' test_bkey=b'x12x34' test_bmsg=b'x45x67' if 2 < len(sys.argv): test_hex_input_file=sys.argv[2] json_load='' with open(test_hex_input_file, mode='rb') as fin: json_load = json.load(fin) test_bkey = bytearray.fromhex(json_load['key']) test_bmsg = bytearray.fromhex(json_load['msg']) main_bin(test_bkey, test_bmsg) pass else: print("invalid read mode:" + sys.argv[1]) pass else: print("no read mode provided!") pass pass
测试数据文件:
{ "key":"54686520686173682070726f636573736f7220697320612066756c6c7920636f6d706c69616e7420696d706c656d656e746174696f6e206f662074686520736563757265206861736820616c676f726974686d20285348412d31292c20746865204d443520286d6573736167652d64696765737420616c676f726974686d203529206861736820616c676f726974686d20616e642074686520484d414320286b657965642d68617368206d6573736167652061757468656e7469636174696f6e20636f64652920616c676f726974686d207375697461626c6520666f7220612076617269657479206f66206170706c69636174696f6e732e2a2a2a2053544d3332202a2a2a", "msg":"54686520686173682070726f636573736f7220697320612066756c6c7920636f6d706c69616e7420696d706c656d656e746174696f6e206f662074686520736563757265206861736820616c676f726974686d20285348412d31292c20746865204d443520286d6573736167652d64696765737420616c676f726974686d203529206861736820616c676f726974686d20616e642074686520484d414320286b657965642d68617368206d6573736167652061757468656e7469636174696f6e20636f64652920616c676f726974686d207375697461626c6520666f7220612076617269657479206f66206170706c69636174696f6e732e2a2a2a2053544d3332202a2a2a" }
验证:
$ python3 t1.py f bkey:b'54686520686173682070726f636573736f7220697320612066756c6c7920636f6d706c69616e7420696d706c656d656e746174696f6e206f662074686520736563757265206861736820616c676f726974686d20285348412d31292c20746865204d443520286d6573736167652d64696765737420616c676f726974686d203529206861736820616c676f726974686d20616e642074686520484d414320286b657965642d68617368206d6573736167652061757468656e7469636174696f6e20636f64652920616c676f726974686d207375697461626c6520666f7220612076617269657479206f66206170706c69636174696f6e732e2a2a2a2053544d3332202a2a2a' bmsg:b'54686520686173682070726f636573736f7220697320612066756c6c7920636f6d706c69616e7420696d706c656d656e746174696f6e206f662074686520736563757265206861736820616c676f726974686d20285348412d31292c20746865204d443520286d6573736167652d64696765737420616c676f726974686d203529206861736820616c676f726974686d20616e642074686520484d414320286b657965642d68617368206d6573736167652061757468656e7469636174696f6e20636f64652920616c676f726974686d207375697461626c6520666f7220612076617269657479206f66206170706c69636174696f6e732e2a2a2a2053544d3332202a2a2a' hash md5: 6707862c7cd0b522b2dd22d8477be318 hash sha1: f859c18dec9472427924fb61ef7c6a6b670bf9c3 hash sha224: 76ccdd1fde036cde39c9d23ce6bdb169ff743b89d15791bfba109a55 hash sha256: 9691cf47c93807990b049ad4d2e7f60133ab48aada53a80889a3da46170f4afe hmac md5: 877ebbbfc8a9c08578a2c331d67ec70e hmac sha1: 2b47ef34f66658be3b2ac6ec5885f21ed59fddad hmac sha224: 6bd3132e89c7715c9cbaee0150d0b25c577297e4264031cae9656078 hmac sha256: c501fc6c173778e69744ae06944f094c9eaf1c562f58debc478cdea85a421f58
谢谢阅读, 下一篇再见!
---------------------
作者:zhanzr21
链接:https://bbs.21ic.com/icview-3288320-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。