/** @file | |
EDKII Device Security library for SPDM device. | |
It follows the SPDM Specification. | |
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <Library/BaseLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include "hal/base.h" | |
#include "hal/library/memlib.h" | |
/** | |
* Copies bytes from a source buffer to a destination buffer. | |
* | |
* This function copies "src_len" bytes from "src_buf" to "dst_buf". | |
* | |
* Asserts and returns a non-zero value if any of the following are true: | |
* 1) "src_buf" or "dst_buf" are NULL. | |
* 2) "src_len" or "dst_len" is greater than (SIZE_MAX >> 1). | |
* 3) "src_len" is greater than "dst_len". | |
* 4) "src_buf" and "dst_buf" overlap. | |
* | |
* If any of these cases fail, a non-zero value is returned. Additionally if | |
* "dst_buf" points to a non-NULL value and "dst_len" is valid, then "dst_len" | |
* bytes of "dst_buf" are zeroed. | |
* | |
* This function follows the C11 cppreference description of memcpy_s. | |
* https://en.cppreference.com/w/c/string/byte/memcpy | |
* The cppreferece description does NOT allow the source or destination | |
* buffers to be NULL. | |
* | |
* This function differs from the Microsoft and Safeclib memcpy_s implementations | |
* in that the Microsoft and Safeclib implementations allow for NULL source and | |
* destinations pointers when the number of bytes to copy (src_len) is zero. | |
* | |
* In addition the Microsoft and Safeclib memcpy_s functions return different | |
* negative values on error. For best support, clients should generally check | |
* against zero for success or failure. | |
* | |
* @param dst_buf Destination buffer to copy to. | |
* @param dst_len Maximum length in bytes of the destination buffer. | |
* @param src_buf Source buffer to copy from. | |
* @param src_len The number of bytes to copy from the source buffer. | |
* | |
* @return 0 on success. non-zero on error. | |
* | |
**/ | |
void | |
libspdm_copy_mem ( | |
void *dst_buf, | |
size_t dst_len, | |
const void *src_buf, | |
size_t src_len | |
) | |
{ | |
volatile uint8_t *dst; | |
const volatile uint8_t *src; | |
dst = (volatile uint8_t *)dst_buf; | |
src = (const volatile uint8_t *)src_buf; | |
/* Check for case where "dst" or "dst_len" may be invalid. | |
* Do not zero "dst" in this case. */ | |
if ((dst == NULL) || (dst_len > (SIZE_MAX >> 1))) { | |
ASSERT (0); | |
} | |
/* Gaurd against invalid source. Zero "dst" in this case. */ | |
if (src == NULL) { | |
ZeroMem (dst_buf, dst_len); | |
ASSERT (0); | |
} | |
/* Guard against overlap case. Zero "dst" in these cases. */ | |
if (((src < dst) && (src + src_len > dst)) || ((dst < src) && (dst + src_len > src))) { | |
ZeroMem (dst_buf, dst_len); | |
ASSERT (0); | |
} | |
/* Guard against invalid lengths. Zero "dst" in these cases. */ | |
if ((src_len > dst_len) || | |
(src_len > (SIZE_MAX >> 1))) | |
{ | |
ZeroMem (dst_buf, dst_len); | |
ASSERT (0); | |
} | |
while (src_len-- != 0) { | |
*(dst++) = *(src++); | |
} | |
} | |
/** | |
* Fills a target buffer with a byte value, and returns the target buffer. | |
* | |
* This function fills length bytes of buffer with value, and returns buffer. | |
* | |
* If length is greater than (MAX_ADDRESS - buffer + 1), then ASSERT(). | |
* | |
* @param buffer The memory to set. | |
* @param length The number of bytes to set. | |
* @param value The value with which to fill length bytes of buffer. | |
* | |
* @return buffer. | |
* | |
**/ | |
void | |
libspdm_set_mem ( | |
void *buffer, | |
size_t length, | |
uint8_t value | |
) | |
{ | |
SetMem (buffer, length, value); | |
} | |
/** | |
* Fills a target buffer with zeros, and returns the target buffer. | |
* | |
* This function fills length bytes of buffer with zeros, and returns buffer. | |
* | |
* If length > 0 and buffer is NULL, then ASSERT(). | |
* If length is greater than (MAX_ADDRESS - buffer + 1), then ASSERT(). | |
* | |
* @param buffer The pointer to the target buffer to fill with zeros. | |
* @param length The number of bytes in buffer to fill with zeros. | |
* | |
* @return buffer. | |
* | |
**/ | |
void | |
libspdm_zero_mem ( | |
void *buffer, | |
size_t length | |
) | |
{ | |
ZeroMem (buffer, length); | |
} | |
/** | |
* Compares the contents of two buffers in const time. | |
* | |
* This function compares length bytes of source_buffer to length bytes of destination_buffer. | |
* If all length bytes of the two buffers are identical, then 0 is returned. Otherwise, the | |
* value returned is the first mismatched byte in source_buffer subtracted from the first | |
* mismatched byte in destination_buffer. | |
* | |
* If length > 0 and destination_buffer is NULL, then ASSERT(). | |
* If length > 0 and source_buffer is NULL, then ASSERT(). | |
* If length is greater than (MAX_ADDRESS - destination_buffer + 1), then ASSERT(). | |
* If length is greater than (MAX_ADDRESS - source_buffer + 1), then ASSERT(). | |
* | |
* @param destination_buffer A pointer to the destination buffer to compare. | |
* @param source_buffer A pointer to the source buffer to compare. | |
* @param length The number of bytes to compare. | |
* | |
* @return 0 All length bytes of the two buffers are identical. | |
* @retval Non-zero There is mismatched between source_buffer and destination_buffer. | |
* | |
**/ | |
bool | |
libspdm_consttime_is_mem_equal ( | |
const void *destination_buffer, | |
const void *source_buffer, | |
size_t length | |
) | |
{ | |
if (CompareMem (destination_buffer, source_buffer, length) == 0) { | |
return true; | |
} else { | |
return false; | |
} | |
} |