SM3 杂凑加速器

[English]

SM3(GM/T 0004-2012)是中国商用密码(SM)标准中的密码杂凑算法。它以 64 字节为分组读取消息,输出 256 位摘要,与 SHA-256 相当。在 ESP32-C5 上,SHA 加速器以硬件方式计算 SM3。

esp_sm3 API 是访问 SM3 硬件的唯一接口。Mbed TLS 和 PSA Crypto API 均不提供 SM3。

一次性摘要

当整条消息位于同一个缓冲区时,使用 esp_sm3()

#include "esp_sm3.h"

uint8_t digest[ESP_SM3_DIGEST_LEN];

esp_err_t err = esp_sm3(message, message_len, digest, sizeof(digest));
if (err != ESP_OK) {
    // 未写入摘要,请处理该错误。
}

流式摘要

当消息分多次到达时,使用上下文函数:

#include "esp_sm3.h"

uint8_t digest[ESP_SM3_DIGEST_LEN];
esp_sm3_ctx_handle_t ctx = NULL;

esp_err_t err = esp_sm3_create(&ctx);
if (err != ESP_OK) {
    return err;
}

err = esp_sm3_update(ctx, part1, part1_len);
if (err == ESP_OK) {
    err = esp_sm3_update(ctx, part2, part2_len);
}
if (err == ESP_OK) {
    err = esp_sm3_finish(ctx, digest, sizeof(digest));
}

esp_sm3_delete(ctx);

esp_sm3_create() 会分配上下文,并把句柄写入 ctx。如果该函数返回 ESP_ERR_NO_MEMESP_ERR_NOT_SUPPORTED,则向 ctx 写入 NULL。上下文是不透明的,应用程序不得读写其内容。

esp_sm3_delete() 会清除上下文中的消息字节和摘要状态,然后释放该上下文。调用之后句柄失效。如果应用程序不调用该函数,该上下文会一直占用内存。

请在调用 esp_sm3_finish() 之后调用 esp_sm3_delete()。中止操作时同样需要调用。

并发

esp_sm3_update()esp_sm3_finish() 会占用 SHA 外设。它们仅在硬件处理消息分组期间持有该外设,并在返回前释放。esp_sm3_create()esp_sm3_delete() 不会访问该外设。

只有当新增字节凑满至少一个 64 字节分组时,esp_sm3_update() 才会占用该外设。字节不足时,该函数只把它们复制到上下文中并返回。esp_sm3_finish() 总会占用该外设,因为填充会凑满最后一个分组。

因此,一个操作可以长时间保持打开状态,而不会给该外设的其他使用者带来开销。使用不同上下文的操作可以在不同任务中并行执行。

不要在两个任务中同时使用同一个上下文。

API 参考

Header File

  • components/esp_security/include/esp_sm3.h

  • This header file can be included with:

    #include "esp_sm3.h"
    
  • This header file is a part of the API provided by the esp_security component. To declare that your component depends on esp_security, add the following to your CMakeLists.txt:

    REQUIRES esp_security
    

    or

    PRIV_REQUIRES esp_security
    

Functions

esp_err_t esp_sm3_create(esp_sm3_ctx_handle_t *ctx)

Start a new SM3 operation.

The function allocates the context. Call esp_sm3_delete() to release it.

参数:

ctx -- [out] Receives the handle of the new context. The function writes NULL if it returns ESP_ERR_NO_MEM or ESP_ERR_NOT_SUPPORTED.

返回:

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG if ctx is NULL

  • ESP_ERR_NO_MEM if the allocation fails

  • ESP_ERR_NOT_SUPPORTED if an eFuse disables the SM crypto functions

esp_err_t esp_sm3_update(esp_sm3_ctx_handle_t ctx, const void *input, size_t ilen)

Add message bytes to an SM3 operation.

Call this function as many times as necessary. The function acquires the SHA peripheral only when the new bytes complete at least one 64-byte block. It releases the peripheral before it returns.

参数:
  • ctx -- Context from esp_sm3_create().

  • input -- Message bytes. Can be NULL if ilen is 0.

  • ilen -- Number of message bytes.

返回:

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG if ctx is NULL, or if input is NULL and ilen is not 0

  • ESP_ERR_NOT_SUPPORTED if an eFuse disables the SM crypto functions

esp_err_t esp_sm3_finish(esp_sm3_ctx_handle_t ctx, uint8_t *output, size_t olen)

Complete an SM3 operation and read the digest.

The function always acquires the SHA peripheral, because the padding completes the last message block. It releases the peripheral before it returns.

参数:
  • ctx -- Context from esp_sm3_create().

  • output -- Buffer for the digest.

  • olen -- Size of output in bytes. Must be ESP_SM3_DIGEST_LEN or more.

返回:

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG if ctx or output is NULL

  • ESP_ERR_INVALID_SIZE if olen is too small

  • ESP_ERR_NOT_SUPPORTED if an eFuse disables the SM crypto functions

void esp_sm3_delete(esp_sm3_ctx_handle_t ctx)

Erase and release an SM3 context.

The function erases the message bytes and the digest state. Then it frees the context. Call this function after esp_sm3_finish(), and also to abandon an operation. The handle is not valid after the call. If you do not call this function, the context stays allocated.

参数:

ctx -- Context from esp_sm3_create(). The function accepts NULL.

esp_err_t esp_sm3(const void *input, size_t ilen, uint8_t *output, size_t olen)

Compute the SM3 digest of one buffer.

参数:
  • input -- Message bytes. Can be NULL if ilen is 0.

  • ilen -- Number of message bytes.

  • output -- Buffer for the digest.

  • olen -- Size of output in bytes. Must be ESP_SM3_DIGEST_LEN or more.

返回:

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG if output is NULL, or if input is NULL and ilen is not 0

  • ESP_ERR_INVALID_SIZE if olen is too small

  • ESP_ERR_NOT_SUPPORTED if an eFuse disables the SM crypto functions

Macros

ESP_SM3_DIGEST_LEN

Length of an SM3 digest in bytes.

ESP_SM3_BLOCK_LEN

Size of an SM3 message block in bytes.

Type Definitions

typedef struct esp_sm3_ctx_s *esp_sm3_ctx_handle_t

Handle of one SM3 operation.

esp_sm3_create() allocates the context. esp_sm3_delete() releases it. Do not read or write the context.


此文档对您有帮助吗?