1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, Linaro Limited 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <crypto/crypto.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <tee/tee_cryp_pbkdf2.h> 33 #include <tee/tee_cryp_utl.h> 34 #include <utee_defines.h> 35 36 struct hmac_parms { 37 uint32_t algo; 38 size_t hash_len; 39 void *ctx; 40 }; 41 42 struct pbkdf2_parms { 43 const uint8_t *password; 44 size_t password_len; 45 const uint8_t *salt; 46 size_t salt_len; 47 uint32_t iteration_count; 48 }; 49 50 static TEE_Result pbkdf2_f(uint8_t *out, size_t len, uint32_t idx, 51 struct hmac_parms *h, struct pbkdf2_parms *p) 52 { 53 TEE_Result res; 54 uint8_t u[TEE_MAX_HASH_SIZE]; 55 uint32_t be_index; 56 size_t i, j; 57 58 memset(out, 0, len); 59 for (i = 1; i <= p->iteration_count; i++) { 60 res = crypto_mac_init(h->ctx, h->algo, p->password, 61 p->password_len); 62 if (res != TEE_SUCCESS) 63 return res; 64 65 if (i == 1) { 66 if (p->salt && p->salt_len) { 67 res = crypto_mac_update(h->ctx, h->algo, 68 p->salt, p->salt_len); 69 if (res != TEE_SUCCESS) 70 return res; 71 } 72 73 be_index = TEE_U32_TO_BIG_ENDIAN(idx); 74 75 res = crypto_mac_update(h->ctx, h->algo, 76 (uint8_t *)&be_index, 77 sizeof(be_index)); 78 if (res != TEE_SUCCESS) 79 return res; 80 } else { 81 res = crypto_mac_update(h->ctx, h->algo, u, 82 h->hash_len); 83 if (res != TEE_SUCCESS) 84 return res; 85 } 86 87 res = crypto_mac_final(h->ctx, h->algo, u, sizeof(u)); 88 if (res != TEE_SUCCESS) 89 return res; 90 91 for (j = 0; j < len; j++) 92 out[j] ^= u[j]; 93 } 94 return TEE_SUCCESS; 95 } 96 97 TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password, 98 size_t password_len, const uint8_t *salt, 99 size_t salt_len, uint32_t iteration_count, 100 uint8_t *derived_key, size_t derived_key_len) 101 { 102 TEE_Result res; 103 size_t ctx_size, i, l, r; 104 uint8_t *out = derived_key; 105 struct pbkdf2_parms pbkdf2_parms; 106 struct hmac_parms hmac_parms = {0, }; 107 108 hmac_parms.algo = TEE_ALG_HMAC_ALGO(hash_id); 109 110 res = tee_mac_get_digest_size(hmac_parms.algo, &hmac_parms.hash_len); 111 if (res != TEE_SUCCESS) 112 return res; 113 114 res = crypto_mac_get_ctx_size(hmac_parms.algo, &ctx_size); 115 if (res != TEE_SUCCESS) 116 return res; 117 118 hmac_parms.ctx = malloc(ctx_size); 119 if (!hmac_parms.ctx) 120 return TEE_ERROR_OUT_OF_MEMORY; 121 122 pbkdf2_parms.password = password; 123 pbkdf2_parms.password_len = password_len; 124 pbkdf2_parms.salt = salt; 125 pbkdf2_parms.salt_len = salt_len; 126 pbkdf2_parms.iteration_count = iteration_count; 127 128 l = derived_key_len / hmac_parms.hash_len; 129 r = derived_key_len % hmac_parms.hash_len; 130 131 for (i = 1; i <= l; i++) { 132 res = pbkdf2_f(out, hmac_parms.hash_len, i, &hmac_parms, 133 &pbkdf2_parms); 134 if (res != TEE_SUCCESS) 135 goto out; 136 out += hmac_parms.hash_len; 137 } 138 if (r) 139 res = pbkdf2_f(out, r, i, &hmac_parms, &pbkdf2_parms); 140 141 out: 142 free(hmac_parms.ctx); 143 return res; 144 } 145