mirror of
				https://github.com/projectacrn/acrn-hypervisor.git
				synced 2025-10-31 17:34:34 +00:00 
			
		
		
		
	internal commit: 14ac2bc2299032fa6714d1fefa7cf0987b3e3085 Signed-off-by: Eddie Dong <eddie.dong@intel.com>
		
			
				
	
	
		
			164 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2018 Intel Corporation. All rights reserved.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  *
 | |
|  *   * Redistributions of source code must retain the above copyright
 | |
|  *     notice, this list of conditions and the following disclaimer.
 | |
|  *   * Redistributions in binary form must reproduce the above copyright
 | |
|  *     notice, this list of conditions and the following disclaimer in
 | |
|  *     the documentation and/or other materials provided with the
 | |
|  *     distribution.
 | |
|  *   * Neither the name of Intel Corporation nor the names of its
 | |
|  *     contributors may be used to endorse or promote products derived
 | |
|  *     from this software without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
|  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
|  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
|  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
|  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
|  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
|  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
|  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include <rtl.h>
 | |
| 
 | |
| #include "tinycrypt/hmac.h"
 | |
| #include "tinycrypt/sha256.h"
 | |
| 
 | |
| #define SHA256_HASH_SIZE 32 /* SHA-256 length */
 | |
| 
 | |
| static uint8_t *hmac_sha256(uint8_t *out, unsigned int out_len,
 | |
| 				const void *key, size_t key_len,
 | |
| 				const uint8_t *data, size_t data_len)
 | |
| {
 | |
| 	struct tc_hmac_state h;
 | |
| 
 | |
| 	memset(&h, 0x0, sizeof(h));
 | |
| 
 | |
| 	if (!tc_hmac_set_key(&h, key, key_len) ||
 | |
| 			!tc_hmac_init(&h) ||
 | |
| 			!tc_hmac_update(&h, data, data_len) ||
 | |
| 			!tc_hmac_final(out, out_len, &h)) {
 | |
| 		out = NULL;
 | |
| 	}
 | |
| 
 | |
| 	memset(&h, 0x0, sizeof(h));
 | |
| 
 | |
| 	return out;
 | |
| }
 | |
| 
 | |
| /* This function implements HKDF extract
 | |
|  * https://tools.ietf.org/html/rfc5869#section-2.2
 | |
|  */
 | |
| static int hkdf_sha256_extract(uint8_t *out_key, size_t out_len,
 | |
| 				const uint8_t *secret, size_t secret_len,
 | |
| 				const uint8_t *salt, size_t salt_len)
 | |
| {
 | |
| 	uint8_t salt0[SHA256_HASH_SIZE];
 | |
| 
 | |
| 	/* salt is optional for hkdf_sha256, it can be NULL.
 | |
| 	 *  The implement of tc_hmac_set_key in tinycrypt can't
 | |
| 	 *  accept NULL pointer, so salt0 is used here and set
 | |
| 	 *  to all 0s
 | |
| 	 */
 | |
| 	if (!salt || salt_len == 0) {
 | |
| 		memset(salt0, 0, SHA256_HASH_SIZE);
 | |
| 		salt = salt0;
 | |
| 		salt_len = SHA256_HASH_SIZE;
 | |
| 	}
 | |
| 
 | |
| 	if (!hmac_sha256(out_key, out_len,
 | |
| 				salt, salt_len,
 | |
| 				secret, secret_len))
 | |
| 		return 0;
 | |
| 
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| /* This function implements HKDF expand
 | |
|  * https://tools.ietf.org/html/rfc5869#section-2.3
 | |
|  */
 | |
| static int hkdf_sha256_expand(uint8_t *out_key, size_t out_len,
 | |
| 				const uint8_t *prk, size_t prk_len,
 | |
| 				const uint8_t *info, size_t info_len)
 | |
| {
 | |
| 	const size_t digest_len = SHA256_HASH_SIZE;
 | |
| 	uint8_t T[SHA256_HASH_SIZE];
 | |
| 	size_t n, done = 0;
 | |
| 	unsigned int i;
 | |
| 	int ret = 0;
 | |
| 	struct tc_hmac_state h;
 | |
| 
 | |
| 	n = (out_len + digest_len - 1) / digest_len;
 | |
| 	if (n > 255)
 | |
| 		return 0;
 | |
| 
 | |
| 	memset(&h, 0x0, sizeof(h));
 | |
| 
 | |
| 	for (i = 0; i < n; i++) {
 | |
| 		uint8_t ctr = i + 1;
 | |
| 		size_t todo;
 | |
| 
 | |
| 		tc_hmac_set_key(&h, prk, prk_len);
 | |
| 		tc_hmac_init(&h);
 | |
| 		if (i != 0 && (!tc_hmac_update(&h, T, digest_len)))
 | |
| 			goto out;
 | |
| 
 | |
| 		if (!tc_hmac_update(&h, info, info_len) ||
 | |
| 				!tc_hmac_update(&h, &ctr, 1) ||
 | |
| 				!tc_hmac_final(T, digest_len, &h)) {
 | |
| 			goto out;
 | |
| 		}
 | |
| 
 | |
| 		todo = digest_len;
 | |
| 		/* Check if the length of left buffer is smaller than
 | |
| 		 * 32 to make sure no buffer overflow in below memcpy
 | |
| 		 */
 | |
| 		if (done + todo > out_len)
 | |
| 			todo = out_len - done;
 | |
| 
 | |
| 		memcpy_s(out_key + done, todo, T, todo);
 | |
| 		done += todo;
 | |
| 	}
 | |
| 
 | |
| 	ret = 1;
 | |
| 
 | |
| out:
 | |
| 	memset(&h, 0x0, sizeof(h));
 | |
| 	memset(T, 0x0, SHA256_HASH_SIZE);
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| /* https://tools.ietf.org/html/rfc5869#section-2 */
 | |
| int hkdf_sha256(uint8_t *out_key, size_t out_len,
 | |
| 		const uint8_t *secret, size_t secret_len,
 | |
| 		const uint8_t *salt, size_t salt_len,
 | |
| 		const uint8_t *info, size_t info_len)
 | |
| {
 | |
| 	uint8_t prk[SHA256_HASH_SIZE];
 | |
| 	size_t prk_len = SHA256_HASH_SIZE;
 | |
| 
 | |
| 	if (!hkdf_sha256_extract(prk, prk_len,
 | |
| 				secret, secret_len,
 | |
| 				salt, salt_len)) {
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	if (!hkdf_sha256_expand(out_key, out_len,
 | |
| 				prk, prk_len,
 | |
| 				info, info_len)) {
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	return 1;
 | |
| }
 |