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_hkdf.h> 29 #include <tee/tee_cryp_provider.h> 30 #include <tee/tee_cryp_utl.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <utee_defines.h> 34 35 36 static const uint8_t zero_salt[TEE_MAX_HASH_SIZE]; 37 38 static TEE_Result hkdf_extract(uint32_t hash_id, const uint8_t *ikm, 39 size_t ikm_len, const uint8_t *salt, 40 size_t salt_len, uint8_t *prk, size_t *prk_len) 41 { 42 TEE_Result res; 43 size_t ctx_size; 44 void *ctx = NULL; 45 uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); 46 uint32_t hmac_algo = (TEE_OPERATION_MAC << 28) | hash_id; 47 struct mac_ops *m = &crypto_ops.mac; 48 49 if (!m->get_ctx_size || !m->init || !m->update) { 50 res = TEE_ERROR_NOT_IMPLEMENTED; 51 goto out; 52 } 53 54 if (!salt || !salt_len) { 55 /* 56 * RFC 5869 section 2.2: 57 * If not provided, [the salt] is set to a string of HashLen 58 * zeros 59 */ 60 salt = zero_salt; 61 res = tee_hash_get_digest_size(hash_algo, &salt_len); 62 if (res != TEE_SUCCESS) 63 goto out; 64 } 65 66 res = m->get_ctx_size(hmac_algo, &ctx_size); 67 if (res != TEE_SUCCESS) 68 goto out; 69 70 ctx = malloc(ctx_size); 71 if (!ctx) { 72 res = TEE_ERROR_OUT_OF_MEMORY; 73 goto out; 74 } 75 76 /* 77 * RFC 5869 section 2.1: "Note that in the extract step, 'IKM' is used 78 * as the HMAC input, not as the HMAC key." 79 * Therefore, salt is the HMAC key in the formula from section 2.2: 80 * "PRK = HMAC-Hash(salt, IKM)" 81 */ 82 res = m->init(ctx, hmac_algo, salt, salt_len); 83 if (res != TEE_SUCCESS) 84 goto out; 85 86 res = m->update(ctx, hmac_algo, ikm, ikm_len); 87 if (res != TEE_SUCCESS) 88 goto out; 89 90 res = m->final(ctx, hmac_algo, prk, *prk_len); 91 if (res != TEE_SUCCESS) 92 goto out; 93 94 res = tee_hash_get_digest_size(hash_algo, prk_len); 95 out: 96 free(ctx); 97 return res; 98 } 99 100 static TEE_Result hkdf_expand(uint32_t hash_id, const uint8_t *prk, 101 size_t prk_len, const uint8_t *info, 102 size_t info_len, uint8_t *okm, size_t okm_len) 103 { 104 uint8_t tn[TEE_MAX_HASH_SIZE]; 105 size_t tn_len, hash_len, i, n, where, ctx_size; 106 TEE_Result res = TEE_SUCCESS; 107 void *ctx = NULL; 108 struct mac_ops *m = &crypto_ops.mac; 109 uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); 110 uint32_t hmac_algo = TEE_ALG_HMAC_ALGO(hash_id); 111 112 if (!m->get_ctx_size || !m->init || !m->update || !m->final) { 113 res = TEE_ERROR_NOT_IMPLEMENTED; 114 goto out; 115 } 116 117 res = tee_hash_get_digest_size(hash_algo, &hash_len); 118 if (res != TEE_SUCCESS) 119 goto out; 120 121 if (!okm || prk_len < hash_len) { 122 res = TEE_ERROR_BAD_STATE; 123 goto out; 124 } 125 126 if (!info) 127 info_len = 0; 128 129 res = m->get_ctx_size(hmac_algo, &ctx_size); 130 if (res != TEE_SUCCESS) 131 goto out; 132 133 ctx = malloc(ctx_size); 134 if (!ctx) { 135 res = TEE_ERROR_OUT_OF_MEMORY; 136 goto out; 137 } 138 139 /* N = ceil(L/HashLen) */ 140 n = okm_len / hash_len; 141 if ((okm_len % hash_len) != 0) 142 n++; 143 144 if (n > 255) { 145 res = TEE_ERROR_BAD_PARAMETERS; 146 goto out; 147 } 148 149 150 /* 151 * RFC 5869 section 2.3 152 * T = T(1) | T(2) | T(3) | ... | T(N) 153 * OKM = first L octets of T 154 * T(0) = empty string (zero length) 155 * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) 156 * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) 157 * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) 158 * ... 159 */ 160 tn_len = 0; 161 where = 0; 162 for (i = 1; i <= n; i++) { 163 uint8_t c = i; 164 165 res = m->init(ctx, hmac_algo, prk, prk_len); 166 if (res != TEE_SUCCESS) 167 goto out; 168 res = m->update(ctx, hmac_algo, tn, tn_len); 169 if (res != TEE_SUCCESS) 170 goto out; 171 res = m->update(ctx, hmac_algo, info, info_len); 172 if (res != TEE_SUCCESS) 173 goto out; 174 res = m->update(ctx, hmac_algo, &c, 1); 175 if (res != TEE_SUCCESS) 176 goto out; 177 res = m->final(ctx, hmac_algo, tn, sizeof(tn)); 178 if (res != TEE_SUCCESS) 179 goto out; 180 181 memcpy(okm + where, tn, (i < n) ? hash_len : (okm_len - where)); 182 where += hash_len; 183 tn_len = hash_len; 184 } 185 186 out: 187 free(ctx); 188 return res; 189 } 190 191 TEE_Result tee_cryp_hkdf(uint32_t hash_id, const uint8_t *ikm, size_t ikm_len, 192 const uint8_t *salt, size_t salt_len, 193 const uint8_t *info, size_t info_len, uint8_t *okm, 194 size_t okm_len) 195 { 196 TEE_Result res; 197 uint8_t prk[TEE_MAX_HASH_SIZE]; 198 size_t prk_len = sizeof(prk); 199 200 res = hkdf_extract(hash_id, ikm, ikm_len, salt, salt_len, prk, 201 &prk_len); 202 if (res != TEE_SUCCESS) 203 return res; 204 res = hkdf_expand(hash_id, prk, prk_len, info, info_len, okm, 205 okm_len); 206 207 return res; 208 } 209