00 TrustZone mimarisi
ARM TrustZone, tek bir SoC üzerinde iki tamamen ayrı çalışma ortamı oluşturur: Secure World ve Normal World. Donanım, bellek ve IO kaynaklarını bu iki dünya arasında yalıtır.
İki dünyanın yapısı
┌───────────────────────┐ ┌───────────────────────┐
│ NORMAL WORLD │ │ SECURE WORLD │
│ │ │ │
│ Linux Kernel (EL1) │ │ OP-TEE OS (S-EL1) │
│ User apps (EL0) │ │ Trusted Apps (S-EL0) │
│ KVM/Xen (EL2) │ │ │
└──────────┬────────────┘ └────────────┬───────────┘
│ SMC │ SMC
└──────────┬───────────────────┘
▼
Secure Monitor — EL3
(TF-A BL31 — daima çalışır)
NS bit: SCR_EL3.NS
│
┌───────▼────────┐
│ SoC Hardware │
│ TZC-400 DRAM │
│ GIC (FIQ yön.) │
│ Secure SRAM │
└────────────────┘
Secure/Non-Secure ayrımı
| Kaynak | Normal World | Secure World |
|---|---|---|
| DRAM bölgesi | NS DRAM (Linux heap, stack) | Secure DRAM (OP-TEE heap, TA stack) |
| SRAM | Erişim yok | Secure SRAM — hızlı erişim |
| Periferler | UART, USB, Ethernet vb. | Güvenli UART, OTP, crypto HW |
| Kesmeler | IRQ (GIC NS interrupt) | FIQ (GIC Secure interrupt) |
| Cache | NS cache satırları | Secure cache satırları (TrustZone cache) |
Monitor modu ve geçiş
Normal World bir TEE servisi istediğinde smc #0 komutu çalıştırır. EL3'teki Secure Monitor (TF-A BL31) çağrıyı alır, NS bit'i sıfırlar ve S-EL1'deki OP-TEE'ye geçiş yapar. OP-TEE işi bitirdiğinde tekrar EL3 üzerinden Normal World'e dönülür.
/* Normal World çağrısı — libteec içindeki SMC wrapper */
static uint32_t smc(uint32_t func_id, uint32_t a1, uint32_t a2,
uint32_t a3, uint32_t a4, uint32_t a5,
uint32_t a6, struct smc_param *param)
{
/* x0 = func_id (OPTEE_SMC_CALL_WITH_RPC_ARG)
x1-x6 = argümanlar
Sonuç x0-x3'te dönüyor */
asm volatile(
"mov x0, %[fid]\n"
"mov x1, %[a1]\n"
"mov x2, %[a2]\n"
"smc #0\n"
"str x0, %[ret0]\n"
: [ret0] "=m" (param->a0)
: [fid] "r" (func_id), [a1] "r" (a1), [a2] "r" (a2)
: "x0", "x1", "x2", "memory"
);
return param->a0;
}
01 OP-TEE OS yapısı
OP-TEE, GlobalPlatform TEE Core API standardını implement eden açık kaynaklı bir Trusted Operating System'dir; Linaro tarafından geliştirilen proje TF-A ile entegre çalışır.
Kaynak ağacı
optee_os/
├── core/
│ ├── arch/arm/ # ARM-spesifik: entry, exception vektörleri, MMU
│ │ ├── sm/ # Secure Monitor interface (EL3 ↔ S-EL1)
│ │ ├── plat-*/ # Platform portları (stm32mp1, vexpress, rpi3 vb.)
│ │ └── tee/ # TEE çekirdek servisleri
│ ├── drivers/ # Crypto HW, UART, RNG, RPMB sürücüleri
│ ├── kernel/ # Thread scheduler, mutex, IPC
│ ├── mm/ # Güvenli bellek yönetimi, mobj
│ └── tee/ # GP TEE Core API impl: crypto, storage, time
├── lib/
│ ├── libutee/ # TA tarafı API (Trusted Applications bağlanır)
│ └── libutils/ # String, math yardımcıları
├── ta/ # Yerleşik TA'lar: pkcs11, device_id, gprof
└── mk/ # Derleme sistemi Makefile'ları
Thread modeli
OP-TEE, Normal World'den gelen her SMC çağrısı için bir S-EL1 thread tahsis eder. Thread sayısı CFG_NUM_THREADS ile sınırlandırılır; genellikle çekirdek sayısına eşittir. Her TA çağrısı ayrı thread bağlamında çalışır.
OP-TEE supplicant
Normal World'de çalışan tee-supplicant daemon'u, Trusted OS'un dosya sistemi, RPC ve RPMB erişimlerini karşılar. OP-TEE'nin disk dosyalarına erişmesi için gereklidir; sistem açılışında otomatik başlamalıdır.
# systemd servisi
# /lib/systemd/system/tee-supplicant.service
[Unit]
Description=TEE Supplicant Daemon
After=local-fs.target
[Service]
ExecStart=/usr/sbin/tee-supplicant
Restart=on-failure
RestartSec=1
[Install]
WantedBy=multi-user.target
02 Trusted Application anatomisi
Trusted Application (TA), Secure World'de S-EL0 seviyesinde çalışan, GlobalPlatform TEE Internal Core API'yi kullanan paylaşımlı kütüphane biçiminde ELF dosyasıdır.
TA giriş noktaları
Her TA beş zorunlu giriş noktası (entry point) implement etmek zorundadır. OP-TEE bu fonksiyonları TA yaşam döngüsü boyunca çağırır.
/* ta/hello_world/hello_world_ta.c */
#include <tee_internal_api.h>
#include <tee_internal_api_extensions.h>
#include "hello_world_ta.h"
/* TA ilk yüklendiğinde — instance oluştur */
TEE_Result TA_CreateEntryPoint(void)
{
DMSG("TA_CreateEntryPoint cagrildi");
/* Global kaynakları tahsis et */
return TEE_SUCCESS;
}
/* TA kaldırılmadan önce */
void TA_DestroyEntryPoint(void)
{
DMSG("TA_DestroyEntryPoint cagrildi");
/* Global kaynakları serbest bırak */
}
/* Normal World bir session açtığında */
TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types,
TEE_Param params[4],
void **sess_ctx)
{
uint32_t exp_param_types = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE);
if (param_types != exp_param_types)
return TEE_ERROR_BAD_PARAMETERS;
/* Session'a özel bağlam tahsis et */
struct session_ctx *ctx = TEE_Malloc(sizeof(*ctx), 0);
if (!ctx) return TEE_ERROR_OUT_OF_MEMORY;
*sess_ctx = ctx;
return TEE_SUCCESS;
}
/* Session kapatılırken */
void TA_CloseSessionEntryPoint(void *sess_ctx)
{
struct session_ctx *ctx = sess_ctx;
TEE_Free(ctx);
}
/* Normal World komut çağırdığında — ana iş burada */
TEE_Result TA_InvokeCommandEntryPoint(void *sess_ctx,
uint32_t cmd_id,
uint32_t param_types,
TEE_Param params[4])
{
switch (cmd_id) {
case TA_HELLO_WORLD_CMD_INC_VALUE:
return inc_value(param_types, params);
case TA_HELLO_WORLD_CMD_DEC_VALUE:
return dec_value(param_types, params);
default:
EMSG("Bilinmeyen komut: 0x%x", cmd_id);
return TEE_ERROR_NOT_SUPPORTED;
}
}
TA UUID ve manifest
/* ta/hello_world/Android.mk veya Makefile içindeki UUID */
/* Her TA eşsiz bir UUID ile tanımlanır */
/* hello_world_ta.h */
#define TA_HELLO_WORLD_UUID \
{ 0x8aaaf200, 0x2450, 0x11e4, \
{ 0xab, 0xe2, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }
#define TA_HELLO_WORLD_CMD_INC_VALUE 0
#define TA_HELLO_WORLD_CMD_DEC_VALUE 1
/* user_ta_header_defines.h — TA özellikleri */
#define TA_UUID TA_HELLO_WORLD_UUID
#define TA_FLAGS (TA_FLAG_EXEC_DDR | TA_FLAG_SINGLE_INSTANCE)
#define TA_STACK_SIZE (4 * 1024) /* 4 KB */
#define TA_DATA_SIZE (32 * 1024) /* 32 KB heap */
#define TA_VERSION "1.0"
#define TA_DESCRIPTION "Hello World Ornek TA"
TA imzalama
Production ortamında TA'lar, OP-TEE'nin güvendiği bir anahtar çiftiyle imzalanmalıdır. Development modunda test anahtar çifti kullanılır; CFG_TA_KEY_SETUP değişkeniyle kontrol edilir.
# TA imzalama scripti (scripts/sign_encrypt.py)
python3 scripts/sign_encrypt.py \
--uuid 8aaaf200-2450-11e4-abe2-0002a5d5c51b \
--key keys/default_ta.pem \
--in hello_world.stripped.elf \
--out 8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta
# İmzalanan .ta dosyası rootfs'e kopyalanır:
# /lib/optee_armtz/8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta
03 TEE Client API — Normal World tarafı
libteec, Normal World uygulamalarının OP-TEE ile iletişim kurması için GlobalPlatform TEE Client API standardını implement eder; /dev/tee0 üzerinden çalışır.
Bağlantı akışı
Normal World uygulama
│
│ TEEC_InitializeContext()
▼
TEE Context ──── /dev/tee0 ────> OP-TEE driver (kernel)
│ │
│ TEEC_OpenSession() │ SMC
▼ ▼
TEE Session <──────────────────> OP-TEE OS (S-EL1)
│ │
│ TEEC_InvokeCommand() │ TA_InvokeCommandEntryPoint()
▼ ▼
Sonuç & çıktı parametreler <──── TA işlem sonucu
Tam bir istemci örneği
/* host/main.c — Normal World istemci uygulaması */
#include <tee_client_api.h>
#include "hello_world_ta.h"
int main(void)
{
TEEC_Result res;
TEEC_Context ctx;
TEEC_Session sess;
TEEC_Operation op;
TEEC_UUID uuid = TA_HELLO_WORLD_UUID;
uint32_t err_origin;
/* 1. TEE bağlamını başlat — /dev/tee0 aç */
res = TEEC_InitializeContext(NULL, &ctx);
if (res != TEEC_SUCCESS) {
fprintf(stderr, "TEEC_InitializeContext hata: 0x%x\n", res);
return 1;
}
/* 2. TA ile oturum aç */
res = TEEC_OpenSession(&ctx, &sess, &uuid,
TEEC_LOGIN_PUBLIC, NULL, NULL,
&err_origin);
if (res != TEEC_SUCCESS) {
fprintf(stderr, "TEEC_OpenSession hata: 0x%x (origin: 0x%x)\n",
res, err_origin);
TEEC_FinalizeContext(&ctx);
return 1;
}
/* 3. Komut hazırla: VALUE_INOUT parametresi ile değer gönder */
memset(&op, 0, sizeof(op));
op.paramTypes = TEEC_PARAM_TYPES(
TEEC_VALUE_INOUT, /* params[0]: değer gönder/al */
TEEC_NONE,
TEEC_NONE,
TEEC_NONE);
op.params[0].value.a = 42; /* giriş değeri */
printf("TA'ya 42 gonderiyorum, artirmasini istiyorum...\n");
res = TEEC_InvokeCommand(&sess,
TA_HELLO_WORLD_CMD_INC_VALUE,
&op, &err_origin);
if (res != TEEC_SUCCESS) {
fprintf(stderr, "InvokeCommand hata: 0x%x\n", res);
} else {
printf("TA sonucu: %d\n", op.params[0].value.a); /* 43 */
}
/* 4. Temizle */
TEEC_CloseSession(&sess);
TEEC_FinalizeContext(&ctx);
return (res == TEEC_SUCCESS) ? 0 : 1;
}
Hata kodları
| Kod | Değer | Açıklama |
|---|---|---|
| TEEC_SUCCESS | 0x00000000 | Başarılı |
| TEE_ERROR_BAD_PARAMETERS | 0xFFFF0006 | Geçersiz parametre tipi ya da değeri |
| TEE_ERROR_ACCESS_DENIED | 0xFFFF0001 | İzin yok — TA imza hatası |
| TEE_ERROR_OUT_OF_MEMORY | 0xFFFF000C | Secure heap tükendi |
| TEE_ERROR_ITEM_NOT_FOUND | 0xFFFF0008 | Secure storage'da nesne yok |
| TEE_ERROR_COMMUNICATION | 0xFFFF000E | OP-TEE supplicant bağlantı hatası |
| TEE_ERROR_NOT_SUPPORTED | 0xFFFF000A | Bilinmeyen komut ID'si |
04 Shared memory ve parametre tipleri
Normal World ile Secure World arasında büyük veri transferi için shared memory kullanılır; TEE Client API dört parametre tipini destekler.
Parametre tipleri
Geçici buffer kullanımı (şifreleme örneği)
/* AES şifreleme: giriş düz metin → çıktı şifreli metin */
TEEC_Operation op;
uint8_t plaintext[64] = "Gizli mesaj 12345678901234567890123456";
uint8_t ciphertext[64] = {0};
memset(&op, 0, sizeof(op));
op.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_TEMP_INPUT, /* params[0]: düz metin */
TEEC_MEMREF_TEMP_OUTPUT, /* params[1]: şifreli metin */
TEEC_VALUE_INPUT, /* params[2]: anahtar handle */
TEEC_NONE);
op.params[0].tmpref.buffer = plaintext;
op.params[0].tmpref.size = sizeof(plaintext);
op.params[1].tmpref.buffer = ciphertext;
op.params[1].tmpref.size = sizeof(ciphertext);
op.params[2].value.a = key_handle_id;
res = TEEC_InvokeCommand(&sess, TA_CMD_AES_ENCRYPT, &op, &err_origin);
printf("Sifrelendi: %zu byte\n", op.params[1].tmpref.size);
Kayıtlı shared memory (büyük veri)
/* Büyük dosya transferi için shared memory kaydet */
TEEC_SharedMemory shm;
shm.size = 1 * 1024 * 1024; /* 1 MB */
shm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
res = TEEC_AllocateSharedMemory(&ctx, &shm);
/* shm.buffer artık hem Normal hem Secure World görür */
/* Buffer'ı doldur */
memcpy(shm.buffer, large_data, shm.size);
/* MEMREF_WHOLE ile tüm bloğu geç */
op.params[0].memref.parent = &shm;
op.params[0].memref.offset = 0;
op.params[0].memref.size = shm.size;
op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE,
TEEC_NONE, TEEC_NONE, TEEC_NONE);
TEEC_InvokeCommand(&sess, TA_CMD_PROCESS_BUFFER, &op, &err_origin);
/* Temizle */
TEEC_ReleaseSharedMemory(&shm);
05 Secure Storage — güvenli anahtar saklama
OP-TEE, kriptografik anahtarları ve hassas verileri kalıcı olarak depolamak için şifreli ve bütünlük korumalı Persistent Object API sunar.
Depolama arka uçları
Nesne oluşturma ve yazma
/* TA içinde kalıcı nesne oluştur — AES-256 anahtar sakla */
#include <tee_internal_api.h>
TEE_Result store_aes_key(const uint8_t *key_data, size_t key_len)
{
TEE_ObjectHandle obj = TEE_HANDLE_NULL;
TEE_Result res;
const char obj_id[] = "device_aes_key_v1";
size_t obj_id_sz = sizeof(obj_id) - 1;
/* Var olan nesneyi sil (idempotent) */
TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
obj_id, obj_id_sz,
TEE_DATA_FLAG_ACCESS_WRITE_META,
&obj);
if (obj != TEE_HANDLE_NULL) {
TEE_CloseAndDeletePersistentObject1(obj);
obj = TEE_HANDLE_NULL;
}
/* Yeni nesne oluştur */
res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id, obj_id_sz,
TEE_DATA_FLAG_ACCESS_WRITE |
TEE_DATA_FLAG_ACCESS_READ |
TEE_DATA_FLAG_OVERWRITE,
TEE_HANDLE_NULL, /* attribute yok — ham veri */
key_data, key_len, /* başlangıç verisi */
&obj);
if (res == TEE_SUCCESS)
TEE_CloseObject(obj);
return res;
}
Nesne okuma
TEE_Result read_aes_key(uint8_t *key_buf, size_t *key_len)
{
TEE_ObjectHandle obj = TEE_HANDLE_NULL;
TEE_ObjectInfo info;
TEE_Result res;
const char obj_id[] = "device_aes_key_v1";
res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id, sizeof(obj_id) - 1,
TEE_DATA_FLAG_ACCESS_READ,
&obj);
if (res != TEE_SUCCESS) return res;
/* Nesne boyutunu sorgula */
TEE_GetObjectInfo1(obj, &info);
if (*key_len < info.dataSize) {
TEE_CloseObject(obj);
*key_len = info.dataSize;
return TEE_ERROR_SHORT_BUFFER;
}
uint32_t read_count;
res = TEE_ReadObjectData(obj, key_buf, info.dataSize, &read_count);
*key_len = read_count;
TEE_CloseObject(obj);
return res;
}
Anahtar nesne (TEE_Attribute) ile depolama
/* AES-256 key nesnesi oluştur ve kalıcı olarak sakla */
TEE_Result create_and_store_aes256(void)
{
TEE_ObjectHandle transient = TEE_HANDLE_NULL;
TEE_ObjectHandle persistent = TEE_HANDLE_NULL;
TEE_Result res;
/* Geçici AES-256 anahtar nesnesi oluştur */
res = TEE_AllocateTransientObject(TEE_TYPE_AES, 256, &transient);
if (res) return res;
/* Rastgele anahtar üret */
res = TEE_GenerateKey(transient, 256, NULL, 0);
if (res) goto out;
/* Kalıcı nesneye dönüştür */
res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
"aes256_master_key", 18,
TEE_DATA_FLAG_ACCESS_WRITE,
transient, /* attribute kaynağı */
NULL, 0, /* ek veri yok */
&persistent);
out:
if (transient) TEE_FreeTransientObject(transient);
if (persistent) TEE_CloseObject(persistent);
return res;
}
06 Kriptografi API
OP-TEE, GlobalPlatform TEE Cryptographic API üzerinden AES, RSA, ECC, HMAC, SHA gibi algoritmaları hem yazılım hem donanım hızlandırıcıyla sunar.
Simetrik şifreleme — AES-CBC
/* TA içinde AES-128-CBC şifreleme */
TEE_Result aes_cbc_encrypt(TEE_ObjectHandle key_obj,
const uint8_t *iv, size_t iv_len,
const uint8_t *in, size_t in_len,
uint8_t *out, size_t *out_len)
{
TEE_OperationHandle op = TEE_HANDLE_NULL;
TEE_Result res;
/* İşlem nesnesi oluştur */
res = TEE_AllocateOperation(&op, TEE_ALG_AES_CBC_NOPAD,
TEE_MODE_ENCRYPT, 128);
if (res) return res;
/* Anahtarı işleme ata */
res = TEE_SetOperationKey(op, key_obj);
if (res) goto out;
/* IV ile başlat */
TEE_CipherInit(op, iv, iv_len);
/* Şifrele */
res = TEE_CipherDoFinal(op, in, in_len, out, out_len);
out:
TEE_FreeOperation(op);
return res;
}
Özet hesaplama — SHA-256
TEE_Result sha256_hash(const uint8_t *data, size_t data_len,
uint8_t *digest, size_t *digest_len)
{
TEE_OperationHandle op = TEE_HANDLE_NULL;
TEE_Result res;
res = TEE_AllocateOperation(&op, TEE_ALG_SHA256,
TEE_MODE_DIGEST, 0);
if (res) return res;
/* Veriyi bloklara bölerek besleyebiliriz */
TEE_DigestUpdate(op, data, data_len / 2);
TEE_DigestUpdate(op, data + data_len / 2, data_len - data_len / 2);
/* Sonuç üret */
res = TEE_DigestDoFinal(op, NULL, 0, digest, digest_len);
TEE_FreeOperation(op);
return res; /* *digest_len = 32 (SHA-256 = 256 bit) */
}
Asimetrik şifreleme — RSA-OAEP
/* RSA-2048 OAEP ile şifreleme (public key ile) */
TEE_Result rsa_oaep_encrypt(TEE_ObjectHandle pub_key,
const uint8_t *plain, size_t plain_len,
uint8_t *cipher, size_t *cipher_len)
{
TEE_OperationHandle op = TEE_HANDLE_NULL;
TEE_Result res;
res = TEE_AllocateOperation(&op,
TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256,
TEE_MODE_ENCRYPT, 2048);
if (res) return res;
res = TEE_SetOperationKey(op, pub_key);
if (res) goto out;
res = TEE_AsymmetricEncrypt(op, NULL, 0,
plain, plain_len,
cipher, cipher_len);
out:
TEE_FreeOperation(op);
return res;
}
/* ECC-P256 imzalama */
TEE_Result ecdsa_sign(TEE_ObjectHandle priv_key,
const uint8_t *hash, size_t hash_len,
uint8_t *sig, size_t *sig_len)
{
TEE_OperationHandle op = TEE_HANDLE_NULL;
TEE_Result res;
res = TEE_AllocateOperation(&op,
TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, 256);
if (res) return res;
res = TEE_SetOperationKey(op, priv_key);
if (res) goto out;
res = TEE_AsymmetricSignDigest(op, NULL, 0,
hash, hash_len,
sig, sig_len);
out:
TEE_FreeOperation(op);
return res;
}
HMAC — mesaj doğrulama
TEE_Result hmac_sha256(TEE_ObjectHandle hmac_key,
const uint8_t *msg, size_t msg_len,
uint8_t *mac, size_t *mac_len)
{
TEE_OperationHandle op = TEE_HANDLE_NULL;
TEE_Result res;
res = TEE_AllocateOperation(&op, TEE_ALG_HMAC_SHA256,
TEE_MODE_MAC, 256);
if (res) return res;
res = TEE_SetOperationKey(op, hmac_key);
if (res) goto out;
TEE_MACInit(op, NULL, 0); /* IV yok */
TEE_MACUpdate(op, msg, msg_len);
res = TEE_MACComputeFinal(op, NULL, 0, mac, mac_len);
out:
TEE_FreeOperation(op);
return res;
}
Desteklenen algoritmalar
| Kategori | Algoritma | TEE_ALG sabit |
|---|---|---|
| Simetrik | AES-ECB/CBC/CTR/GCM/CCM | TEE_ALG_AES_* |
| Asimetrik | RSA-1024/2048/4096 | TEE_ALG_RSAES_* / TEE_ALG_RSASSA_* |
| ECC | ECDSA P-192/224/256/384/521 | TEE_ALG_ECDSA_P* |
| ECDH | ECDH P-192..521 | TEE_ALG_ECDH_P* |
| Özet | SHA-1/224/256/384/512 | TEE_ALG_SHA* |
| MAC | HMAC-SHA*, AES-CMAC | TEE_ALG_HMAC_* / TEE_ALG_AES_CMAC |
| KDF | HKDF, PBKDF2, Concat KDF | TEE_ALG_HKDF_* (GP ext.) |
07 PSA Certified ve attestation
OP-TEE, PSA Certified çerçevesindeki Initial Attestation Token (IAT) standardını destekler; cihazın güvenilir kimliğini uzak tarafa kriptografik olarak kanıtlar.
PSA Attestation mimarisi
Cihaz (OP-TEE + TF-A) Uzak Doğrulayıcı
───────────────────── ─────────────────
1. Client: psa_initial_attest_get_token()
│
▼
OP-TEE Attestation TA
- Cihaz boot ölçümleri (BL1,BL2,BL31 hash)
- Platform instance ID (hardware unique key)
- SW bileşen listesi
- Nonce (challenge)
→ COSE_Sign1 [ EAT / IAT claim seti ]
↳ ECC-P256 ile imzalı (DAK — Device Attestation Key)
│
▼ token (CBOR)
2. Verifier:
- CBOR ayrıştır
- COSE imzasını doğrula (DAK cert chain)
- Claim'leri politikayla karşılaştır
- Güven kararı ver
PSA API kullanımı
/* psa/crypto.h ve psa/initial_attestation.h */
#include <psa/crypto.h>
#include <psa/initial_attestation.h>
int get_attestation_token(const uint8_t *nonce, size_t nonce_len,
uint8_t *token_buf, size_t token_buf_size,
size_t *token_len)
{
psa_status_t status;
/* PSA kriptografi alt sistemini başlat */
status = psa_crypto_init();
if (status != PSA_SUCCESS) return -1;
/* Initial Attestation Token talep et */
status = psa_initial_attest_get_token(
nonce, nonce_len, /* challenge — tekrar saldırısı önler */
token_buf, token_buf_size,
token_len);
return (status == PSA_SUCCESS) ? 0 : -1;
}
IAT claim içeriği
| Claim (CBOR tag) | İçerik | Zorunlu |
|---|---|---|
| EAT_NONCE (10) | Verifier'ın gönderdiği nonce | Evet |
| EAT_INSTANCE_ID (256) | UEID — cihaza özgü 33 byte ID | Evet |
| EAT_BOOT_SEED (268) | Boot sırasında üretilen 32 byte rastgele değer | Evet |
| EAT_SW_COMPONENTS (2393) | BL1/BL2/BL31/OP-TEE/Linux hash listesi | Evet |
| EAT_IMPLEMENTATION_ID (265) | Platform UUID — donanım kimliği | Evet |
| EAT_SECURITY_LIFECYCLE (267) | PSA güvenlik yaşam döngüsü aşaması | Evet |
| EAT_CLIENT_ID (71) | Çağıran NSPE/SPE bileşeni kimliği | Hayır |
08 Derleme, yükleme ve debug
OP-TEE ekosistemini derleme, hedef sisteme kurma, TA yükleme ve xtest ile doğrulama adımları.
Repo manifest ile tam build
# OP-TEE manifest ile tüm bileşenleri çek
mkdir optee-project && cd optee-project
repo init -u https://github.com/OP-TEE/manifest.git \
-m qemu_v8.xml -b 3.21.0
repo sync -j4
# QEMU ARM v8 için derleme
cd build
make toolchains -j2
make PLATFORM=vexpress-qemu_armv8a -j$(nproc)
# Çıktılar:
# out-br/images/rootfs.cpio.gz — Normal World rootfs
# out/bin/tee.bin — OP-TEE OS binary (BL32)
# out-br/images/u-boot.bin — BL33
TA derleme (tek TA için)
# OP-TEE examples reposunu çek
git clone https://github.com/linaro-swg/optee_examples.git
cd optee_examples
# Cross-compile toolchain ortamı
export CROSS_COMPILE=aarch64-linux-gnu-
export CROSS_COMPILE_HOST=aarch64-linux-gnu-
export TA_DEV_KIT_DIR=/path/to/optee_os/export-ta_arm64
export TEEC_EXPORT=/path/to/optee_client/export-usr__aarch64
make -C hello_world
# Çıktılar:
# hello_world/ta/
# 8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta (imzalı TA)
# hello_world/host/
# optee_example_hello_world (CA binary)
Hedef sisteme kurma
# TA'yı rootfs'e kopyala
scp 8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta \
root@target:/lib/optee_armtz/
# CA'yı kopyala
scp optee_example_hello_world root@target:/usr/bin/
# Hedef sistem üzerinde çalıştır
ssh root@target
systemctl status tee-supplicant # supplicant çalışıyor mu?
optee_example_hello_world # TA'yı çağır
xtest — kapsamlı test süiti
# Tüm GP API testlerini çalıştır
xtest
# Belirli test grubunu çalıştır
xtest -t regression # Regresyon testleri
xtest 4001 # Tek test senaryosu (crypto)
xtest -t pkcs11 # PKCS#11 testleri
xtest --level 15 # Uzun süreli dayanıklılık
# Tipik başarılı çıktı:
# +-----------------------------------------------------
# 26944 subtests of which 0 failed
# 104 test cases of which 0 failed
# 0 test cases were skipped
# TEE test application done!
TA debug — OP-TEE syslog
# OP-TEE log mesajları kernel syslog'a gider
dmesg | grep optee
journalctl -u tee-supplicant -f
# TA içinde debug mesajları için (TA kaynak kodu):
DMSG("Deger: %d, ptr: %p", val, ptr); /* debug build'de görünür */
IMSG("Bilgi mesaji");
EMSG("Hata: res=0x%x", res);
# Kernel OP-TEE driver debug
echo 8 > /proc/sys/kernel/printk # Tüm seviyeleri etkinleştir
cat /sys/kernel/debug/optee/call_count
ls /sys/kernel/debug/optee/