// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021 Rockchip Electronics Co. Ltd. */ #include #include #include #include #include #include #include "rk_crypto_api.h" #define CRYPTO_DEBUG 0 static uint32_t long2byte(uint64_t value, uint8_t ch[8]) { int i; uint32_t len = 0; for (i = 7; i >= 0; i--) { ch[i] = (value & 0xff00000000000000) >> 56; value = value << 8; if (ch[i] != 0 && len == 0) len = i + 1; } return len; } TEE_Result rk_gen_rsa_key(rsa_key_t *rsa_key, uint32_t key_len, uint64_t public_exponent) { TEE_Result res; TEE_ObjectHandle obj; TEE_Attribute attr; uint8_t e[8] = {0}; uint32_t e_len = 0; uint32_t out_len = 0; if (rsa_key == NULL) return TEE_ERROR_BAD_PARAMETERS; if (key_len != 32 && key_len != 64 && key_len != 96 && key_len != 128 && key_len != 192 && key_len != 256 && key_len != 384 && key_len != 512) return TEE_ERROR_BAD_PARAMETERS; /* support 3 and 65537 for now */ if (public_exponent != 3 && public_exponent != 65537) return TEE_ERROR_BAD_PARAMETERS; e_len = long2byte(public_exponent, e); TEE_InitRefAttribute(&attr, TEE_ATTR_RSA_PUBLIC_EXPONENT, e, e_len); res = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR, key_len * 8, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); return res; } res = TEE_GenerateKey(obj, key_len * 8, &attr, 1); if (res != TEE_SUCCESS) { EMSG("TEE_GenerateKey failed with code 0x%x", res); goto exit; } out_len = sizeof(rsa_key->n); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_RSA_MODULUS, rsa_key->n, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_n failed with code 0x%x", res); goto exit; } rsa_key->key_len = out_len; res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_RSA_PUBLIC_EXPONENT, rsa_key->e, &e_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_e failed with code 0x%x", res); goto exit; } rsa_key->e_len = e_len; out_len = sizeof(rsa_key->d); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_RSA_PRIVATE_EXPONENT, rsa_key->d, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_d failed with code 0x%x", res); goto exit; } rsa_key->d_len = out_len; out_len = sizeof(rsa_key->p); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_RSA_PRIME1, rsa_key->p, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_p failed with code 0x%x", res); goto exit; } rsa_key->p_len = out_len; out_len = sizeof(rsa_key->q); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_RSA_PRIME2, rsa_key->q, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_q failed with code 0x%x", res); goto exit; } rsa_key->q_len = out_len; out_len = sizeof(rsa_key->dp); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_RSA_EXPONENT1, rsa_key->dp, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_dp failed with code 0x%x", res); goto exit; } rsa_key->dp_len = out_len; out_len = sizeof(rsa_key->dq); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_RSA_EXPONENT2, rsa_key->dq, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_dq failed with code 0x%x", res); goto exit; } rsa_key->dq_len = out_len; out_len = sizeof(rsa_key->iq); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_RSA_COEFFICIENT, rsa_key->iq, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_iq failed with code 0x%x", res); goto exit; } rsa_key->iq_len = out_len; exit: TEE_FreeTransientObject(obj); return res; } TEE_Result rk_gen_ec_key(ec_key_t *ec_key, uint32_t key_len /* bit */, uint32_t curve) { TEE_Result res; TEE_ObjectHandle obj; TEE_Attribute attr; uint32_t out_len = 0; uint32_t padding_len = 0; uint32_t key_size_bytes = 0; uint8_t tmp_buf[66] = {0}; #if CRYPTO_DEBUG IMSG("key_len = %d; curve = %d", key_len, curve); #endif if (ec_key == NULL) return TEE_ERROR_BAD_PARAMETERS; if (key_len != 192 && key_len != 224 && key_len != 256 && key_len != 384 && key_len != 521) return TEE_ERROR_BAD_PARAMETERS; if (curve != TEE_ECC_CURVE_NIST_P192 && curve != TEE_ECC_CURVE_NIST_P224 && curve != TEE_ECC_CURVE_NIST_P256 && curve != TEE_ECC_CURVE_NIST_P384 && curve != TEE_ECC_CURVE_NIST_P521) return TEE_ERROR_BAD_PARAMETERS; ec_key->curve = curve; ec_key->key_len = key_len; key_size_bytes = (key_len + 7) / 8; TEE_InitValueAttribute(&attr, TEE_ATTR_ECC_CURVE, curve, 0); res = TEE_AllocateTransientObject(TEE_TYPE_ECDSA_KEYPAIR, key_len, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); return res; } res = TEE_GenerateKey(obj, key_len, &attr, 1); if (res != TEE_SUCCESS) { EMSG("TEE_GenerateKey failed with code 0x%x", res); goto exit; } out_len = sizeof(tmp_buf); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_ECC_PRIVATE_VALUE, tmp_buf, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for ECC_d failed with code 0x%x", res); goto exit; } padding_len = key_size_bytes - out_len; TEE_MemFill(ec_key->d, 0, padding_len); TEE_MemMove(ec_key->d + padding_len, tmp_buf, out_len); ec_key->d_len = key_size_bytes; out_len = sizeof(tmp_buf); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_ECC_PUBLIC_VALUE_X, tmp_buf, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for ECC_x failed with code 0x%x", res); goto exit; } padding_len = key_size_bytes - out_len; TEE_MemFill(ec_key->x, 0, padding_len); TEE_MemMove(ec_key->x + padding_len, tmp_buf, out_len); ec_key->x_len = key_size_bytes; out_len = sizeof(tmp_buf); res = TEE_GetObjectBufferAttribute(obj, TEE_ATTR_ECC_PUBLIC_VALUE_Y, tmp_buf, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for ECC_y failed with code 0x%x", res); goto exit; } padding_len = key_size_bytes - out_len; TEE_MemFill(ec_key->y, 0, padding_len); TEE_MemMove(ec_key->y + padding_len, tmp_buf, out_len); ec_key->y_len = key_size_bytes; exit: TEE_FreeTransientObject(obj); return res; } TEE_Result rk_cipher_crypto(uint8_t *in, uint8_t *out, uint32_t len, uint8_t *key, uint32_t key_len, uint8_t *iv, uint32_t algo, TEE_OperationMode mode) { TEE_Result res = 0; TEE_OperationHandle crypto_op = NULL; TEE_ObjectHandle obj = NULL; TEE_ObjectHandle obj_2 = NULL; TEE_Attribute attr; uint32_t obj_type; uint32_t iv_len = 0; uint32_t out_size = 0; uint32_t obj_key_size = 0; uint32_t op_key_size = 0; if (in == NULL || out == NULL || key == NULL) return TEE_ERROR_BAD_PARAMETERS; if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("in is 0x%x; out is 0x%x; key is 0x%x; ", *in, *out, *key); IMSG("in_len is %d; key_len is %d; algo is %08x", len, key_len, algo); if (iv) IMSG("iv is 0x%x", *iv); #endif out_size = len; switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_AES_CTR: case TEE_ALG_AES_CTS: if (key_len != 16 && key_len != 24 && key_len != 32) return TEE_ERROR_BAD_PARAMETERS; /* CTS is only for data which is not multiple of AES_BLOCK_SIZE * Others except CTR, are only for data which is multiple of AES_BLOCK_SIZE */ if (((algo == TEE_ALG_AES_CTS) && (len % AES_BLOCK_SIZE == 0)) || ((algo != TEE_ALG_AES_CTS) && (algo != TEE_ALG_AES_CTR) && (len % AES_BLOCK_SIZE != 0)) ) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_AES; iv_len = AES_BLOCK_SIZE; obj_key_size = key_len * 8; op_key_size = obj_key_size; break; case TEE_ALG_AES_XTS: if (key_len != 32 && key_len != 64) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_AES; iv_len = AES_BLOCK_SIZE; key_len = key_len / 2; //Divide the key into two XTS keys. obj_key_size = key_len * 8; op_key_size = obj_key_size * 2; //Should specifies both two keys. break; case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES_CBC_NOPAD: if ((key_len != 8) || (len % DES_BLOCK_SIZE != 0)) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_DES; iv_len = DES_BLOCK_SIZE; obj_key_size = key_len * 7; op_key_size = obj_key_size; break; case TEE_ALG_DES3_ECB_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: if ((key_len != 16 && key_len != 24) || (len % DES_BLOCK_SIZE != 0)) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_DES3; iv_len = DES_BLOCK_SIZE; obj_key_size = key_len * 7; op_key_size = obj_key_size; break; default: return TEE_ERROR_BAD_PARAMETERS; } if (!iv) iv_len = 0; res = TEE_AllocateOperation(&crypto_op, algo, mode, op_key_size); if(res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } /* Set object of key 1 */ TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_len); res = TEE_AllocateTransientObject(obj_type, obj_key_size, &obj); if(res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj, &attr, 1); if(res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } if (algo == TEE_ALG_AES_XTS) { /* Set object of key 2 */ TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key + key_len, key_len); res = TEE_AllocateTransientObject(obj_type, obj_key_size, &obj_2); if(res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj_2, &attr, 1); if(res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } /* Set operation of two keys */ res = TEE_SetOperationKey2(crypto_op, obj, obj_2); if(res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey2 failed with code 0x%x", res); goto exit; } } else { /* Set operation of one key */ res = TEE_SetOperationKey(crypto_op, obj); if(res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } } TEE_CipherInit(crypto_op, iv, iv_len); res = TEE_CipherDoFinal(crypto_op, in, len, out, &out_size); if (res != TEE_SUCCESS) { EMSG("TEE_CipherDoFinal failed with code 0x%x", res); goto exit; } exit: if (obj) TEE_FreeTransientObject(obj); if (obj_2) TEE_FreeTransientObject(obj_2); if (crypto_op) TEE_FreeOperation(crypto_op); return res; } TEE_Result rk_set_padding(crypto_ctx_t *ctx, int padding) { if (padding) ctx->padding = PKCS7_PADDING; else ctx->padding = NO_PADDING; return TEE_SUCCESS; } TEE_Result rk_set_sign_mode(crypto_ctx_t *ctx, unsigned int mode) { if (ctx == NULL) return TEE_ERROR_BAD_PARAMETERS; if (mode != SIGN_DIGEST && mode != SIGN_DATA) return TEE_ERROR_BAD_PARAMETERS; ctx->sign_mode = mode; return TEE_SUCCESS; } static TEE_Result rk_aes_padding_pkcs7(uint8_t *in, uint8_t *out, uint32_t len) { int pad_len; if ((!in) || (!out)) return TEE_ERROR_BAD_PARAMETERS; pad_len = AES_BLOCK_SIZE - len % AES_BLOCK_SIZE; TEE_MemMove(out, in, len); TEE_MemFill(&out[len], pad_len, pad_len); return TEE_SUCCESS; } static int rk_cut_pkcs7_padding(uint8_t *out, uint32_t *out_len) { int i, n; int len = 0; if (out == NULL || out_len == NULL) return TEE_ERROR_BAD_PARAMETERS; if (*out_len == 0) return TEE_ERROR_BAD_PARAMETERS; len = *out_len; n = out[len - 1]; for (i = 0; i < n; i ++) { if (out[len - 1 - i] != n) { return TEE_ERROR_BAD_FORMAT; } } *out_len -= n; return TEE_SUCCESS; } crypto_ctx_t *rk_crypto_malloc_ctx(void) { return TEE_Malloc(sizeof(crypto_ctx_t), TEE_MALLOC_FILL_ZERO); } void rk_crypto_free_ctx(crypto_ctx_t **ctx) { if (!*ctx) return; if ((*ctx)->obj) TEE_FreeTransientObject((*ctx)->obj); if ((*ctx)->obj_2) TEE_FreeTransientObject((*ctx)->obj_2); if ((*ctx)->op) TEE_FreeOperation((*ctx)->op); TEE_MemFill(*ctx, 0, sizeof(crypto_ctx_t)); TEE_Free(*ctx); *ctx = NULL; } TEE_Result rk_cipher_begin(crypto_ctx_t *ctx, uint8_t *key, uint32_t key_len, uint8_t *iv, uint32_t algo, TEE_OperationMode mode) { TEE_Result res = 0; TEE_OperationHandle crypto_op = NULL; TEE_ObjectHandle obj = NULL; TEE_ObjectHandle obj_2 = NULL; TEE_Attribute attr; uint32_t obj_type; uint32_t iv_len = 0; uint32_t obj_key_size = 0; uint32_t op_key_size = 0; if (ctx == NULL || key == NULL) return TEE_ERROR_BAD_PARAMETERS; if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_CLASS(algo) != TEE_OPERATION_CIPHER) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("key is 0x%x; key_len is %d; algo is %08x", *key, key_len, algo); if (iv) IMSG("iv is 0x%x", *iv); #endif switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_AES_CTR: case TEE_ALG_AES_CTS: if (key_len != 16 && key_len != 24 && key_len != 32) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_AES; iv_len = AES_BLOCK_SIZE; obj_key_size = key_len * 8; op_key_size = obj_key_size; break; case TEE_ALG_AES_XTS: if (key_len != 32 && key_len != 64) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_AES; iv_len = AES_BLOCK_SIZE; key_len = key_len / 2; //Divide the key into two XTS keys. obj_key_size = key_len * 8; op_key_size = obj_key_size * 2; //Should specifies both two keys. break; case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES_CBC_NOPAD: if (key_len != 8) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_DES; iv_len = DES_BLOCK_SIZE; obj_key_size = key_len * 7; op_key_size = obj_key_size; break; case TEE_ALG_DES3_ECB_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: if (key_len != 16 && key_len != 24) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_DES3; iv_len = DES_BLOCK_SIZE; obj_key_size = key_len * 7; op_key_size = obj_key_size; break; default: return TEE_ERROR_BAD_PARAMETERS; } if (!iv) iv_len = 0; res = TEE_AllocateOperation(&crypto_op, algo, mode, op_key_size); if(res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } /* Set object of key 1 */ TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_len); res = TEE_AllocateTransientObject(obj_type, obj_key_size, &obj); if(res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj, &attr, 1); if(res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } if (algo == TEE_ALG_AES_XTS) { /* Set object of key 2 */ TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key + key_len, key_len); res = TEE_AllocateTransientObject(obj_type, obj_key_size, &obj_2); if(res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj_2, &attr, 1); if(res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } /* Set operation of two keys */ res = TEE_SetOperationKey2(crypto_op, obj, obj_2); if(res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey2 failed with code 0x%x", res); goto exit; } } else { /* Set operation of one key */ res = TEE_SetOperationKey(crypto_op, obj); if(res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } } TEE_CipherInit(crypto_op, iv, iv_len); ctx->obj = obj; ctx->obj_2 = obj_2; ctx->op = crypto_op; ctx->algo = algo; ctx->mode = mode; ctx->buffer_offs = 0; return TEE_SUCCESS; exit: if (obj) TEE_FreeTransientObject(obj); if (obj_2) TEE_FreeTransientObject(obj_2); if (crypto_op) TEE_FreeOperation(crypto_op); return res; } static TEE_Result rk_cipher_buffer_update(crypto_ctx_t *ctx, uint8_t *in, uint8_t *out, uint32_t in_len, uint32_t *out_len) { TEE_Result res = 0; uint32_t real_in_len = 0; uint32_t tmp_out_len = 0; uint32_t out_size = 0; uint32_t buf_offs = 0; #if CRYPTO_DEBUG IMSG("ctx->buffer_offs: %d; ctx->algo: 0x%x", ctx->buffer_offs, ctx->algo); if (in && out && out_len) IMSG("in is 0x%x; out is 0x%x; in_len is %d; out_len is %d", *in, *out, in_len, *out_len); #endif buf_offs = ctx->buffer_offs; if ((ctx->buffer_offs + in_len) <= AES_BLOCK_SIZE) { TEE_MemMove(ctx->buffer + ctx->buffer_offs, in, in_len); ctx->buffer_offs += in_len; out_size = 0; if ((ctx->buffer_offs == AES_BLOCK_SIZE) && ((ctx->padding == NO_PADDING) || ((ctx->padding == PKCS7_PADDING) && ctx->mode == TEE_MODE_ENCRYPT))) { tmp_out_len = AES_BLOCK_SIZE; if (*out_len < tmp_out_len) return TEE_ERROR_SHORT_BUFFER; res = TEE_CipherUpdate(ctx->op, ctx->buffer, ctx->buffer_offs, out, &tmp_out_len); if (res != TEE_SUCCESS) { EMSG("TEE_CipherUpdate failed with code 0x%x\n", res); return res; } ctx->buffer_offs = 0; out_size += tmp_out_len; } } else { if (ctx->padding == NO_PADDING) { real_in_len = ((ctx->buffer_offs + in_len) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; } else if (ctx->padding == PKCS7_PADDING) { if (ctx->mode == TEE_MODE_DECRYPT) real_in_len = ROUNDUP(ctx->buffer_offs + in_len, AES_BLOCK_SIZE) - AES_BLOCK_SIZE; else real_in_len = ROUNDDOWN(ctx->buffer_offs + in_len, AES_BLOCK_SIZE); } if (*out_len < real_in_len) return TEE_ERROR_SHORT_BUFFER; /* update one block size data */ TEE_MemMove(ctx->buffer + ctx->buffer_offs, in, AES_BLOCK_SIZE - ctx->buffer_offs); tmp_out_len = AES_BLOCK_SIZE; res = TEE_CipherUpdate(ctx->op, ctx->buffer, AES_BLOCK_SIZE, out, &tmp_out_len); if (res != TEE_SUCCESS) { EMSG("TEE_CipherUpdate failed with code 0x%x\n", res); return res; } out_size += tmp_out_len; tmp_out_len = real_in_len - AES_BLOCK_SIZE; res = TEE_CipherUpdate(ctx->op, in + AES_BLOCK_SIZE - ctx->buffer_offs, tmp_out_len, out + AES_BLOCK_SIZE, &tmp_out_len); if (res != TEE_SUCCESS) { EMSG("TEE_CipherUpdate failed with code 0x%x\n", res); return res; } out_size += tmp_out_len; tmp_out_len = (ctx->buffer_offs + in_len) % AES_BLOCK_SIZE; if (ctx->padding == NO_PADDING) { ctx->buffer_offs = tmp_out_len; } else if (ctx->padding == PKCS7_PADDING) { if (ctx->mode == TEE_MODE_DECRYPT) ctx->buffer_offs = tmp_out_len == 0 ? 16 : tmp_out_len; else ctx->buffer_offs = tmp_out_len; } TEE_MemMove(ctx->buffer, in + real_in_len - buf_offs, ctx->buffer_offs); } *out_len = out_size; #if CRYPTO_DEBUG IMSG("out[0] is 0x%x; out_size is %d", *out, out_size); #endif return TEE_SUCCESS; } TEE_Result rk_cipher_update(crypto_ctx_t *ctx, uint8_t *in, uint8_t *out, uint32_t in_len, uint32_t *out_len) { TEE_Result res = 0; if (ctx == NULL || (in == NULL && in_len != 0) || out_len == NULL || (out == NULL && *out_len != 0)) return TEE_ERROR_BAD_PARAMETERS; if (ctx->obj == NULL || ctx->op == NULL) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("ctx->obj: 0x%x;ctx->op: 0x%x;ctx->algo: 0x%x", (uint32_t)ctx->obj, (uint32_t)ctx->op, ctx->algo); IMSG("in is 0x%x; out is 0x%x; in_len is %d; out_len is %d", *in, *out, in_len, *out_len); #endif if (ctx->algo == TEE_ALG_AES_ECB_NOPAD || ctx->algo == TEE_ALG_AES_CBC_NOPAD) { res = rk_cipher_buffer_update(ctx, in, out, in_len, out_len); if (res != TEE_SUCCESS) { EMSG("rk_cipher_buffer_update failed with code 0x%x\n", res); return res; } } else { res = TEE_CipherUpdate(ctx->op, in, in_len, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_CipherUpdate failed with code 0x%x\n", res); return res; } } return TEE_SUCCESS; } TEE_Result rk_cipher_finish(crypto_ctx_t *ctx, uint8_t *out, uint32_t *out_len) { TEE_Result res = 0; uint8_t feed_in[32]; int fd_len = 0; if (ctx == NULL || out_len == NULL || (out == NULL && *out_len != 0)) return TEE_ERROR_BAD_PARAMETERS; if (ctx->obj == NULL || ctx->op == NULL) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("ctx->obj: 0x%x;ctx->op: 0x%x;ctx->algo: 0x%x; ctx->padding: %d", (uint32_t)ctx->obj, (uint32_t)ctx->op, ctx->algo, ctx->padding); #endif if ((ctx->algo == TEE_ALG_AES_ECB_NOPAD) || (ctx->algo == TEE_ALG_AES_CBC_NOPAD)) { if (ctx->padding == NO_PADDING) { if (ctx->buffer_offs % AES_BLOCK_SIZE) { EMSG("The length of all data is NOT multiple of block size"); return TEE_ERROR_BAD_PARAMETERS; } res = TEE_CipherDoFinal(ctx->op, NULL, 0, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_CipherDoFinal failed with code 0x%x", res); return res; } } else if (ctx->padding == PKCS7_PADDING) { if (ctx->mode == TEE_MODE_ENCRYPT) { res = rk_aes_padding_pkcs7(ctx->buffer, feed_in, ctx->buffer_offs); if (res != TEE_SUCCESS) { EMSG("rk_aes_padding_pkcs7 failed with 0x%x", res); return res; } fd_len = (ctx->buffer_offs / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE; if ((int)*out_len < fd_len) return TEE_ERROR_SHORT_BUFFER; res = TEE_CipherDoFinal(ctx->op, feed_in, fd_len, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_CipherDoFinal failed with code 0x%x", res); return res; } } else { if (*out_len < ctx->buffer_offs) { return TEE_ERROR_SHORT_BUFFER; } if (ctx->buffer_offs % AES_BLOCK_SIZE) { EMSG("The length of all data is NOT multiple of block size"); return TEE_ERROR_BAD_PARAMETERS; } res = TEE_CipherDoFinal(ctx->op, ctx->buffer, ctx->buffer_offs, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_CipherDoFinal failed with code 0x%x", res); return res; } res = rk_cut_pkcs7_padding(out, out_len); if (res != TEE_SUCCESS) { EMSG("rk_cut_pkcs7_padding failed with code 0x%x", res); return res; } } } } else { res = TEE_CipherDoFinal(ctx->op, NULL, 0, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_CipherDoFinal failed with code 0x%x", res); return res; } } return TEE_SUCCESS; } TEE_Result rk_ae_begin(crypto_ctx_t *ctx, uint8_t *key, uint32_t key_len, uint8_t *iv, uint32_t iv_len, uint32_t aad_len, uint32_t tag_len, uint32_t payload_len, uint32_t algo, TEE_OperationMode mode) { TEE_Result res = 0; TEE_OperationHandle crypto_op = NULL; TEE_ObjectHandle obj = NULL; TEE_Attribute attr; uint32_t obj_type; uint32_t max_key_size = 0; if (ctx == NULL || key == NULL) return TEE_ERROR_BAD_PARAMETERS; if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("key is 0x%x; key_len is %d; algo is %08x", *key, key_len, algo); IMSG("aad_len is %d; tag_len is %d; payload_len is %d", aad_len, tag_len, payload_len); if (iv) IMSG("iv is 0x%x", *iv); IMSG("iv_len is %d", iv_len); #endif if (key_len != 16 && key_len != 24 && key_len != 32) return TEE_ERROR_BAD_PARAMETERS; obj_type = TEE_TYPE_AES; max_key_size = key_len * 8; if (algo == TEE_ALG_AES_GCM) { if (iv_len > AES_BLOCK_SIZE) return TEE_ERROR_BAD_PARAMETERS; } else if (algo == TEE_ALG_AES_CCM) { if (iv_len > 15 || iv_len < 7 || iv == NULL) return TEE_ERROR_BAD_PARAMETERS; } else { return TEE_ERROR_BAD_PARAMETERS; } TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_len); res = TEE_AllocateTransientObject(obj_type, max_key_size, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj, &attr, 1); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&crypto_op, algo, mode, max_key_size); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(crypto_op, obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } res = TEE_AEInit(crypto_op, iv, iv_len, tag_len * 8, aad_len, payload_len); if (res != TEE_SUCCESS) { EMSG("TEE_AEInit failed with code 0x%x", res); goto exit; } ctx->obj = obj; ctx->op = crypto_op; ctx->algo = algo; ctx->mode = mode; return TEE_SUCCESS; exit: if (obj) TEE_FreeTransientObject(obj); if (crypto_op) TEE_FreeOperation(crypto_op); return res; } TEE_Result rk_ae_update(crypto_ctx_t *ctx, uint8_t *in, uint8_t *out, uint32_t in_len, uint32_t *out_len, rk_ae_update_type_t is_aad) { TEE_Result res = 0; if (ctx == NULL || (in == NULL && in_len != 0)) return TEE_ERROR_BAD_PARAMETERS; if (!is_aad && (out_len == NULL || (out == NULL && *out_len != 0))) return TEE_ERROR_BAD_PARAMETERS; if (ctx->obj == NULL || ctx->op == NULL) return TEE_ERROR_BAD_PARAMETERS; if (is_aad) { TEE_AEUpdateAAD(ctx->op, in, in_len); } else { res = TEE_AEUpdate(ctx->op, in, in_len, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_AEUpdate failed with code 0x%x", res); return res; } } return TEE_SUCCESS; } TEE_Result rk_ae_finish(crypto_ctx_t *ctx, uint8_t *in, uint8_t *out, uint8_t *tag, uint32_t in_len, uint32_t *out_len, uint32_t *tag_len) { TEE_Result res = 0; uint32_t tmp_out_len; uint32_t tmp_tag_len; if (ctx == NULL || (in == NULL && in_len != 0) || out_len == NULL || (out == NULL && *out_len != 0) || tag == NULL || tag_len == NULL) return TEE_ERROR_BAD_PARAMETERS; if (ctx->obj == NULL || ctx->op == NULL) return TEE_ERROR_BAD_PARAMETERS; tmp_tag_len = *tag_len; tmp_out_len = *out_len; #if CRYPTO_DEBUG IMSG("ctx->obj: 0x%x;ctx->op: 0x%x;ctx->algo: 0x%x;ctx->mode: 0x%x", (uint32_t)ctx->obj, (uint32_t)ctx->op, ctx->algo, ctx->mode); IMSG("in_len = %d, out_len = %d, tag_len = %d", in_len, tmp_out_len, tmp_tag_len); #endif if (ctx->mode == TEE_MODE_ENCRYPT) { res = TEE_AEEncryptFinal(ctx->op, in, in_len, out, &tmp_out_len, tag, &tmp_tag_len); } else { uint8_t tmp_tag[16]; if (tmp_tag_len > sizeof(tmp_tag)) return TEE_ERROR_BAD_PARAMETERS; TEE_MemMove(tmp_tag, tag, tmp_tag_len); res = TEE_AEDecryptFinal(ctx->op, in, in_len, out, &tmp_out_len, tmp_tag, tmp_tag_len); } *tag_len = tmp_tag_len; *out_len = tmp_out_len; if (res != TEE_SUCCESS) { EMSG("TEE_AEFinal failed with code 0x%x", res); return res; } return TEE_SUCCESS; } TEE_Result rk_hash_begin(crypto_ctx_t *ctx, uint32_t algo) { TEE_Result res = 0; TEE_OperationHandle hash_op = NULL; res = TEE_AllocateOperation(&hash_op, algo, TEE_MODE_DIGEST, 0); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); return res; } ctx->op = hash_op; return TEE_SUCCESS; } TEE_Result rk_hash_update(crypto_ctx_t *ctx, uint8_t *in, uint32_t in_len) { if (ctx == NULL || (in == NULL && in_len != 0)) { return TEE_ERROR_BAD_PARAMETERS; } if (ctx->op == NULL) { return TEE_ERROR_BAD_PARAMETERS; } TEE_DigestUpdate(ctx->op, in, in_len); return TEE_SUCCESS; } TEE_Result rk_hash_finish(crypto_ctx_t *ctx, uint8_t *in, uint8_t *out, uint32_t in_len, uint32_t *out_len) { TEE_Result res = 0; if (ctx == NULL || (in == NULL && in_len != 0) || out_len == NULL || (out == NULL && *out_len != 0)) { return TEE_ERROR_BAD_PARAMETERS; } if (ctx->op == NULL) { return TEE_ERROR_BAD_PARAMETERS; } res = TEE_DigestDoFinal(ctx->op, in, in_len, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_DigestDoFinal failed with code 0x%x", res); return res; } return TEE_SUCCESS; } TEE_Result rk_hash_crypto(uint8_t *in, uint8_t *out, uint32_t in_len, uint32_t out_len, uint32_t algo) { TEE_Result res = TEE_SUCCESS; crypto_ctx_t *ctx = NULL; uint32_t out_size = out_len; ctx = rk_crypto_malloc_ctx(); if (!ctx) { EMSG("Malloc context memory FAILED!"); return TEE_ERROR_OUT_OF_MEMORY; } res = rk_hash_begin(ctx, algo); if (res) { EMSG("---rk_hash_begin---FAILED! return value: 0x%x", res); goto exit; } res = rk_hash_update(ctx, in, in_len); if (res) { EMSG("---rk_hash_update---FAILED! return value: 0x%x", res); goto exit; } res = rk_hash_finish(ctx, NULL, out, 0, &out_size); if (res) { EMSG("---rk_hash_finish---FAILED! return value: 0x%x", res); goto exit; } if (out_size != out_len) { EMSG("out_size:%d != out_len:%d", out_size, out_len); res = TEE_ERROR_GENERIC; goto exit; } exit: if (ctx) rk_crypto_free_ctx(&ctx); return res; } TEE_Result rk_mac_crypto(uint8_t *in, uint8_t *out, uint32_t in_len, uint32_t *out_len, uint8_t *key, uint32_t key_len, uint8_t *iv, uint32_t algo) { TEE_OperationHandle mac_op; TEE_ObjectHandle obj; TEE_Attribute attr; TEE_Result res = 0; uint32_t obj_type = 0; uint32_t iv_len = 0; uint32_t out_size = 0; uint32_t max_key_size = 0; if (!in || !out || !key || !in_len || !key_len) return TEE_ERROR_BAD_PARAMETERS; /* AES_CMAC is only for data which is larger than AES_BLOCK_SIZE */ if (algo == TEE_ALG_AES_CMAC && in_len < AES_BLOCK_SIZE) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("in is 0x%x; out is 0x%x; key is 0x%x", *in, *out, *key); IMSG("in_len is %d; out_len is %d; key_len is %d; iv_len is %d; algo is %08x", in_len, *out_len, key_len, iv_len, algo); if (iv) IMSG("iv is 0x%x", *iv); #endif switch (algo) { case TEE_ALG_AES_CMAC: obj_type = TEE_TYPE_AES; iv_len = AES_BLOCK_SIZE; max_key_size = key_len * 8; out_size = AES_BLOCK_SIZE; break; case TEE_ALG_HMAC_SHA256: obj_type = TEE_TYPE_HMAC_SHA256; iv_len = AES_BLOCK_SIZE; max_key_size = key_len * 8; out_size = SHA256_HASH_SIZE; break; case TEE_ALG_HMAC_SHA1: obj_type = TEE_TYPE_HMAC_SHA1; iv_len = AES_BLOCK_SIZE; max_key_size = key_len * 8; out_size = SHA1_HASH_SIZE; break; case TEE_ALG_HMAC_MD5: obj_type = TEE_TYPE_HMAC_MD5; iv_len = AES_BLOCK_SIZE; max_key_size = key_len * 8; out_size = MD5_HASH_SIZE; break; default: return TEE_ERROR_BAD_PARAMETERS; } if (!iv) iv_len = 0; TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_len); res = TEE_AllocateTransientObject(obj_type, max_key_size, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj, &attr, 1); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&mac_op, algo, TEE_MODE_MAC, max_key_size); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(mac_op, obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } TEE_MACInit(mac_op, iv, iv_len); res = TEE_MACComputeFinal(mac_op, in, in_len, out, &out_size); if (res != TEE_SUCCESS) { EMSG("TEE_MACComputeFinal failed with code 0x%x", res); goto exit; } *out_len = out_size; exit: TEE_FreeTransientObject(obj); TEE_FreeOperation(mac_op); return res; } TEE_Result rk_mac_begin(crypto_ctx_t *ctx, uint8_t *key, uint32_t key_len, uint8_t *iv, uint32_t algo) { TEE_OperationHandle mac_op = NULL; TEE_ObjectHandle obj = NULL; TEE_Attribute attr; TEE_Result res = 0; uint32_t obj_type = 0; uint32_t iv_len = 0; uint32_t max_key_size = 0; uint32_t key_block[MAX_HASH_BLOCK_SIZE]; uint32_t key_block_len = 0; uint32_t block_size = 0; uint32_t hash_algo; if (ctx == NULL || key == NULL || key_len == 0) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_CLASS(algo) != TEE_OPERATION_MAC) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("key is 0x%x; key_len is %d; iv_len is %d; algo is %08x", *key, key_len, iv_len, algo); if (iv) IMSG("iv is 0x%x", *iv); #endif TEE_MemFill(key_block, 0, sizeof(key_block)); switch (algo) { case TEE_ALG_AES_CMAC: obj_type = TEE_TYPE_AES; iv_len = AES_BLOCK_SIZE; max_key_size = key_len * 8; if (max_key_size != 128 && max_key_size != 192 && max_key_size != 256) return TEE_ERROR_BAD_PARAMETERS; TEE_MemMove(key_block, key, key_len); key_block_len = key_len; break; case TEE_ALG_HMAC_SHA1: obj_type = TEE_TYPE_HMAC_SHA1; block_size = 64; hash_algo = TEE_ALG_SHA1; key_block_len = SHA1_HASH_SIZE; break; case TEE_ALG_HMAC_SHA224: obj_type = TEE_TYPE_HMAC_SHA224; block_size = 64; key_block_len = SHA224_HASH_SIZE; hash_algo = TEE_ALG_SHA224; break; case TEE_ALG_HMAC_SHA256: obj_type = TEE_TYPE_HMAC_SHA256; block_size = 64; key_block_len = SHA256_HASH_SIZE; hash_algo = TEE_ALG_SHA256; break; case TEE_ALG_HMAC_SHA384: obj_type = TEE_TYPE_HMAC_SHA384; block_size = 128; key_block_len = SHA384_HASH_SIZE; hash_algo = TEE_ALG_SHA384; break; case TEE_ALG_HMAC_SHA512: obj_type = TEE_TYPE_HMAC_SHA512; block_size = 128; key_block_len = SHA512_HASH_SIZE; hash_algo = TEE_ALG_SHA512; break; case TEE_ALG_HMAC_MD5: obj_type = TEE_TYPE_HMAC_MD5; block_size = 64; key_block_len = MD5_HASH_SIZE; hash_algo = TEE_ALG_MD5; break; default: return TEE_ERROR_BAD_PARAMETERS; } if (!iv) iv_len = 0; /* handle the key size for HMAC */ if (algo != TEE_ALG_AES_CMAC) { iv_len = 0; /* Long keys are hashed. */ if (key_len > block_size) { res = rk_hash_crypto(key, (uint8_t *)key_block, key_len, key_block_len, hash_algo); if (res) { EMSG("Hash long keys failed."); return res; } /* Min key size is set as 64 bits in OS. */ } else if (key_len < 8) { TEE_MemMove(key_block, key, key_len); key_block_len = 8; } else { if (key_len <= sizeof(key_block)) { TEE_MemMove(key_block, key, key_len); key_block_len = key_len; } else { EMSG("Check key len failed."); res = TEE_ERROR_GENERIC; return res; } } max_key_size = key_block_len * 8; } TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key_block, key_block_len); res = TEE_AllocateTransientObject(obj_type, max_key_size, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj, &attr, 1); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&mac_op, algo, TEE_MODE_MAC, max_key_size); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(mac_op, obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } TEE_MACInit(mac_op, iv, iv_len); ctx->obj = obj; ctx->op = mac_op; ctx->algo = algo; return TEE_SUCCESS; exit: if (obj) TEE_FreeTransientObject(obj); if (mac_op) TEE_FreeOperation(mac_op); return res; } TEE_Result rk_mac_update(crypto_ctx_t *ctx, uint8_t *in, uint32_t in_len) { if (ctx == NULL || (in == NULL && in_len != 0)) return TEE_ERROR_BAD_PARAMETERS; if (ctx->obj == NULL || ctx->op == NULL) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("ctx->obj: 0x%x;ctx->op: 0x%x;ctx->algo: 0x%x", (uint32_t)ctx->obj, (uint32_t)ctx->op, ctx->algo); IMSG("in is 0x%x; in_len is %d", *in, in_len); #endif TEE_MACUpdate(ctx->op, in, in_len); return TEE_SUCCESS; } TEE_Result rk_mac_finish(crypto_ctx_t *ctx, uint8_t *in, uint8_t *mac, uint32_t in_len, uint32_t *mac_len, rk_mac_mode_t mode) { TEE_Result res = 0; uint32_t out_size = 0; if (ctx == NULL || (in == NULL && in_len != 0) || mac_len == NULL || mac == NULL) return TEE_ERROR_BAD_PARAMETERS; if (ctx->obj == NULL || ctx->op == NULL) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("ctx->obj: 0x%x;ctx->op: 0x%x;ctx->algo: 0x%x", (uint32_t)ctx->obj, (uint32_t)ctx->op, ctx->algo); IMSG("mac is 0x%x; in_len is %d; mac_len is %d", *mac, in_len, *mac_len); if (in) IMSG("in is 0x%x", *in); #endif switch (ctx->algo) { case TEE_ALG_AES_CMAC: out_size = AES_BLOCK_SIZE; break; case TEE_ALG_HMAC_SHA1: out_size = SHA1_HASH_SIZE; break; case TEE_ALG_HMAC_SHA224: out_size = SHA224_HASH_SIZE; break; case TEE_ALG_HMAC_SHA256: out_size = SHA256_HASH_SIZE; break; case TEE_ALG_HMAC_SHA384: out_size = SHA384_HASH_SIZE; break; case TEE_ALG_HMAC_SHA512: out_size = SHA512_HASH_SIZE; break; case TEE_ALG_HMAC_MD5: out_size = MD5_HASH_SIZE; break; default: return TEE_ERROR_BAD_PARAMETERS; } if (mode == RK_MAC_SIGN) { res = TEE_MACComputeFinal(ctx->op, in, in_len, mac, &out_size); if (res != TEE_SUCCESS) { EMSG("TEE_MACComputeFinal failed with code 0x%x", res); return res; } *mac_len = out_size; } else if (mode == RK_MAC_VERIFY) { res = TEE_MACCompareFinal(ctx->op, in, in_len, mac, *mac_len); if (res != TEE_SUCCESS) { EMSG("TEE_MACCompareFinal failed with code 0x%x", res); return res; } } else { EMSG("Unsupport mode: 0x%x", mode); return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } TEE_Result rk_rsa_begin(crypto_ctx_t *ctx, rsa_key_t *key, uint32_t algo, TEE_OperationMode mode) { TEE_Result res = 0; TEE_OperationHandle rsa_op = NULL; TEE_ObjectHandle obj = NULL; TEE_Attribute attr[3]; uint32_t max_key_size = 0; if (!key || !ctx) return TEE_ERROR_BAD_PARAMETERS; if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT && mode != TEE_MODE_SIGN && mode != TEE_MODE_VERIFY) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_MAIN_ALG(algo) != TEE_MAIN_ALGO_RSA) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("key->n is 0x%x; key->e is 0x%x; key->d is 0x%x", *(key->n), *(key->e), *(key->d)); IMSG("key->key_len is %d; algo is 0x%x; mode is 0x%x", key->key_len, algo, mode); #endif max_key_size = key->key_len * 8; TEE_InitRefAttribute(&attr[0], TEE_ATTR_RSA_MODULUS, key->n, key->key_len); TEE_InitRefAttribute(&attr[1], TEE_ATTR_RSA_PUBLIC_EXPONENT, key->e, key->e_len); TEE_InitRefAttribute(&attr[2], TEE_ATTR_RSA_PRIVATE_EXPONENT, key->d, key->d_len); res = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR, max_key_size, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); return res; } res = TEE_PopulateTransientObject(obj, attr, 3); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&rsa_op, algo, mode, max_key_size); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(rsa_op, obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } ctx->obj = obj; ctx->op = rsa_op; ctx->algo = algo; ctx->mode = mode; return TEE_SUCCESS; exit: if (obj) TEE_FreeTransientObject(obj); if (rsa_op) TEE_FreeOperation(rsa_op); return res; } TEE_Result rk_rsa_finish(crypto_ctx_t *ctx, uint8_t *in, uint8_t *out, uint32_t in_len, uint32_t *out_len, uint32_t salt_len) { TEE_Result res = 0; TEE_Attribute attr; if (ctx == NULL || (in == NULL && in_len != 0) || out_len == NULL || (out == NULL && *out_len != 0)) return TEE_ERROR_BAD_PARAMETERS; if (ctx->obj == NULL || ctx->op == NULL) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("ctx->obj: 0x%x;ctx->op: 0x%x;ctx->algo: 0x%x", (uint32_t)ctx->obj, (uint32_t)ctx->op, ctx->algo); IMSG("salt_len is %d", salt_len); if (in != NULL && in_len != 0) IMSG("in is 0x%x; in_len is %d; ", *in, in_len); if (out != NULL && *out_len != 0) IMSG("out is 0x%x; out_len is %d;", *out, *out_len); #endif TEE_InitValueAttribute(&attr, TEE_ATTR_RSA_PSS_SALT_LENGTH, salt_len, 0); switch (ctx->mode) { case TEE_MODE_ENCRYPT: res = TEE_AsymmetricEncrypt(ctx->op, NULL, 0, in, in_len, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_AsymmetricEncrypt failed with code 0x%x", res); return res; } break; case TEE_MODE_DECRYPT: res = TEE_AsymmetricDecrypt(ctx->op, NULL, 0, in, in_len, out, out_len); if (res != TEE_SUCCESS) { EMSG("TEE_AsymmetricDecrypt failed with code 0x%x", res); return res; } break; case TEE_MODE_SIGN: if (ctx->sign_mode == SIGN_DIGEST) { res = TEE_AsymmetricSignDigest(ctx->op, &attr, 1, in, in_len, out, out_len); } else if (ctx->sign_mode == SIGN_DATA) { res = TEE_AsymmetricPrivateEncrypt(ctx->op, NULL, 0, in, in_len, out, out_len); } else { EMSG("Error sign mode!"); res = TEE_ERROR_BAD_PARAMETERS; } if (res != TEE_SUCCESS) { EMSG("TEE_AsymmetricSignDigest failed with code 0x%x", res); return res; } break; case TEE_MODE_VERIFY: if (ctx->sign_mode == SIGN_DIGEST) { res = TEE_AsymmetricVerifyDigest(ctx->op, &attr, 1, in, in_len, out, *out_len); } else if (ctx->sign_mode == SIGN_DATA) { res = TEE_AsymmetricPublicDecrypt(ctx->op, NULL, 0, in, in_len, out, out_len); } else { EMSG("Error sign mode!"); res = TEE_ERROR_BAD_PARAMETERS; } if (res != TEE_SUCCESS) { if (res == TEE_ERROR_SIGNATURE_INVALID) { EMSG("Verify failed!!!The signature is invalid!!!"); } else { EMSG("TEE_AsymmetricVerifyDigest failed with code 0x%x", res); } return res; } break; default: EMSG("Unknown mode!!!"); return TEE_ERROR_BAD_PARAMETERS; } #if CRYPTO_DEBUG IMSG("out[0] is 0x%x; out_len is %d; in_len is %d", *out, *out_len, in_len); #endif return TEE_SUCCESS; } TEE_Result rk_rsa_crypto(uint8_t *in, uint8_t *out, uint32_t len, rsa_key_t *key, uint32_t algo, TEE_OperationMode mode) { TEE_Result res = 0; TEE_OperationHandle rsa_op; TEE_ObjectHandle obj; TEE_Attribute attr[3]; uint32_t out_size = 0; uint32_t max_key_size = 0; if (!in || !out || !key || !len) return TEE_ERROR_BAD_PARAMETERS; if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("in is 0x%x; out is 0x%x; len is %d; key_len is 0x%x", *in, *out, len, key->key_len); #endif out_size = key->key_len; max_key_size = key->key_len * 8; TEE_InitRefAttribute(&attr[0], TEE_ATTR_RSA_MODULUS, key->n, key->key_len); TEE_InitRefAttribute(&attr[1], TEE_ATTR_RSA_PUBLIC_EXPONENT, key->e, 3); TEE_InitRefAttribute(&attr[2], TEE_ATTR_RSA_PRIVATE_EXPONENT, key->d, key->d_len); res = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR, max_key_size, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj, attr, 3); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&rsa_op, algo, mode, max_key_size); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(rsa_op, obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } if (mode == TEE_MODE_ENCRYPT) { res = TEE_AsymmetricEncrypt(rsa_op, NULL, 0, in, len, out, &out_size); if (res != TEE_SUCCESS) { EMSG("TEE_AsymmetricEncrypt failed with code 0x%x", res); goto exit; } } else { res = TEE_AsymmetricDecrypt(rsa_op, NULL, 0, in, len, out, &out_size); if (res != TEE_SUCCESS) { EMSG("TEE_AsymmetricDecrypt failed with code 0x%x", res); goto exit; } } #if CRYPTO_DEBUG IMSG("out[0] is 0x%x; out_size is %d; len is %d", *out, out_size, len); #endif exit: TEE_FreeTransientObject(obj); TEE_FreeOperation(rsa_op); return res; } TEE_Result rk_rsa_sign(uint8_t *digest, uint8_t *signature, uint32_t digest_len, uint32_t *signature_len, rsa_key_t *key, uint32_t salt_len, uint32_t algo, TEE_OperationMode mode) { TEE_Result res = 0; TEE_OperationHandle rsa_op; TEE_ObjectHandle obj; TEE_Attribute attr[4]; uint32_t out_size = 0; uint32_t max_key_size = 0; #if CRYPTO_DEBUG IMSG("digest is 0x%x; signature is 0x%x; digest_len is %d; salt_len is %d", *digest, *signature, digest_len, salt_len); IMSG("key->n is 0x%x; key->e is 0x%x; key->d is 0x%x", *key->n, *key->e, *key->d); #endif out_size = *signature_len; max_key_size = key->key_len * 8; TEE_InitRefAttribute(&attr[0], TEE_ATTR_RSA_MODULUS, key->n, key->key_len); TEE_InitRefAttribute(&attr[1], TEE_ATTR_RSA_PUBLIC_EXPONENT, key->e, 3); TEE_InitRefAttribute(&attr[2], TEE_ATTR_RSA_PRIVATE_EXPONENT, key->d, key->d_len); TEE_InitValueAttribute(&attr[3], TEE_ATTR_RSA_PSS_SALT_LENGTH, salt_len, 0); res = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR, max_key_size, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj, attr, 3); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&rsa_op, algo, mode, max_key_size); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(rsa_op, obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } if (mode == TEE_MODE_SIGN) { res = TEE_AsymmetricSignDigest(rsa_op, &attr[3], 1, digest, digest_len, signature, &out_size); if (res != TEE_SUCCESS) { EMSG("TEE_AsymmetricSignDigest failed with code 0x%x", res); goto exit; } *signature_len = out_size; } else { res = TEE_AsymmetricVerifyDigest(rsa_op, &attr[3], 1, digest, digest_len, signature, out_size); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_SIGNATURE_INVALID) { EMSG("Verify failed!!!The signature is invalid!!!"); } else { EMSG("TEE_AsymmetricVerifyDigest failed with code 0x%x", res); } } } exit: TEE_FreeTransientObject(obj); TEE_FreeOperation(rsa_op); return res; } TEE_Result rk_ecdsa_sign(uint8_t *digest, uint8_t *signature, uint32_t digest_len, uint32_t *signature_len, ec_key_t *key, uint32_t algo, TEE_OperationMode mode) { TEE_Result res = 0; TEE_OperationHandle ecdsa_op; TEE_ObjectHandle obj; TEE_Attribute attr[4]; uint32_t out_size = 0; uint32_t max_key_size = 0; #if CRYPTO_DEBUG IMSG("digest is 0x%x; signature is 0x%x; digest_len is %d; signature_len is %d", *digest, *signature, digest_len, *signature_len); IMSG("key->d is 0x%x; key->x is 0x%x; key->y is 0x%x", *key->d, *key->x, *key->y); IMSG("key->d_len is %d; key->x_len is %d; key->y_len is %d", key->d_len, key->x_len, key->y_len); IMSG("key->curve is 0x%x; key->key_len is %d; algo is 0x%x; mode is 0x%x", key->curve, key->key_len, algo, mode); #endif out_size = *signature_len; max_key_size = key->key_len; TEE_InitRefAttribute(&attr[0], TEE_ATTR_ECC_PUBLIC_VALUE_X, key->x, key->x_len); TEE_InitRefAttribute(&attr[1], TEE_ATTR_ECC_PUBLIC_VALUE_Y, key->y, key->y_len); TEE_InitRefAttribute(&attr[2], TEE_ATTR_ECC_PRIVATE_VALUE, key->d, key->d_len); TEE_InitValueAttribute(&attr[3], TEE_ATTR_ECC_CURVE, key->curve, 0); res = TEE_AllocateTransientObject(TEE_TYPE_ECDSA_KEYPAIR, max_key_size, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); return res; } res = TEE_PopulateTransientObject(obj, attr, 4); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&ecdsa_op, algo, mode, max_key_size); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(ecdsa_op, obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } if (mode == TEE_MODE_SIGN) { res = TEE_AsymmetricSignDigest(ecdsa_op, NULL, 0, digest, digest_len, signature, &out_size); if (res != TEE_SUCCESS) { EMSG("TEE_AsymmetricSignDigest failed with code 0x%x", res); goto exit; } *signature_len = out_size; } else { res = TEE_AsymmetricVerifyDigest(ecdsa_op, NULL, 0, digest, digest_len, signature, out_size); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_SIGNATURE_INVALID) { EMSG("Verify failed!!!The signature is invalid!!!"); } else { EMSG("TEE_AsymmetricVerifyDigest failed with code 0x%x", res); } } } exit: TEE_FreeTransientObject(obj); TEE_FreeOperation(ecdsa_op); return res; } TEE_Result rk_ecdsa_begin(crypto_ctx_t *ctx, ec_key_t *key, uint32_t algo, TEE_OperationMode mode) { TEE_Result res = TEE_ERROR_GENERIC; TEE_OperationHandle ecdsa_op = NULL; TEE_ObjectHandle obj = NULL; TEE_Attribute attr[4]; uint32_t max_key_size = 0; if (!key || !ctx) return TEE_ERROR_BAD_PARAMETERS; if (mode != TEE_MODE_SIGN && mode != TEE_MODE_VERIFY) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_MAIN_ALG(algo) != TEE_MAIN_ALGO_ECDSA) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("key->d is 0x%x; key->x is 0x%x; key->y is 0x%x", *key->d, *key->x, *key->y); IMSG("key->d_len is %d; key->x_len is %d; key->y_len is %d", key->d_len, key->x_len, key->y_len); IMSG("key->curve is 0x%x; key->key_len is %d; algo is 0x%x; mode is 0x%x", key->curve, key->key_len, algo, mode); #endif max_key_size = key->key_len; TEE_InitRefAttribute(&attr[0], TEE_ATTR_ECC_PUBLIC_VALUE_X, key->x, key->x_len); TEE_InitRefAttribute(&attr[1], TEE_ATTR_ECC_PUBLIC_VALUE_Y, key->y, key->y_len); TEE_InitRefAttribute(&attr[2], TEE_ATTR_ECC_PRIVATE_VALUE, key->d, key->d_len); TEE_InitValueAttribute(&attr[3], TEE_ATTR_ECC_CURVE, key->curve, 0); res = TEE_AllocateTransientObject(TEE_TYPE_ECDSA_KEYPAIR, max_key_size, &obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(obj, attr, 4); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&ecdsa_op, algo, mode, max_key_size); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(ecdsa_op, obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } ctx->obj = obj; ctx->op = ecdsa_op; ctx->algo = algo; ctx->mode = mode; return TEE_SUCCESS; exit: if (obj) TEE_FreeTransientObject(obj); if (ecdsa_op) TEE_FreeOperation(ecdsa_op); return res; } TEE_Result rk_ecdsa_finish(crypto_ctx_t *ctx, uint8_t *digest, uint8_t *sign, uint32_t digest_len, uint32_t *sign_len) { TEE_Result res = 0; if (ctx == NULL || (digest == NULL && digest_len != 0) || sign_len == NULL || (sign == NULL && *sign_len != 0)) return TEE_ERROR_BAD_PARAMETERS; if (ctx->obj == NULL || ctx->op == NULL) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("ctx->obj: 0x%x;ctx->op: 0x%x;ctx->algo: 0x%x", (uint32_t)ctx->obj, (uint32_t)ctx->op, ctx->algo); #endif switch (ctx->mode) { case TEE_MODE_SIGN: res = TEE_AsymmetricSignDigest(ctx->op, NULL, 0, digest, digest_len, sign, sign_len); if (res != TEE_SUCCESS) { EMSG("TEE_AsymmetricSignDigest failed with code 0x%x", res); return res; } break; case TEE_MODE_VERIFY: res = TEE_AsymmetricVerifyDigest(ctx->op, NULL, 0, digest, digest_len, sign, *sign_len); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_SIGNATURE_INVALID) { EMSG("Verify failed!!!The asn1_sign is invalid!!!"); } else { EMSG("TEE_AsymmetricVerifyDigest failed with code 0x%x", res); } return res; } break; default: EMSG("Unknown mode: 0x%x", ctx->mode); return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } TEE_Result rk_pkcs5_pbkdf2_hmac(uint8_t *password, uint32_t password_len, uint8_t *salt, uint32_t salt_len, uint32_t iterations, uint32_t algo, uint32_t key_len, uint8_t *out_key) { TEE_Result res = 0; TEE_OperationHandle derive_op = NULL; TEE_ObjectHandle password_obj = NULL; TEE_ObjectHandle key_obj = NULL; TEE_Attribute params[4]; uint32_t param_count = 0; uint32_t out_len = 0; if (out_key == NULL && key_len != 0) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_MAIN_ALG(algo) != TEE_MAIN_ALGO_PBKDF2) return TEE_ERROR_BAD_PARAMETERS; if (password_len > 512) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("password_len is %d; salt_len is %d; iterations is %d; key_len is %d", password_len, salt_len, iterations, key_len); #endif TEE_InitRefAttribute(params, TEE_ATTR_PBKDF2_PASSWORD, password, password_len); param_count = 1; res = TEE_AllocateTransientObject(TEE_TYPE_PBKDF2_PASSWORD, password_len * 8, &password_obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(password_obj, params, param_count); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&derive_op, algo, TEE_MODE_DERIVE, password_len * 8); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(derive_op, password_obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET, key_len * 8, &key_obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } param_count = 0; if (salt) { TEE_InitRefAttribute(¶ms[param_count], TEE_ATTR_PBKDF2_SALT, salt, salt_len); param_count++; } TEE_InitValueAttribute(¶ms[param_count], TEE_ATTR_PBKDF2_DKM_LENGTH, key_len, 0); param_count++; TEE_InitValueAttribute(¶ms[param_count], TEE_ATTR_PBKDF2_ITERATION_COUNT, iterations, 0); param_count++; TEE_DeriveKey(derive_op, params, param_count, key_obj); out_len = key_len; res = TEE_GetObjectBufferAttribute(key_obj, TEE_ATTR_SECRET_VALUE, out_key, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_n failed with code 0x%x", res); goto exit; } exit: if (password_obj) TEE_FreeTransientObject(password_obj); if (key_obj) TEE_FreeTransientObject(key_obj); if (derive_op) TEE_FreeOperation(derive_op); return res; } TEE_Result rk_hkdf_genkey(uint8_t *ikm, uint32_t ikm_len, uint8_t *salt, uint32_t salt_len, uint32_t *info, uint32_t info_len, uint32_t algo, uint32_t okm_len, uint8_t *okm) { TEE_Result res = 0; TEE_OperationHandle derive_op = NULL; TEE_ObjectHandle password_obj = NULL; TEE_ObjectHandle key_obj = NULL; TEE_Attribute params[4]; uint32_t param_count = 0; uint32_t out_len = 0; if (okm == NULL && okm_len != 0) return TEE_ERROR_BAD_PARAMETERS; if (ikm == NULL && ikm_len != 0) return TEE_ERROR_BAD_PARAMETERS; if (salt == NULL && salt_len != 0) return TEE_ERROR_BAD_PARAMETERS; if (info == NULL && info_len != 0) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_MAIN_ALG(algo) != TEE_MAIN_ALGO_HKDF) return TEE_ERROR_BAD_PARAMETERS; if (ikm_len > 512) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("ikm_len is %d; salt_len is %d; okm_len is %d; info_len is %d; algo is 0x%x", ikm_len, salt_len, okm_len, info_len, algo); #endif TEE_InitRefAttribute(params, TEE_ATTR_HKDF_IKM, ikm, ikm_len); param_count = 1; res = TEE_AllocateTransientObject(TEE_TYPE_HKDF_IKM, ikm_len * 8, &password_obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_PopulateTransientObject(password_obj, params, param_count); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_AllocateOperation(&derive_op, algo, TEE_MODE_DERIVE, ikm_len * 8); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(derive_op, password_obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET, okm_len * 8, &key_obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } param_count = 0; if (salt) { TEE_InitRefAttribute(¶ms[param_count], TEE_ATTR_HKDF_SALT, salt, salt_len); param_count++; } TEE_InitValueAttribute(¶ms[param_count], TEE_ATTR_HKDF_OKM_LENGTH, okm_len, 0); param_count++; TEE_InitRefAttribute(¶ms[param_count], TEE_ATTR_HKDF_INFO, info, info_len); param_count++; TEE_DeriveKey(derive_op, params, param_count, key_obj); out_len = okm_len; res = TEE_GetObjectBufferAttribute(key_obj, TEE_ATTR_SECRET_VALUE, okm, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute for RSA_n failed with code 0x%x", res); goto exit; } exit: if (password_obj) TEE_FreeTransientObject(password_obj); if (key_obj) TEE_FreeTransientObject(key_obj); if (derive_op) TEE_FreeOperation(derive_op); return res; } TEE_Result rk_ecdh_genkey(uint8_t *private, uint8_t *publicx, uint32_t *publicy, uint32_t algo, uint32_t curve, uint32_t keysize, uint8_t *out) { TEE_Result res = 0; TEE_OperationHandle derive_op = NULL; TEE_ObjectHandle password_obj = NULL; TEE_ObjectHandle key_obj = NULL; TEE_Attribute params[4]; uint32_t param_count = 0; uint32_t out_len = 0; uint32_t size_byte = (keysize + 7) / 8; if (private == NULL || publicx == NULL || publicy == NULL) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_MAIN_ALG(algo) != TEE_MAIN_ALGO_ECDH) return TEE_ERROR_BAD_PARAMETERS; if (keysize != 192 && keysize != 224 && keysize != 256 && keysize != 384 && keysize != 521) return TEE_ERROR_BAD_PARAMETERS; #if CRYPTO_DEBUG IMSG("algo is %d; curve is %d; keysize is %d", algo, curve, keysize); #endif res = TEE_AllocateOperation(&derive_op, algo, TEE_MODE_DERIVE, keysize); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateOperation failed with code 0x%x", res); goto exit; } res = TEE_AllocateTransientObject(TEE_TYPE_ECDH_KEYPAIR, keysize, &password_obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } TEE_InitValueAttribute(¶ms[param_count], TEE_ATTR_ECC_CURVE, curve, 0); param_count++; TEE_InitRefAttribute(¶ms[param_count], TEE_ATTR_ECC_PRIVATE_VALUE, private, size_byte); param_count++; TEE_InitRefAttribute(¶ms[param_count], TEE_ATTR_ECC_PUBLIC_VALUE_X, private, size_byte); param_count++; TEE_InitRefAttribute(¶ms[param_count], TEE_ATTR_ECC_PUBLIC_VALUE_Y, private, size_byte); param_count++; res = TEE_PopulateTransientObject(password_obj, params, param_count); if (res != TEE_SUCCESS) { EMSG("TEE_PopulateTransientObject failed with code 0x%x", res); goto exit; } res = TEE_SetOperationKey(derive_op, password_obj); if (res != TEE_SUCCESS) { EMSG("TEE_SetOperationKey failed with code 0x%x", res); goto exit; } res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET, size_byte * 8, &key_obj); if (res != TEE_SUCCESS) { EMSG("TEE_AllocateTransientObject failed with code 0x%x", res); goto exit; } param_count = 0; TEE_InitRefAttribute(¶ms[param_count], TEE_ATTR_ECC_PUBLIC_VALUE_X, publicx, size_byte); param_count++; TEE_InitRefAttribute(¶ms[param_count], TEE_ATTR_ECC_PUBLIC_VALUE_Y, publicy, size_byte); param_count++; TEE_DeriveKey(derive_op, params, param_count, key_obj); out_len = size_byte; res = TEE_GetObjectBufferAttribute(key_obj, TEE_ATTR_SECRET_VALUE, out, &out_len); if (res != TEE_SUCCESS) { EMSG("TEE_GetObjectBufferAttribute failed with code 0x%x", res); goto exit; } exit: if (password_obj) TEE_FreeTransientObject(password_obj); if (key_obj) TEE_FreeTransientObject(key_obj); if (derive_op) TEE_FreeOperation(derive_op); return res; }