11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
20f2293b7SJerome Forissier /*
30f2293b7SJerome Forissier * Copyright (c) 2014, Linaro Limited
40f2293b7SJerome Forissier */
50f2293b7SJerome Forissier
6e1770e71SJens Wiklander #include <crypto/crypto.h>
70f2293b7SJerome Forissier #include <stdlib.h>
80f2293b7SJerome Forissier #include <string.h>
9e1770e71SJens Wiklander #include <tee/tee_cryp_pbkdf2.h>
10e1770e71SJens Wiklander #include <tee/tee_cryp_utl.h>
11e1770e71SJens Wiklander #include <utee_defines.h>
120f2293b7SJerome Forissier
130f2293b7SJerome Forissier struct hmac_parms {
140f2293b7SJerome Forissier uint32_t algo;
150f2293b7SJerome Forissier size_t hash_len;
160f2293b7SJerome Forissier void *ctx;
170f2293b7SJerome Forissier };
180f2293b7SJerome Forissier
190f2293b7SJerome Forissier struct pbkdf2_parms {
200f2293b7SJerome Forissier const uint8_t *password;
210f2293b7SJerome Forissier size_t password_len;
220f2293b7SJerome Forissier const uint8_t *salt;
230f2293b7SJerome Forissier size_t salt_len;
240f2293b7SJerome Forissier uint32_t iteration_count;
250f2293b7SJerome Forissier };
260f2293b7SJerome Forissier
pbkdf2_f(uint8_t * out,size_t len,uint32_t idx,struct hmac_parms * h,struct pbkdf2_parms * p)270f2293b7SJerome Forissier static TEE_Result pbkdf2_f(uint8_t *out, size_t len, uint32_t idx,
280f2293b7SJerome Forissier struct hmac_parms *h, struct pbkdf2_parms *p)
290f2293b7SJerome Forissier {
300f2293b7SJerome Forissier TEE_Result res;
310f2293b7SJerome Forissier uint8_t u[TEE_MAX_HASH_SIZE];
320f2293b7SJerome Forissier uint32_t be_index;
330f2293b7SJerome Forissier size_t i, j;
340f2293b7SJerome Forissier
350f2293b7SJerome Forissier memset(out, 0, len);
360f2293b7SJerome Forissier for (i = 1; i <= p->iteration_count; i++) {
37c69bc615SJens Wiklander res = crypto_mac_init(h->ctx, p->password, p->password_len);
380f2293b7SJerome Forissier if (res != TEE_SUCCESS)
390f2293b7SJerome Forissier return res;
400f2293b7SJerome Forissier
410f2293b7SJerome Forissier if (i == 1) {
420f2293b7SJerome Forissier if (p->salt && p->salt_len) {
43c69bc615SJens Wiklander res = crypto_mac_update(h->ctx, p->salt,
44c69bc615SJens Wiklander p->salt_len);
450f2293b7SJerome Forissier if (res != TEE_SUCCESS)
460f2293b7SJerome Forissier return res;
470f2293b7SJerome Forissier }
480f2293b7SJerome Forissier
490f2293b7SJerome Forissier be_index = TEE_U32_TO_BIG_ENDIAN(idx);
500f2293b7SJerome Forissier
51c69bc615SJens Wiklander res = crypto_mac_update(h->ctx, (uint8_t *)&be_index,
520f2293b7SJerome Forissier sizeof(be_index));
530f2293b7SJerome Forissier if (res != TEE_SUCCESS)
540f2293b7SJerome Forissier return res;
550f2293b7SJerome Forissier } else {
56c69bc615SJens Wiklander res = crypto_mac_update(h->ctx, u, h->hash_len);
570f2293b7SJerome Forissier if (res != TEE_SUCCESS)
580f2293b7SJerome Forissier return res;
590f2293b7SJerome Forissier }
600f2293b7SJerome Forissier
61c69bc615SJens Wiklander res = crypto_mac_final(h->ctx, u, sizeof(u));
620f2293b7SJerome Forissier if (res != TEE_SUCCESS)
630f2293b7SJerome Forissier return res;
640f2293b7SJerome Forissier
650f2293b7SJerome Forissier for (j = 0; j < len; j++)
660f2293b7SJerome Forissier out[j] ^= u[j];
670f2293b7SJerome Forissier }
680f2293b7SJerome Forissier return TEE_SUCCESS;
690f2293b7SJerome Forissier }
700f2293b7SJerome Forissier
tee_cryp_pbkdf2(uint32_t hash_id,const uint8_t * password,size_t password_len,const uint8_t * salt,size_t salt_len,uint32_t iteration_count,uint8_t * derived_key,size_t derived_key_len)710f2293b7SJerome Forissier TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password,
720f2293b7SJerome Forissier size_t password_len, const uint8_t *salt,
730f2293b7SJerome Forissier size_t salt_len, uint32_t iteration_count,
740f2293b7SJerome Forissier uint8_t *derived_key, size_t derived_key_len)
750f2293b7SJerome Forissier {
760f2293b7SJerome Forissier TEE_Result res;
7782ef73bcSJens Wiklander size_t i, l, r;
780f2293b7SJerome Forissier uint8_t *out = derived_key;
790f2293b7SJerome Forissier struct pbkdf2_parms pbkdf2_parms;
800f2293b7SJerome Forissier struct hmac_parms hmac_parms = {0, };
810f2293b7SJerome Forissier
820f2293b7SJerome Forissier hmac_parms.algo = TEE_ALG_HMAC_ALGO(hash_id);
830f2293b7SJerome Forissier
84*7c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(hmac_parms.algo, &hmac_parms.hash_len);
850f2293b7SJerome Forissier if (res != TEE_SUCCESS)
860f2293b7SJerome Forissier return res;
870f2293b7SJerome Forissier
8882ef73bcSJens Wiklander res = crypto_mac_alloc_ctx(&hmac_parms.ctx, hmac_parms.algo);
890f2293b7SJerome Forissier if (res != TEE_SUCCESS)
900f2293b7SJerome Forissier return res;
910f2293b7SJerome Forissier
920f2293b7SJerome Forissier pbkdf2_parms.password = password;
930f2293b7SJerome Forissier pbkdf2_parms.password_len = password_len;
940f2293b7SJerome Forissier pbkdf2_parms.salt = salt;
950f2293b7SJerome Forissier pbkdf2_parms.salt_len = salt_len;
960f2293b7SJerome Forissier pbkdf2_parms.iteration_count = iteration_count;
970f2293b7SJerome Forissier
980f2293b7SJerome Forissier l = derived_key_len / hmac_parms.hash_len;
990f2293b7SJerome Forissier r = derived_key_len % hmac_parms.hash_len;
1000f2293b7SJerome Forissier
1010f2293b7SJerome Forissier for (i = 1; i <= l; i++) {
1020f2293b7SJerome Forissier res = pbkdf2_f(out, hmac_parms.hash_len, i, &hmac_parms,
1030f2293b7SJerome Forissier &pbkdf2_parms);
1040f2293b7SJerome Forissier if (res != TEE_SUCCESS)
1050f2293b7SJerome Forissier goto out;
1060f2293b7SJerome Forissier out += hmac_parms.hash_len;
1070f2293b7SJerome Forissier }
1080f2293b7SJerome Forissier if (r)
1090f2293b7SJerome Forissier res = pbkdf2_f(out, r, i, &hmac_parms, &pbkdf2_parms);
1100f2293b7SJerome Forissier
1110f2293b7SJerome Forissier out:
112c69bc615SJens Wiklander crypto_mac_free_ctx(hmac_parms.ctx);
1130f2293b7SJerome Forissier return res;
1140f2293b7SJerome Forissier }
115