# libkcapi

`libkcapi` 是 kernel 推荐的用户层接口，X5 支持使用 `libkcapi` 库调用以下算法类型：`hash` 、`cipher` 以及 `aead`。下面对 libkcapi API 的介绍摘录自 `kcapi.h`，详细内容可到下面链接中了解。

kcapi官网： [https://www.chronox.de/libkcapi/libkcapi.html](https://www.chronox.de/libkcapi/libkcapi.html)

kcapi git： [https://github.com/smuellerDD/libkcapi](https://github.com/smuellerDD/libkcapi)

kernel介绍： [https://www.kernel.org/doc/html/v5.10/crypto/userspace-if.html](https://www.kernel.org/doc/html/v5.10/crypto/userspace-if.html)

## 对称算法

对称算法通过调用libkcapi库，完成加解密操作。头文件kcapi.h，版本为1.1.5。

### API参考

[kcapi_cipher_init](#kcapi_cipher_init) : 初始化接口  
[kcapi_cipher_destroy](#kcapi_cipher_destroy) : 释放资源接口  
[kcapi_cipher_setkey](#kcapi_cipher_setkey) : 设置密钥接口  
[kcapi_cipher_encrypt](#kcapi_cipher_encrypt) : 加密接口  
[kcapi_cipher_decrypt](#kcapi_cipher_decrypt) : 解密接口  

### 接口说明

<span id="kcapi_cipher_init"/> </span>

#### kcapi_cipher_init

**【函数声明】**：

```C
int kcapi_cipher_init(struct kcapi_handle **handle, const char *ciphername,
        uint32_t flags);
```

**【功能描述】**：

用于初始化一个 cipher 上下文

**【参数描述】**：

- [OUT] struct kcapi_handle **handle : 指向 kcapi_handle 结构体的指针，表示一个加密算法的实例
- [OUT] char *ciphername : cipher 名称
- [IN] uint32_t flags : 指定 cipher 句柄的类型的标志

**【返回值】**：

- 成功，返回 0
- 失败：非零异常值
  - -ENOENT - 加密算法不可用
  - -EOPNOTSUPP - AF_ALG family 不可用
  - -EINVAL - accept syscall 调用失败
  - -ENOMEM - 无法创建加密句柄

<span id="kcapi_cipher_destroy"/> </span>

#### kcapi_cipher_destroy

**【函数声明】**：

```C
void kcapi_cipher_destroy(struct kcapi_handle *handle);
```

**【功能描述】**：

关闭加密句柄，并释放资源

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄

**【返回值】**：

无

<span id="kcapi_cipher_setkey"/> </span>

#### kcapi_cipher_setkey

**【函数声明】**：

```C
int kcapi_cipher_setkey(struct kcapi_handle *handle,
   const uint8_t *key, uint32_t keylen);
```

**【功能描述】**：

设置加解密操作所需的密钥

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄
- [IN] uint8_t *key : 密钥 buffer
- [IN] uint32_t keylen : 密钥长度

**【返回值】**：

- 成功，返回 0
- 失败：非零

<span id="kcapi_cipher_encrypt"/> </span>

#### kcapi_cipher_encrypt

**【函数声明】**：

```C
int32_t kcapi_cipher_encrypt(struct kcapi_handle *handle,
        const uint8_t *in, uint32_t inlen,
        const uint8_t *iv,
        uint8_t *out, uint32_t outlen, int access);
```

**【功能描述】**：

执行加密操作

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄
- [IN] uint8_t *in : 明文 buffer
- [IN] uint32_t inlen : 明文长度
- [IN] uint8_t *iv : 保存 iv 的 buffer
- [OUT] uint8_t *out : 密文 buffer
- [OUT] uint32_t outlen : 密文长度
- [INT] int access : 内核访问类型
  - KCAPI_ACCESS_HEURISTIC - 使用内部启发式方法以实现最快的内核访问
  - KCAPI_ACCESS_VMSPLICE - 通过 vmsplice 访问
  - KCAPI_ACCESS_SENDMSG - 通过 sendmsg 访问

**【返回值】**：

- 加密成功的字节数

<span id="kcapi_cipher_decrypt"/> </span>

#### kcapi_cipher_decrypt

**【函数声明】**：

```C
int32_t kcapi_cipher_decrypt(struct kcapi_handle *handle,
        const uint8_t *in, uint32_t inlen,
        const uint8_t *iv,
        uint8_t *out, uint32_t outlen, int access);
```

**【功能描述】**：

执行解密操作

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄
- [IN] uint8_t *in : 密文 buffer
- [IN] uint32_t inlen : 密文长度
- [IN] uint8_t *iv : 保存 iv 的 buffer
- [OUT] uint8_t *out : 明文 buffer
- [OUT] uint32_t outlen : 明文长度
- [INT] int access : 内核访问类型
  - KCAPI_ACCESS_HEURISTIC - 使用内部启发式方法以实现最快的内核访问
  - KCAPI_ACCESS_VMSPLICE - 通过 vmsplice 访问
  - KCAPI_ACCESS_SENDMSG - 通过 sendmsg 访问

**【返回值】**：

- 解密成功的字节数

### 使用示例

```C
ssize_t test_cipher(const char *name,
                const uint8_t *key, uint32_t keylen,
                const uint8_t *in, size_t inlen,
                const uint8_t *iv,
                uint8_t *out, size_t outlen)
{
        struct kcapi_handle *handle;
        ssize_t ret = kcapi_cipher_init(&handle, name, 0);
        if (ret)
                return ret;
        ret = kcapi_cipher_setkey(handle, key, keylen);
        if (ret)
                goto out;
        ret = kcapi_cipher_encrypt(handle, in, inlen, iv, out, outlen, 0);
out:
        kcapi_cipher_destroy(handle);
        return ret;
}
```

## HASH算法

HASH算法通过调用libkcapi库，完成计算hash操作。头文件kcapi.h，版本为1.1.5。

### API参考

[kcapi_md_init](#kcapi_md_init) : 初始化接口  
[kcapi_md_destroy](#kcapi_md_destroy) : 释放资源接口  
[kcapi_md_update](#kcapi_md_update) : 消息摘要 update 接口  
[kcapi_md_final](#kcapi_md_final) : 消息摘要结束接口  

<span id="kcapi_md_init"/> </span>

#### kcapi_md_init

**【函数声明】**：

```C
int kcapi_md_init(struct kcapi_handle **handle, const char *ciphername,
    uint32_t flags);
```

**【功能描述】**：

用于初始化一个 cipher 上下文

**【参数描述】**：

- [OUT] struct kcapi_handle **handle : 指向 kcapi_handle 结构体的指针，表示一个加密算法的实例
- [OUT] char *ciphername : cipher 名称
- [IN] uint32_t flags : 指定 cipher 句柄的类型的标志

**【返回值】**：

- 成功，返回 0
- 失败：非零异常值
  - -ENOENT - 加密算法不可用
  - -EOPNOTSUPP - AF_ALG family 不可用
  - -EINVAL - accept syscall 调用失败
  - -ENOMEM - 无法创建加密句柄

<span id="kcapi_md_destroy"/> </span>

#### kcapi_md_destroy

**【函数声明】**：

```C
void kcapi_md_destroy(struct kcapi_handle *handle);
```

**【功能描述】**：

关闭 cipher 句柄，并释放资源

**【参数描述】**：

- [IN] struct kcapi_handle *handle : cipher 句柄

**【返回值】**：

无

<span id="kcapi_md_update"/> </span>

#### kcapi_md_update

**【函数声明】**：

```C
int32_t kcapi_md_update(struct kcapi_handle *handle,
   const uint8_t *buffer, uint32_t len);
```

**【功能描述】**：

更新消息摘要

**【参数描述】**：

- [IN] struct kcapi_handle *handle : cipher 句柄
- [IN] uint8_t *buffer : 添加到计算消息摘要的数据 buffer
- [IN] uint32_t len : 数据 buffer 长度

**【返回值】**：

- 成功，返回 0
- 失败：非零

<span id="kcapi_md_final"/> </span>

#### kcapi_md_final

**【函数声明】**：

```C
int32_t kcapi_md_final(struct kcapi_handle *handle,
         uint8_t *buffer, uint32_t len);
```

**【功能描述】**：

更新消息摘要

**【参数描述】**：

- [IN] struct kcapi_handle *handle : cipher 句柄
- [OUT] uint8_t *buffer : 消息摘要 buffer
- [IN] uint32_t len : buffer 长度

**【返回值】**：

- 成功计算消息摘要的长度

### 使用示例

```
int test_hash(const char *name,
                const uint8_t *in, uint32_t inlen,
                uint8_t *out, uint32_t outlen)
{
        struct kcapi_handle *handle;
        int32_t ret = kcapi_md_init(&handle, name, 0);
        if (ret)
                return ret;

        ret = kcapi_md_update(handle, in, inlen);
        if (0 > ret)
                goto out;
        ret = kcapi_md_final(handle, out, outlen);
        if (0 > ret)
                goto out;
out:
        kcapi_md_destroy(handle);
        return ret;
}
```

## AEAD算法

AEAD算法通过调用libkcapi库，完成加解密操作。头文件kcapi.h，版本为1.1.5。

### API参考

[kcapi_aead_init](#kcapi_aead_init) : 初始化接口  
[kcapi_aead_destroy](#kcapi_aead_destroy) : 释放资源接口  
[kcapi_aead_setkey](#kcapi_aead_setkey) : 设置密钥接口  
[kcapi_aead_settaglen](#kcapi_aead_settaglen) : 设置加密tag len接口  
[kcapi_aead_setassoclen](#kcapi_aead_setassoclen) : 设置assoclen接口  
[kcapi_aead_encrypt](#kcapi_aead_encrypt) : 加密接口  
[kcapi_aead_decrypt](#kcapi_aead_decrypt) : 解密接口  

<span id="kcapi_aead_init"/> </span>

#### kcapi_aead_init

**【函数声明】**：

```C
int kcapi_aead_init(struct kcapi_handle **handle, const char *ciphername,
    uint32_t flags);
```

**【功能描述】**：

用于初始化一个 cipher 上下文

**【参数描述】**：

- [OUT] struct kcapi_handle **handle : 指向 kcapi_handle 结构体的指针，表示一个加密算法的实例
- [OUT] char *ciphername : cipher 名称
- [IN] uint32_t flags : 指定 cipher 句柄的类型的标志

**【返回值】**：

- 成功，返回 0
- 失败：非零异常值
  - -ENOENT - 加密算法不可用
  - -EOPNOTSUPP - AF_ALG family 不可用
  - -EINVAL - accept syscall 调用失败
  - -ENOMEM - 无法创建加密句柄

<span id="kcapi_aead_destroy"/> </span>

#### kcapi_aead_destroy

**【函数声明】**：

```C
void kcapi_aead_destroy(struct kcapi_handle *handle);
```

**【功能描述】**：

关闭 cipher 句柄，并释放资源

**【参数描述】**：

- [IN] struct kcapi_handle *handle : cipher 句柄

**【返回值】**：

无

<span id="kcapi_aead_setkey"/> </span>

#### kcapi_aead_setkey

**【函数声明】**：

```C
int kcapi_aead_setkey(struct kcapi_handle *handle,
        const uint8_t *key, uint32_t keylen);
```

**【功能描述】**：

设置加解密操作所需的密钥

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄
- [IN] uint8_t *key : 密钥 buffer
- [IN] uint32_t keylen : 密钥长度

**【返回值】**：

- 成功，返回 0
- 失败：非零

<span id="kcapi_aead_settaglen"/> </span>

#### kcapi_aead_settaglen

**【函数声明】**：

```C
int kcapi_aead_settaglen(struct kcapi_handle *handle, uint32_t taglen);
```

**【功能描述】**：

设置 aead 操作的授权 TAG 的长度

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄
- [IN] uint32_t taglen : 授权 TAG 的长度

**【返回值】**：

- 成功，返回 0
- 失败：非零

<span id="kcapi_aead_setassoclen"/> </span>

#### kcapi_aead_setassoclen

**【函数声明】**：

```C
void kcapi_aead_setassoclen(struct kcapi_handle *handle, uint32_t assoclen);
```

**【功能描述】**：

设置 aead 操作的关联数据的长度，关联数据不会被加密，但会参与身份验证

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄
- [IN] uint32_t assoclen : 授权 TAG 的长度

**【返回值】**：

- 成功，返回 0
- 失败：非零

<span id="kcapi_aead_encrypt"/> </span>

#### kcapi_aead_encrypt

**【函数声明】**：

```C
int32_t kcapi_aead_encrypt(struct kcapi_handle *handle,
      const uint8_t *in, uint32_t inlen,
      const uint8_t *iv,
      uint8_t *out, uint32_t outlen,
      int access);
```

**【功能描述】**：

执行加密操作

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄
- [IN] uint8_t *in : 明文 buffer
- [IN] uint32_t inlen : 明文长度
- [IN] uint8_t *iv : 保存 iv 的 buffer
- [OUT] uint8_t *out : 密文 buffer
- [OUT] uint32_t outlen : 密文长度
- [INT] int access : 内核访问类型
  - KCAPI_ACCESS_HEURISTIC - 使用内部启发式方法以实现最快的内核访问
  - KCAPI_ACCESS_VMSPLICE - 通过 vmsplice 访问
  - KCAPI_ACCESS_SENDMSG - 通过sendmsg 访问

**【返回值】**：

- 加密成功的字节数

<span id="kcapi_aead_decrypt"/> </span>

#### kcapi_aead_decrypt

**【函数声明】**：

```C
int32_t kcapi_aead_decrypt(struct kcapi_handle *handle,
      const uint8_t *in, uint32_t inlen,
      const uint8_t *iv,
      uint8_t *out, uint32_t outlen, int access);
```

**【功能描述】**：

执行解密操作

**【参数描述】**：

- [IN] struct kcapi_handle *handle : 加密句柄
- [IN] uint8_t *in : 密文 buffer
- [IN] uint32_t inlen : 密文长度
- [IN] uint8_t *iv : 保存 iv 的 buffer
- [OUT] uint8_t *out : 明文 buffer
- [OUT] uint32_t outlen : 明文长度
- [INT] int access : 内核访问类型
  - KCAPI_ACCESS_HEURISTIC - 使用内部启发式方法以实现最快的内核访问
  - KCAPI_ACCESS_VMSPLICE - 通过 vmsplice 访问
  - KCAPI_ACCESS_SENDMSG - 通过sendmsg 访问

**【返回值】**：

- 解密成功的字节数

### 使用示例

```
ssize_t test_aead(const char *name,
                const uint8_t *key, uint32_t keylen,
                const uint8_t *in, size_t inlen,
                const uint8_t *iv, uint32_t assoclen, uint32_t taglen,
                uint8_t *out, size_t outlen)
{
        struct kcapi_handle *handle;
        ssize_t ret = kcapi_aead_init(&handle, name, 0);
        if (ret)
                return ret;
        ret = kcapi_aead_settaglen(handle, taglen);
        if (ret)
                goto out;

        kcapi_aead_setassoclen(handle, assoclen);

        ret = kcapi_aead_setkey(handle, key, keylen);
        if (ret)
                goto out;

        ret = kcapi_aead_encrypt(handle, in, inlen, iv, out, outlen, 0);
out:
        kcapi_aead_destroy(handle);
        return ret;
}
```
