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