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