← 返回

DarkneTZ

TEE 安全推理框架 • 2026年3月5日

项目概述

DarkneTZ 是一个基于 OP-TEE 的神经网络安全推理框架,实现了模型分割和内存保护。支持分类器训练和推理,将指定层加载入 TEE (可信执行环境) 以保护模型隐私和安全性。

代码修复

由于 DarkneTZ 项目较老,存在一些代码语法问题需要处理。以下列出所需的修改:

1. classifier.c 文件修改

文件路径:optee_examples/darknetz/host/examples/classifier.c

修改内容:在第 192 行和 777 行修改为:

char output_dir[80];

2. darknet.c 文件修改

文件路径:optee_examples/darknetz/host/examples/darknet.c

修改内容

  • 在第 5 行下增加一行:#include <darknet.h>
  • 在第 408 行左右进行修改,将 return 0 改为 return
if(argc < 2){
    fprintf(stderr, "usage: %s <function>\n", argv[0]);
    return;        // 从 return 0 修改为 return
}

3. convolutional_layer.c 文件修改

文件路径:optee_examples/darknetz/host/src/convolutional_layer.c

修改内容:在第 475 行进行修改:

unsigned int debug_num = 0;

4. darknet.h 文件修改

文件路径:optee_examples/darknetz/host/include/darknet.h

修改内容:在第 7 行增加如下声明:

void darknet_main(int argc, char **argv);

5. mnist_lenet.cfg 文件修改

文件路径:out-br/target/root/cfg/mnist_lenet.cfg

修改内容:更新网络配置文件如下:

[net]
# batch=100
batch=10
subdivisions=1
height=28
width=28
channels=3
momentum=0.9
decay=0.00005
max_crop=28

learning_rate=0.01
policy=poly
power=4
max_batches=100
# max_batches=10000

angle=1
hue=1
saturation=1
exposure=1
aspect=1

[convolutional]
filters=6
size=5
stride=1
pad=1
activation=relu

[maxpool]
size=2
stride=2

[convolutional]
filters=6
size=5
stride=1
pad=1
activation=relu

[maxpool]
size=2
stride=2

[connected]
output=120
activation=relu

[dropout]
probability=.8

[connected]
output=84
activation=relu

[dropout]
probability=.8

[connected]
output=10
activation=linear

[softmax]
groups=1

[cost]
type=sse

编译步骤

完成上述修改后,进行编译步骤如下:

cd ~/File/optee/build
make run -j16

该命令将进入 OP-TEE 构建目录,并使用 16 个并行线程进行编译和运行。

核心特性

  • TEE 集成:基于 OP-TEE 框架实现可信执行环境
  • 模型分割:支持指定层数范围保存在 TEE 中
  • 安全推理:保护模型参数不被恶意访问
  • MNIST 示例:完整的手写数字识别实现
  • 前后向传播:TEE 与 REE 间的完整训练流程

技术栈

  • OP-TEE - 开放式可信执行环境
  • C 语言 - 核心实现
  • 神经网络 - 深度学习框架
  • MNIST - 数据集标准

环境测试

OP-TEE 环境测试(xtest):

OP-TEE 环境测试结果

DarkneTZ 项目分类器训练(MNIST 手写数字数据集)

分类器训练结果

推理测试

推理测试结果

DarkneTZ 项目学习

以分类器(classifier)为例进行详细分析。

模型架构

cfg/mnist_lenet.cfg 为 MNIST 卷积神经网络模型架构,含若干节(section),由 [ ] 标识,每节有若干配置项(option),由键值对表示。

  • 第一节必为 [net] 或 [network],包含神经网络的总体配置,如每批次训练数量(batch),学习率(learning_rate)等。
  • 之后各节为各层神经网络配置,如 [convolutional] 卷积层,[maxpool] 最大池化层,[connected] 全连接层,[dropout] 随机丢弃层,[softmax] 层等,各层的节下配置了输出维度(output),卷积核大小(size),激活函数(activation)等具体架构参数。

数据集

cfg/mnist.dataset 含有分类器(classifier)的训练数据默认配置,如 10 类(classes)即 0 到 9,训练数据列表路径(train),标签列表路径(labels)和名称列表路径(names),topK(top)等。

分类器的训练数据集为 MNIST 手写数字训练数据集,图像数据存储在 data/mnist/images 目录下,命名格式为 <type>_<index>_<label>.png,如 t_00002_c4.png 表示 train(训练)数据集的第 00002 张图片,图像为数字 4。

