[ModusToolbox™] 【英飞凌CYW20829测评】篇5 CYW20829之AES加密

[复制链接]
1168|0
 楼主| abner_ma 发表于 2024-7-22 21:01 | 显示全部楼层 |阅读模式
本帖最后由 abner_ma 于 2024-7-22 21:03 编辑

     英飞凌AIROC™CYW20829是一款高性能、超低功耗、“安全”的MCU+蓝牙,基于Cortex-M33内核支持TrustZone技术,该技术允许将处理器划分为安全区域和非安全区域,从而保护关键数据和代码免受恶意攻击。当与AES-128加密结合使用时,这种安全性得到进一步增强,使得存储在MCU中的数据更加难以被非法获取或篡改。基于M33内核的MCU都内置了AES硬件加速器,用于加速AES算法的执行。这些硬件加速器可以显著提高加密和解密的速度,同时降低CPU的功耗。在使用AES-128加密时,这些硬件加速器能够发挥重要作用,使得加密过程更加高效和安全。   CYW20829基于M33架构和AES-128加密的解决方案广泛应用于各种需要高安全性和低功耗的应用场景中。例如,在物联网设备中,M33处理器可以负责处理设备的核心逻辑,并通过AES-128加密来保护设备与云端之间的通信安全;在智能家居系统中,M33处理器可以实现对家电设备的智能控制,并通过AES-128加密来保护用户的隐私数据。
   

CYW20829 硬件(HW)和软件(SW)的结合能够支持多种加密功能,内置了AES硬件加速器,以支持AES-128、AES-192或AES-256等加密标准的实现。提高加密性能并降低CPU负担。
• 加密/解密
  • AES-128 硬件加速器,支持以下模式:
    • 电子密码本模式(ECB)
    • 密码块链接模式(CBC)
    • 密码反馈模式(CFB)
    • 输出反馈模式(OFB)
    • 计数器模式(CTR)

• 哈希
  • 安全散列算法(SHA-256)硬件加速器
• 消息认证功能(MAC)
  • 使用SHA-256硬件加速的哈希消息认证码(HMAC)
• 真随机数生成器(TRNG)
• 向量单元硬件加速器
  • 使用RSA进行数字签名验证
  • 使用ECDSA进行数字签名验证
