TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *other_info, size_t other_info_len, uint8_t *derived_key, size_t derived_key_len) { TEE_Result res; size_t hash_len, i, n, sz; void *ctx = NULL; uint8_t tmp[TEE_MAX_HASH_SIZE]; uint32_t be_count; uint8_t *out = derived_key; uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); res = crypto_hash_alloc_ctx(&ctx, hash_algo); if (res != TEE_SUCCESS) return res; res = tee_hash_get_digest_size(hash_algo, &hash_len); if (res != TEE_SUCCESS) goto out; n = derived_key_len / hash_len; sz = hash_len; for (i = 1; i <= n + 1; i++) { be_count = TEE_U32_TO_BIG_ENDIAN(i); res = crypto_hash_init(ctx, hash_algo); if (res != TEE_SUCCESS) goto out; res = crypto_hash_update(ctx, hash_algo, (uint8_t *)&be_count, sizeof(be_count)); if (res != TEE_SUCCESS) goto out; res = crypto_hash_update(ctx, hash_algo, shared_secret, shared_secret_len); if (res != TEE_SUCCESS) goto out; if (other_info && other_info_len) { res = crypto_hash_update(ctx, hash_algo, other_info, other_info_len); if (res != TEE_SUCCESS) goto out; } res = crypto_hash_final(ctx, hash_algo, tmp, sizeof(tmp)); if (res != TEE_SUCCESS) goto out; if (i == n + 1) sz = derived_key_len % hash_len; memcpy(out, tmp, sz); out += sz; } res = TEE_SUCCESS; out: crypto_hash_free_ctx(ctx, hash_algo); return res; }
static TEE_Result check_shdr(struct shdr *shdr) { struct rsa_public_key key; TEE_Result res; uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); size_t hash_size; if (shdr->magic != SHDR_MAGIC || shdr->img_type != SHDR_TA) return TEE_ERROR_SECURITY; if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) return TEE_ERROR_SECURITY; res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo), &hash_size); if (res != TEE_SUCCESS) return res; if (hash_size != shdr->hash_size) return TEE_ERROR_SECURITY; if (!crypto_ops.acipher.alloc_rsa_public_key || !crypto_ops.acipher.free_rsa_public_key || !crypto_ops.acipher.rsassa_verify || !crypto_ops.bignum.bin2bn) return TEE_ERROR_NOT_SUPPORTED; res = crypto_ops.acipher.alloc_rsa_public_key(&key, shdr->sig_size); if (res != TEE_SUCCESS) return res; res = crypto_ops.bignum.bin2bn((uint8_t *)&e, sizeof(e), key.e); if (res != TEE_SUCCESS) goto out; res = crypto_ops.bignum.bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size, key.n); if (res != TEE_SUCCESS) goto out; res = crypto_ops.acipher.rsassa_verify(shdr->algo, &key, -1, SHDR_GET_HASH(shdr), shdr->hash_size, SHDR_GET_SIG(shdr), shdr->sig_size); out: crypto_ops.acipher.free_rsa_public_key(&key); if (res != TEE_SUCCESS) return TEE_ERROR_SECURITY; return TEE_SUCCESS; }
static TEE_Result pbkdf2_f(uint8_t *out, size_t len, uint32_t idx, struct hmac_parms *h, struct pbkdf2_parms *p) { TEE_Result res; uint8_t u[TEE_MAX_HASH_SIZE]; uint32_t be_index; size_t i, j; memset(out, 0, len); for (i = 1; i <= p->iteration_count; i++) { res = crypto_mac_init(h->ctx, h->algo, p->password, p->password_len); if (res != TEE_SUCCESS) return res; if (i == 1) { if (p->salt && p->salt_len) { res = crypto_mac_update(h->ctx, h->algo, p->salt, p->salt_len); if (res != TEE_SUCCESS) return res; } be_index = TEE_U32_TO_BIG_ENDIAN(idx); res = crypto_mac_update(h->ctx, h->algo, (uint8_t *)&be_index, sizeof(be_index)); if (res != TEE_SUCCESS) return res; } else { res = crypto_mac_update(h->ctx, h->algo, u, h->hash_len); if (res != TEE_SUCCESS) return res; } res = crypto_mac_final(h->ctx, h->algo, u, sizeof(u)); if (res != TEE_SUCCESS) return res; for (j = 0; j < len; j++) out[j] ^= u[j]; } return TEE_SUCCESS; }