推测 valid 为交叉验证(cross validation)数据集,test 为测试数据集,但相应目录下可能存在数据缺失情况。

模型训练

通过命令进行模型训练:

darknetp classifier train -pp_start 4 -pp_end 10 cfg/mnist.dataset cfg/mnist_lenet.cfg

使用数据集 mnist.dataset 训练 mnist_lenet.cfg 架构的卷积神经网络分类器模型,其中第 4 层至第 10 层存入 TEE 以保护。

train_classifier

  • 首先通过配置文件加载网络,分配空间,根据配置进行参数的初始化,并将分割点间的层加载入 TEE。
  • 随后进行加载数据,通过数据加载线程每次并发加载 net->batch * net->subdivisions * ngpus(每批次数量*分支*gpu数量)张图片,存入缓冲区 buffer(train)。

train_network

通过加载的数据训练神经网络。TEE 与 CEE 通过 net_truth_CA 通信,通过 train_network_datum 进行前向传播->反向传播->更新网络参数,然后返回损失。

forward_network(前向传播)

根据各层类型选择相应函数在各层进行前向传播:

  • Dropout 层:置零输入或随机缩放以防止过拟合。
  • Connected 层:进行矩阵计算或归一化。
  • Convolutional 层:将图像转为列向量,然后分组卷积矩阵运算。
  • Maxpool 层:提取区域内最大值实现降维。
  • Cost 层:位于最后,根据损失函数类型计算与真实值的损失,示例为 sse(均方误差)。

各层推理结果 output 通过神经网络 net 的 input 传递给下一层,softmax 层为实际输出层,计算图像识别各数字概率。

对于 TEE 中的层,通过函数 forward_network_CA 以在 TEE 中前向传播,然后通过 forward_network_back_CA 接收 TEE 中神经网络的推理结果。

Cost 层的输出可用于反向传播调整参数。最后计算成本,calc_network_cost 将各层成本平均值存入 net.cost。

backward_network(反向传播)

根据各层类型,激活函数类型,在各层进行反向传播,梯度计算。

在 TEE 与 REE 分界处,使用:

  • backward_network_back_CA_addidion
  • backward_network_back_CA
  • backward_network_CA

函数向 TA 传入输入,在 TEE 执行反向传播;使用 backward_network_CA_addidion 函数从 TA 传回结果,在 REE 继续反向传播。

update_network(更新参数)

需最后再同时更新所有参数而非过程中更新(梯度下降法需要)。

模型推理

通过命令进行推理:

darknetp classifier predict -pp_start 4 -pp_end 10 cfg/mnist.dataset cfg/mnist_lenet.cfg tmp/backup/mnist_lenet.weights

加载训练的权重 mnist_lenet.weights 进行推理,其中 4 至 10 层于 TEE 中。

在推理时的输出 top 可能出现乱码:

推理输出乱码示例

参考 GitHub Issue #37 修改 predict_classifier 函数的 free 位置。

predict_classifier

加载网络配置和权重,解析参数,加载并处理需要推理的图片,随后调用 network_predict 进行预测,输出 top 个结果。

network_predict

进行前向传播 forward_network,并获取结果,当最后层在 TEE 时通过 net_output_return_CA 函数获取结果。

TA 与 CA 的通信

除一般性的会话和上下文的初始化和销毁之外,TA 与 CA 间的通信体现在网络加载、前向传播与反向传播过程中,在 DarkneTZ 项目中 TA 与 CA 交互相关函数名称含有标识,在 CA 的部分标识"CA",在 TA 的部分标识"TA"。

同一函数在 TA 与 CA 内部的不同版本执行相似操作,分隔点由 OP-TEE 命令和共享内存传参,安全性由 OP-TEE 系统机制保证。

网络加载

  • Load_network -> parse_network_cfg -> make_network 在 CA 中加载网络
  • Parse_network_cfg -> parse_net_options -> make_network_CA 在 TA 中加载分隔点间的网络

传播过程

  • 在分隔点从 CA 传播入 TA 时,构建参数内存空间并使用 OP-TEE 命令传入 TA
  • 在分隔点从 TA 传播至 CA 时,构建共享内存空间并使用 OP-TEE 命令从 TA 传出

相关链接

GitHub 仓库 · 相关Issue