Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sancus_untag functions and fix sancus_unwrap_with_key #37

Merged
merged 5 commits into from
Oct 20, 2021
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 74 additions & 19 deletions src/sancus_support/sm_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,29 @@ sm_id sancus_enable_wrapped(struct SancusModule* sm, unsigned nonce, void* tag);
#define always_inline static inline __attribute__((always_inline))

/**
* Performs constant time comparison between to buffers
* Returns 0 if the first `n` bytes of the two buffers are equal, -1 otherwise
*/
jovanbulck marked this conversation as resolved.
Show resolved Hide resolved
always_inline int constant_time_cmp(const unsigned char *x_,
const unsigned char *y_,
const unsigned int n)
{
const volatile unsigned char *volatile x =
(const volatile unsigned char *volatile) x_;
const volatile unsigned char *volatile y =
(const volatile unsigned char *volatile) y_;
volatile unsigned int d = 0U;
int i;

for (i = 0; i < n; i++) {
d |= x[i] ^ y[i];
}

return (1 & ((d - 1) >> 8)) - 1;
}

/**
* Disable the protection of the calling module.
* DANGEROUS: Disable the protection of the calling module.
*
* NOTE: On Sancus cores that support interruptible enclaves, the
Expand Down Expand Up @@ -481,6 +504,51 @@ always_inline int sancus_wrap(const void* ad, size_t ad_len,
return sancus_wrap_with_key(NULL, ad, ad_len, body, body_len, cipher, tag);
}

/**
* The same as sancus_wrap_with_key() but only produces the MAC of the message.
*/
always_inline int sancus_tag_with_key(const void* key,
const void* body, size_t body_len,
void* tag)
{
return sancus_wrap_with_key(key, body, body_len, NULL, 0, NULL, tag);
}

/**
* The same as sancus_wrap() but only produces the MAC of the message.
*/
always_inline int sancus_tag(const void* body, size_t body_len, void* tag)
{
return sancus_wrap(body, body_len, NULL, 0, NULL, tag);
}

/**
* Verify if the MAC computed over `body` matches with the content of `tag`
*/
always_inline int sancus_untag_with_key(const void* key, const void* body,
size_t body_len, const void* tag)
{
unsigned char computed_tag[SANCUS_TAG_SIZE];

// compute MAC over `body`
if ( !sancus_tag_with_key(key, body, body_len, computed_tag) ) {
return 0;
}

// compare MAC with provided reference `tag`
return constant_time_cmp(tag, computed_tag, SANCUS_TAG_SIZE) == 0;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jovanbulck would this comparison be a security issue as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes good point,it might, so better to avoid this. Since the function already returns an int, no need to do this comparison to zero.

jovanbulck marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Verify if the MAC computed over `body` matches with the content of `tag`
*
* This is the same as sancus_untag_with_key using the key of the caller module.
*/
always_inline int sancus_untag(const void* body, size_t body_len, const void* tag)
{
return sancus_untag_with_key(NULL, body, body_len, tag);
}

/**
* Unwrap a message using the Sancus authenticated encryption features.
*
Expand All @@ -492,6 +560,11 @@ always_inline int sancus_unwrap_with_key(const void* key,
size_t cipher_len,
const void* tag, void* body)
{
// fix: if cipher_len is zero, just compare the MACs using sancus_untag
if(cipher_len == 0) {
return sancus_untag_with_key(key, ad, ad_len, tag);
}

void* ad_end = (char*)ad + ad_len;
void* cipher_end = (char*)cipher + cipher_len;
int ret;
Expand Down Expand Up @@ -532,24 +605,6 @@ always_inline int sancus_unwrap(const void* ad, size_t ad_len,
tag, body);
}

/**
* The same as sancus_wrap() but only produces the MAC of the message.
*/
always_inline int sancus_tag(const void* body, size_t body_len, void* tag)
{
return sancus_wrap(body, body_len, NULL, 0, NULL, tag);
}

/**
* The same as sancus_wrap_with_key() but only produces the MAC of the message.
*/
always_inline int sancus_tag_with_key(const void* key,
const void* body, size_t body_len,
void* tag)
{
return sancus_wrap_with_key(key, body, body_len, NULL, 0, NULL, tag);
}

/**
* Get the Sancus ID of the module loaded at @p addr.
*/
Expand Down Expand Up @@ -582,7 +637,7 @@ always_inline sm_id sancus_get_self_id(void)
* The calling module is defined as the previously executing module. That is,
* the module that entered the currently executing module.
*
* @note This function is implemented as a compiler intrinsic to
* @note This function is implemented as a compiler intrinsic to
* be able to read it from the SM's SSA frame.
*/
sm_id sancus_get_caller_id(void);
Expand Down