这些功能共同构成了强大的加密和数据处理能力,适用于需要高安全性的应用场景,如数据传输、存储保护、身份验证等。
代码
  1. /******************************************************************************
  2. * File Name: main.c
  3. *
  4. * Description: This code provides an implementation of AES Cryptolite,
  5. * demonstrating how to encrypt and decrypt data using the CTR and CFB modes.
  6. *
  7. * Related Document: See README.md
  8. *
  9. *******************************************************************************
  10. * Copyright 2021-2024, Cypress Semiconductor Corporation (an Infineon company) or
  11. * an affiliate of Cypress Semiconductor Corporation.  All rights reserved.
  12. *
  13. * This software, including source code, documentation and related
  14. * materials ("Software") is owned by Cypress Semiconductor Corporation
  15. * or one of its affiliates ("Cypress") and is protected by and subject to
  16. * worldwide patent protection (United States and foreign),
  17. * United States copyright laws and international treaty provisions.
  18. * Therefore, you may use this Software only as provided in the license
  19. * agreement accompanying the software package from which you
  20. * obtained this Software ("EULA").
  21. * If no EULA applies, Cypress hereby grants you a personal, non-exclusive,
  22. * non-transferable license to copy, modify, and compile the Software
  23. * source code solely for use in connection with Cypress's
  24. * integrated circuit products.  Any reproduction, modification, translation,
  25. * compilation, or representation of this Software except as specified
  26. * above is prohibited without the express written permission of Cypress.
  27. *
  28. * Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND,
  29. * EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
  30. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress
  31. * reserves the right to make changes to the Software without notice. Cypress
  32. * does not assume any liability arising out of the application or use of the
  33. * Software or any product or circuit described in the Software. Cypress does
  34. * not authorize its products for use in any products where a malfunction or
  35. * failure of the Cypress product may reasonably be expected to result in
  36. * significant property damage, injury or death ("High Risk Product"). By
  37. * including Cypress's product in a High Risk Product, the manufacturer
  38. * of such system or application assumes all risk of such use and in doing
  39. * so agrees to indemnify Cypress against all liability.
  40. *******************************************************************************/

  41. /*******************************************************************************
  42. *Header Files
  43. *******************************************************************************/

  44. #include "cyhal.h"
  45. #include "cybsp.h"
  46. #include "cy_retarget_io.h"
  47. #include "cy_pdl.h"
  48. #include <string.h>

  49. /*******************************************************************************
  50. * Macros
  51. *******************************************************************************/
  52. /* The input message size (inclusive of the string terminating character '\0').
  53. * Edit this macro to suit your message size.
  54. */
  55. #define MAX_MESSAGE_SIZE                     (100u)

  56. /* Size of the message block that can be processed by Cryptolite hardware for
  57. * AES encryption.
  58. */
  59. #define AES128_ENCRYPTION_LENGTH             (uint32_t)(16u)

  60. #define AES128_KEY_LENGTH                    (uint32_t)(16u)

  61. /* Number of bytes per line to be printed on the UART terminal. */
  62. #define BYTES_PER_LINE                       (16u)

  63. /* Time to wait to receive a character from UART terminal. */
  64. #define UART_INPUT_TIMEOUT_MS                (1u)

  65. /* Available commands */
  66. #define CRYPTOLITE_AES_CTR ('1')
  67. #define CRYPTOLITE_AES_CFB ('2')

  68. /*******************************************************************************
  69. * Data type definitions
  70. *******************************************************************************/
  71. /* Data type definition to track the state machine accepting the user message */
  72. typedef enum
  73. {
  74.     MESSAGE_ENTER_NEW,
  75.     MESSAGE_READY
  76. } message_status_t;


  77. /*******************************************************************************
  78. * Global Variables
  79. *******************************************************************************/

  80. /* UART object used for reading character from terminal */
  81. extern cyhal_uart_t cy_retarget_io_uart_obj;


  82. /* Variables to hold the user message and the corresponding encrypted message */
  83. static uint8_t message[MAX_MESSAGE_SIZE];
  84. static uint8_t encrypted_msg[MAX_MESSAGE_SIZE];
  85. static uint8_t decrypted_msg[MAX_MESSAGE_SIZE];

  86. /* Key used for AES encryption*/
  87. static uint8_t aes_key[AES128_KEY_LENGTH] = {0xAA, 0xBB, 0xCC, 0xDD,
  88.                                             0xEE, 0xFF, 0xFF, 0xEE,
  89.                                             0xDD, 0xCC, 0xBB, 0xAA,
  90.                                             0xAA, 0xBB, 0xCC, 0xDD,};



  91. /******************************CTR Encryption**********************************/
  92. /* AES CFB MODE Initialization Vector*/
  93. static uint8_t AesCtrIV[] =
  94. {
  95.     0x00,0x01,0x02,0x03,
  96.     0x04,0x05,0x06,0x07,
  97.     0x08,0x09,0x0A,0x0B,
  98.     0x0C,0x0D,0x0E,0x0F,
  99. };

  100. static uint8_t AesCtrIV_copied[16];

  101. /********************************CFB Encryption********************************/
  102. /* AES CFB MODE Initialization Vector */
  103. static uint8_t AesCfbIV[] =
  104. {
  105.     0x00,0x01,0x02,0x03,
  106.     0x04,0x05,0x06,0x07,
  107.     0x08,0x09,0x0A,0x0B,
  108.     0x0C,0x0D,0x0E,0x0F,
  109. };

  110. static uint8_t AesCfbIV_copied[16];

  111. /******************************************************************************
  112. *Function Definitions
  113. ******************************************************************************/

  114. void print_data(uint8_t* data, uint8_t len);
  115. void encrypt_message_cfb(uint8_t* message, uint8_t size);
  116. void decrypt_message_cfb(uint8_t* message, uint8_t size);
  117. void encrypt_message_ctr(uint8_t* message, uint8_t size);
  118. void decrypt_message_ctr(uint8_t* message, uint8_t size);


  119. /*******************************************************************************
  120. * Function Name: main
  121. ********************************************************************************
  122. * Summary:
  123. * This is the main function and entry point to the application.
  124. *
  125. * Parameters:
  126. *  void
  127. *
  128. * Return:
  129. *  int
  130. *
  131. *******************************************************************************/

  132. int main(void)
  133. {
  134.     cy_rslt_t result;

  135.     uint8_t dst_cmd;
  136.     /* Variable to track the status of the message entered by the user */
  137.     message_status_t msg_status = MESSAGE_ENTER_NEW;
  138.     uint8_t msg_size = 0;

  139.     /* Initialize the device and board peripherals */
  140.     result = cybsp_init();
  141.     /* Board init failed. Stop program execution */
  142.     if (result != CY_RSLT_SUCCESS)
  143.     {
  144.         CY_ASSERT(0);
  145.     }

  146.     /* Enable global interrupts */
  147.     __enable_irq();

  148.     /* Initialize retarget-io to use the debug UART port */
  149.     result = cy_retarget_io_init_fc(    CYBSP_DEBUG_UART_TX,
  150.                                         CYBSP_DEBUG_UART_RX,
  151.                                         CYBSP_DEBUG_UART_CTS,
  152.                                         CYBSP_DEBUG_UART_RTS,
  153.                                         CY_RETARGET_IO_BAUDRATE);
  154.     /* retarget-io init failed. Stop program execution */
  155.     if (result != CY_RSLT_SUCCESS)
  156.     {
  157.         CY_ASSERT(0);
  158.     }
  159.     printf("*****************CE : Cryptolite AES *****************\r\n");
  160.     printf("\r\n\nKey used for Encryption:\r\n");
  161.     print_data(aes_key, AES128_KEY_LENGTH);
  162.     printf("\n\rEnter the message:\r\n");
  163.     for (;;)
  164.     {
  165.         switch (msg_status)
  166.         {
  167.             case MESSAGE_ENTER_NEW:
  168.             {
  169.                 result = cyhal_uart_getc(&cy_retarget_io_uart_obj,
  170.                                         &message[msg_size],
  171.                                         UART_INPUT_TIMEOUT_MS);
  172.                 if (result == CY_RSLT_SUCCESS)
  173.                     {
  174.                     /* Check if the ENTER Key is pressed. If pressed, set the
  175.                        message status as MESSAGE_READY.*/
  176.                     if (message[msg_size] == '\r' || message[msg_size] == '\n')
  177.                     {
  178.                         message[msg_size]='\0';
  179.                         msg_status = MESSAGE_READY;
  180.                     }
  181.                     else
  182.                     {
  183.                         cyhal_uart_putc(&cy_retarget_io_uart_obj,
  184.                                         message[msg_size]);

  185.                         /* Check if Backspace is pressed by the user. */
  186.                         if(message[msg_size] != '\b')
  187.                         {
  188.                             msg_size++;
  189.                         }
  190.                         else
  191.                         {
  192.                             if(msg_size > 0)
  193.                             {
  194.                                 msg_size--;
  195.                             }
  196.                         }
  197.                         /*Check if size of the message  exceeds MAX_MESSAGE_SIZE
  198.                         (inclusive of the string terminating character '\0').*/
  199.                         if (msg_size > (MAX_MESSAGE_SIZE - 1))
  200.                         {
  201.                         printf("\r\n\nMessage length exceeds %d characters!!!"\
  202.                         " Please enter a shorter message\r\nor edit the macro "\
  203.                         "MAX_MESSAGE_SIZE to suit your message size\r\n", MAX_MESSAGE_SIZE);

  204.                         /* Clear the message buffer and set the msg_status to
  205.                             accept new message from the user. */
  206.                         msg_status = MESSAGE_ENTER_NEW;
  207.                         memset(message, 0, MAX_MESSAGE_SIZE);
  208.                         msg_size = 0;
  209.                         printf("\r\nEnter the message when more than limit:\r\n");
  210.                         break;
  211.                         }
  212.                     }
  213.                     }
  214.                     break;
  215.                 }

  216.                 case MESSAGE_READY:
  217.                 {
  218.                 printf("\n\n\r Choose one of the following AES Mode :\r\n");
  219.                 printf("\n\r (1) CTR (Counter) mode\r\n");
  220.                 printf("\n\r (2) CFB (Cipher Feedback Block) mode\r\n");
  221.                 while(cyhal_uart_getc(&cy_retarget_io_uart_obj, &dst_cmd, 1)!= CY_RSLT_SUCCESS);
  222.                 cyhal_uart_putc(&cy_retarget_io_uart_obj, dst_cmd);

  223.                 if (CRYPTOLITE_AES_CTR == dst_cmd)
  224.                 {
  225.                     printf("\n\r[Command] : AES CTR Mode\r\n");
  226.                     encrypt_message_ctr(message, msg_size);
  227.                     decrypt_message_ctr(message, msg_size);
  228.                 }
  229.                 else if (CRYPTOLITE_AES_CFB == dst_cmd)
  230.                 {
  231.                     printf("\n\r[Command] : AES CFB Mode\r\n");
  232.                     encrypt_message_cfb(message, msg_size);
  233.                     decrypt_message_cfb(message, msg_size);
  234.                 }

  235.                 /* Clear the message buffer and set the msg_status to accept
  236.                 * new message from the user.
  237.                 */

  238.                 msg_status = MESSAGE_ENTER_NEW;
  239.                 memset(message, 0, MAX_MESSAGE_SIZE);
  240.                 msg_size = 0;
  241.                 printf("\n\n\rEnter the message again to accept:\r\n");
  242.                 break;
  243.                 }
  244.             }
  245.         }

  246. }

  247. /*******************************************************************************
  248. * Function Name: print_data()
  249. ********************************************************************************
  250. * Summary: Function used to display the data in hexadecimal format
  251. *
  252. * Parameters:
  253. *  uint8_t* data - Pointer to location of data to be printed
  254. *  uint8_t  len  - length of data to be printed
  255. *
  256. * Return:
  257. *  void
  258. *
  259. *******************************************************************************/

  260. void print_data(uint8_t* data, uint8_t len)
  261. {
  262.     char print[10];
  263.     for (uint32 i=0; i < len; i++)
  264.     {
  265.         if ((i % BYTES_PER_LINE) == 0)
  266.         {
  267.             printf("\r\n");
  268.         }
  269.         snprintf(print,10,"0x%02X ", *(data+i));
  270.         printf("%s", print);
  271.     }
  272.     printf("\r\n");
  273. }

  274. /*******************************************************************************
  275. * Function Name: encrypt_message_cfb
  276. ********************************************************************************
  277. * Summary: Function used to encrypt the message through cfb mode.
  278. *
  279. * Parameters:
  280. *  char * message - pointer to the message to be encrypted
  281. *  uint8_t size   - size of message to be encrypted.
  282. *
  283. * Return:
  284. *  void
  285. *
  286. *******************************************************************************/


  287. void encrypt_message_cfb(uint8_t* message, uint8_t size)
  288. {
  289.     cy_stc_cryptolite_aes_state_t aes_state;
  290.     cy_stc_cryptolite_aes_buffers_t aesBuffers;
  291.     uint8_t aes_block_count = 0;
  292.     cy_en_cryptolite_status_t res;
  293.     void* result;

  294.     aes_block_count =  (size % AES128_ENCRYPTION_LENGTH == 0) ?
  295.                        (size / AES128_ENCRYPTION_LENGTH)
  296.                        : (1 + size / AES128_ENCRYPTION_LENGTH);

  297.     /* Initializes the AES operation by setting key and key length */
  298.     res = Cy_Cryptolite_Aes_Init(CRYPTOLITE, aes_key, &aes_state, &aesBuffers);
  299.     if(res!=CY_CRYPTOLITE_SUCCESS)
  300.     {
  301.         CY_ASSERT(0);
  302.     }

  303.     result = memcpy(AesCfbIV_copied, AesCfbIV, sizeof(AesCfbIV));
  304.     if(result == NULL)
  305.     {
  306.         perror("Memory failed\r\n");
  307.     }

  308.     res = Cy_Cryptolite_Aes_Cfb(  CRYPTOLITE,
  309.                             CY_CRYPTOLITE_ENCRYPT,
  310.                             aes_block_count * AES128_ENCRYPTION_LENGTH,
  311.                             AesCfbIV_copied,
  312.                             encrypted_msg,
  313.                             message,
  314.                             &aes_state);

  315.     if(res!=CY_CRYPTOLITE_SUCCESS)
  316.     {
  317.         CY_ASSERT(0);
  318.     }
  319.     res = Cy_Cryptolite_Aes_Free(CRYPTOLITE,&aes_state);
  320.     if(res!=CY_CRYPTOLITE_SUCCESS)
  321.     {
  322.         CY_ASSERT(0);
  323.     }
  324.     printf("\r\nResult of Encryption:\r\n");
  325.     print_data((uint8_t*) encrypted_msg,
  326.                 aes_block_count * AES128_ENCRYPTION_LENGTH );

  327. }

  328. /*******************************************************************************
  329. * Function Name: decrypt_message
  330. ********************************************************************************
  331. * Summary: Function used to decrypt the message for cfb mode.
  332. *
  333. * Parameters:
  334. *  char * message - pointer to the message to be decrypted
  335. *  uint8_t size   - size of message to be decrypted.
  336. *
  337. * Return:
  338. *  void
  339. *
  340. *******************************************************************************/

  341. void decrypt_message_cfb(uint8_t* message, uint8_t size)
  342. {
  343.     cy_stc_cryptolite_aes_state_t aes_state;
  344.     cy_stc_cryptolite_aes_buffers_t aesBuffers;
  345.     uint8_t aes_block_count = 0;
  346.     cy_en_cryptolite_status_t res;
  347.     void* result;

  348.     aes_block_count =  (size % AES128_ENCRYPTION_LENGTH == 0) ?
  349.                        (size / AES128_ENCRYPTION_LENGTH)
  350.                        : (1 + size / AES128_ENCRYPTION_LENGTH);

  351.     /* Initializes the AES operation by setting key and key length */
  352.     res = Cy_Cryptolite_Aes_Init(CRYPTOLITE, aes_key, &aes_state, &aesBuffers);
  353.     if(res!=CY_CRYPTOLITE_SUCCESS)
  354.     {
  355.         CY_ASSERT(0);
  356.     }
  357.     /* Start decryption operation*/
  358.     result = memcpy(AesCfbIV_copied, AesCfbIV, sizeof(AesCfbIV));
  359.     if(result == NULL)
  360.     {
  361.        perror("Memory failed\r\n");
  362.     }
  363.     res = Cy_Cryptolite_Aes_Cfb(CRYPTOLITE,
  364.                             CY_CRYPTOLITE_DECRYPT,
  365.                             aes_block_count * AES128_ENCRYPTION_LENGTH,
  366.                             AesCfbIV_copied,
  367.                             decrypted_msg,
  368.                             encrypted_msg,
  369.                             &aes_state);
  370.     if(res!=CY_CRYPTOLITE_SUCCESS)
  371.         {
  372.             CY_ASSERT(0);
  373.         }
  374.     res = Cy_Cryptolite_Aes_Free(CRYPTOLITE,&aes_state);
  375.     if(res!=CY_CRYPTOLITE_SUCCESS)
  376.         {
  377.             CY_ASSERT(0);
  378.         }
  379.     decrypted_msg[size]='\0';
  380.     /* Print the decrypted message on the UART terminal */
  381.     printf("\r\nResult of Decryption:\r\n\n");
  382.     printf("%s", decrypted_msg);

  383. }

  384. /*******************************************************************************
  385. * Function Name: encrypt_message_cfb
  386. ********************************************************************************
  387. * Summary: Function used to encrypt the message through ctr mode.
  388. *
  389. * Parameters:
  390. *  char * message - pointer to the message to be encrypted
  391. *  uint8_t size   - size of message to be encrypted.
  392. *
  393. * Return:
  394. *  void
  395. *
  396. *******************************************************************************/

  397. void encrypt_message_ctr(uint8_t* message, uint8_t size)
  398. {
  399.     uint32_t srcOffset;
  400.     cy_stc_cryptolite_aes_state_t aes_state;
  401.     cy_stc_cryptolite_aes_buffers_t aesBuffers;
  402.     uint8_t aes_block_count = 0;
  403.     cy_en_cryptolite_status_t res;
  404.     void* result;

  405.     aes_block_count =  (size % AES128_ENCRYPTION_LENGTH == 0) ?
  406.                        (size / AES128_ENCRYPTION_LENGTH)
  407.                        : (1 + size / AES128_ENCRYPTION_LENGTH);
  408.     /* Initializes the AES operation by setting key and key length */
  409.      res = Cy_Cryptolite_Aes_Init(CRYPTOLITE, aes_key, &aes_state, &aesBuffers);
  410.      if(res!=CY_CRYPTOLITE_SUCCESS)
  411.      {
  412.        CY_ASSERT(0);
  413.      }

  414.      srcOffset = 0;
  415.      result = memcpy(AesCtrIV_copied, AesCtrIV, sizeof(AesCtrIV));
  416.      if(result == NULL)
  417.      {
  418.        perror("Memory failed\r\n");
  419.      }
  420.      res = Cy_Cryptolite_Aes_Ctr( CRYPTOLITE,
  421.                             aes_block_count * AES128_ENCRYPTION_LENGTH,
  422.                             &srcOffset,
  423.                             AesCtrIV_copied,
  424.                             encrypted_msg,
  425.                             message,
  426.                             &aes_state);
  427.      if(res!=CY_CRYPTOLITE_SUCCESS)
  428.      {
  429.        CY_ASSERT(0);
  430.      }
  431.      res = Cy_Cryptolite_Aes_Free(CRYPTOLITE,&aes_state);
  432.      if(res!=CY_CRYPTOLITE_SUCCESS)
  433.      {
  434.        CY_ASSERT(0);
  435.      }
  436.      printf("\r\nResult of Encryption:\r\n");
  437.      print_data((uint8_t*) encrypted_msg,
  438.                 aes_block_count * AES128_ENCRYPTION_LENGTH );

  439. }

  440. /*******************************************************************************
  441. * Function Name: decrypt_message
  442. ********************************************************************************
  443. * Summary: Function used to decrypt the message for ctr mode.
  444. *
  445. * Parameters:
  446. *  char * message - pointer to the message to be decrypted
  447. *  uint8_t size   - size of message to be decrypted.
  448. *
  449. * Return:
  450. *  void
  451. *
  452. *******************************************************************************/

  453. void decrypt_message_ctr(uint8_t* message, uint8_t size)
  454. {
  455.     uint32_t srcOffset;
  456.     cy_stc_cryptolite_aes_state_t aes_state;
  457.     cy_stc_cryptolite_aes_buffers_t aesBuffers;
  458.     uint8_t aes_block_count = 0;
  459.     cy_en_cryptolite_status_t res;
  460.     void* result;
  461.     aes_block_count =  (size % AES128_ENCRYPTION_LENGTH == 0) ?
  462.                        (size / AES128_ENCRYPTION_LENGTH)
  463.                        : (1 + size / AES128_ENCRYPTION_LENGTH);

  464.     /* Initializes the AES operation by setting key and key length */
  465.     res = Cy_Cryptolite_Aes_Init(CRYPTOLITE, aes_key, &aes_state, &aesBuffers);
  466.     if(res!=CY_CRYPTOLITE_SUCCESS)
  467.     {
  468.         CY_ASSERT(0);
  469.     }
  470.     srcOffset = 0;
  471.     /* Start decryption operation*/
  472.     result = memcpy(AesCtrIV_copied, AesCtrIV, sizeof(AesCtrIV));
  473.     if(result == NULL)
  474.     {
  475.         perror("Memory failed\r\n");
  476.     }
  477.     res = Cy_Cryptolite_Aes_Ctr(  CRYPTOLITE,
  478.                             aes_block_count * AES128_ENCRYPTION_LENGTH,
  479.                             &srcOffset,
  480.                             AesCtrIV_copied,
  481.                             decrypted_msg,
  482.                             encrypted_msg,
  483.                             &aes_state);
  484.     if(res!=CY_CRYPTOLITE_SUCCESS)
  485.     {
  486.         CY_ASSERT(0);
  487.     }
  488.     res = Cy_Cryptolite_Aes_Free(CRYPTOLITE,&aes_state);
  489.     if(res!=CY_CRYPTOLITE_SUCCESS)
  490.     {
  491.         CY_ASSERT(0);
  492.     }
  493.     decrypted_msg[size]='\0';
  494.     /* Print the decrypted message on the UART terminal */
  495.     printf("\r\nResult of Decryption:\r\n\n");
  496.     printf("%s", decrypted_msg);

  497. }

  498. /* [] END OF FILE */
运行结果



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:项目经理
简介:资深嵌入式开发工程师

104

主题

191

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部