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

Canonicalize and Generate A String to Sign #5

Closed
wants to merge 4 commits into from

Conversation

sukhmanm
Copy link
Contributor

@sukhmanm sukhmanm commented Mar 17, 2021

Description of changes: Adding internal functions used in constructing the canonicalized strings matching those created service-side for signature verification.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

*/
SigV4Status_t SigV4_AwsIotDateToIso8601( const char * pDate,
size_t dateLen,
char pDateISO8601[ 17 ] );
Copy link

Choose a reason for hiding this comment

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

I guess this change will be rebased based on the recent updates in PR #3

* @param[in] pURI The URI string to encode.
* @param[in] uriLen Length of pURI.
* @param[out] pCanonicalURI The resulting canonicalized URI.
* @param[in, out] canonicalURILen input: the length of pCanonicalURI,
Copy link

Choose a reason for hiding this comment

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

Suggested change
* @param[in, out] canonicalURILen input: the length of pCanonicalURI,
* @param[in, out] canonicalURILen input: the length of pCanonicalURI buffer,

*
* @param[in] pURI The URI string to encode.
* @param[in] uriLen Length of pURI.
* @param[out] pCanonicalURI The resulting canonicalized URI.
Copy link

Choose a reason for hiding this comment

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

Minor: I prefer keeping the output params at the end. Not a fan of mixing the in and out params in the function.

* encoding should be done once or twice. For example, S3 requires that the
* URI is encoded only once, while other services encode twice.
* @param[in, out] canonicalRequest Struct to maintain intermediary buffer
* and state of canonicalization.
Copy link

Choose a reason for hiding this comment

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

It will be better to specify what is the input and output for this param.

* @param[in] uriLen Length of pURI.
* @param[in] encodeOnce Service-dependent option to indicate whether
* encoding should be done once or twice. For example, S3 requires that the
* URI is encoded only once, while other services encode twice.
Copy link

Choose a reason for hiding this comment

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

Is it always encode once vs twice?

canonicalContext_t * canonicalRequest );

/**
* @brief Canonicalize the query string HTTP URL, beginning (but not
Copy link

Choose a reason for hiding this comment

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

Suggested change
* @brief Canonicalize the query string HTTP URL, beginning (but not
* @brief Canonicalize the query string in HTTP URL, beginning (but not

/*-----------------------------------------------------------*/

/* Converts a hex character to its integer value */
static char hexToInt( char pHex )
Copy link

Choose a reason for hiding this comment

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

Did you intend to use int/int8_t as the return type here?

/* Converts a hex character to its integer value */
static char hexToInt( char pHex )
{
return isdigit( pHex ) ? pHex - '0' : tolower( pHex ) - 'a' + 10;
Copy link

Choose a reason for hiding this comment

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

Don't we have to ensure that the character is only through a-f as well here?

}

/* Converts an integer value to its hex character */
static char intToHex( char pInt )
Copy link

Choose a reason for hiding this comment

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

Did you intend to use integer as a param here?

{
static char hex[] = "0123456789abcdef";

return hex[ pInt & 15 ];
Copy link

@leegeth leegeth Mar 19, 2021

Choose a reason for hiding this comment

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

Don't we have to make sure that the integer is below 16?

assert( pURI != NULL );
assert( pCanonicalURI != NULL );
assert( canonicalURILen != NULL );
assert( *canonicalURILen > 0U );
Copy link

Choose a reason for hiding this comment

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

can the uriLen be non zero?

}
else
{
*pBufLoc++ = '%', *pBufLoc++ = intToHex( *pURILoc >> 4 ), *pBufLoc++ = intToHex( *pURILoc & 15 );
Copy link

Choose a reason for hiding this comment

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

What does this case handle? Can you please add comments about the details of the operations to make it more readable.?
What does ',' do here?

index++;
}

*canonicalURILen = index;
Copy link

@leegeth leegeth Mar 19, 2021

Choose a reason for hiding this comment

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

Please make sure in the loop above, we are not writing out of the bounds of the buffer.

assert( pURI != NULL );
assert( canonicalRequest != NULL );

encodeURI( pURI, uriLen, pBufLoc, &encodedLen, false, true );
Copy link

Choose a reason for hiding this comment

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

The documentation of the function mentions about passing the bufer length as the input as well. Does the logic need update to do that?

if( !encodeOnce )
{
encodeURI( pBufLoc, encodedLen, pBufLoc + encodedLen, &remainingLen, false, true );
memmove( canonicalRequest->pBufCur + encodedLen, canonicalRequest->pBufCur, remainingLen );
Copy link

Choose a reason for hiding this comment

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

Why is this memmove required? Is the src and dst pointers reversed here?

memmove( canonicalRequest->pBufCur + encodedLen, canonicalRequest->pBufCur, remainingLen );
}

canonicalRequest->pBufCur += remainingLen;
Copy link

Choose a reason for hiding this comment

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

I think this will be correct only if the encodeOnce is false.

}

canonicalRequest->pBufCur += remainingLen;
*( canonicalRequest->pBufCur++ ) = '\n';
Copy link

Choose a reason for hiding this comment

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

please check for a possible buffer overflow before writing to the buffer.


int compare = strcmp( token_a, token_b );

if( strcmp == 0 )
Copy link

Choose a reason for hiding this comment

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

compare?

assert( token_b != NULL );

compare = strcmp( token_a, token_b );
}
Copy link

@leegeth leegeth Mar 19, 2021

Choose a reason for hiding this comment

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

Not sure if I understood the meaning of this if condition

Copy link

Choose a reason for hiding this comment

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

Adding doxygen comments for all the static functions in this file similar to those already present at the top of the file, would help to improve the readability of the code.


while( tokenQueries != NULL )
{
canonicalRequest->pQueryLoc[ index ] = &tokenQueries[ 0 ];
Copy link

Choose a reason for hiding this comment

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

what is the size of the array pQueryLoc?

index++;
}

qsort( canonicalRequest->pQueryLoc, index, cmpFun );
Copy link

Choose a reason for hiding this comment

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

I think now I understand what the cmpFunc is for. However, more comments would help for that function.


if( tokenParams != NULL )
{
encodeURI( tokenParams, strlen( tokenParams ), pBufLoc, &remainingLen, true, false );
Copy link

Choose a reason for hiding this comment

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

is tokenParams null terminated? If not, strlen will fail to work.


static SigV4Status_t verifySigV4Parameters( const SigV4Parameters_t * pParams )
{
SigV4Status_t returnStatus = SigV4Success;
Copy link

Choose a reason for hiding this comment

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

Initializing to SigV4InvalidParameter will be better here and code can be reduced that way

* <b>Possible values:</b> Any positive 32 bit integer. <br>
* <b>Default value:</b> `1024`
*/
#ifndef SIGV4_PROCESSING_BUFFER_LENGTH
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this a fixed size required for the operations it is used in? If yes, should it be a config value?

Comment on lines +81 to +82
* @brief Macro defining the digest length of the specified hash function, used
* to determine the length of the output buffer.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @brief Macro defining the digest length of the specified hash function, used
* to determine the length of the output buffer.
* @brief Macro defining the digest length (in bytes) of the specified hash function, used
* to determine the length of the output buffer.

* <b>Possible values:</b> Any positive 32 bit integer. <br>
* <b>Default value:</b> `100`
*/
#ifndef SIGV4_MAX_HTTP_HEADER_COUNT
Copy link
Contributor

Choose a reason for hiding this comment

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

How is the default value of 100 chosen?

@@ -0,0 +1,183 @@
/*
* SigV4 Utility Library v1.0.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copy link
Contributor

@aggarw13 aggarw13 Mar 19, 2021

Choose a reason for hiding this comment

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

Change is relevant across the board

Suggested change
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.

* to determine the length of the output buffer.
*
* This macro should be updated if using a hashing algorithm other than SHA256
* (32 byte digest length). For example, SHA512 would require this macro to be
Copy link
Contributor

Choose a reason for hiding this comment

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

Is HMAC-SHA512 algorithm supported in SigV4? If yes, would that require a macro equivalent of the SIGV4_AWS4_HMAC_SHA256 macro for SHA256?

Comment on lines +53 to +62
#define SIGV4_AWS4_HMAC_SHA256 "AWS4-HMAC-SHA256"

/**< AWS identifier for S3 SigV4 streaming upload. */
#define SIGV4_STREAMING_AWS4_HMAC_SHA256_PAYLOAD "STREAMING-AWS4-HMAC-SHA256-PAYLOAD"

/**< AWS identifiers for Amazon specific HTTP header fields. */
#define SIGV4_HTTP_X_AMZ_DATE_HEADER "x-amz-date"
#define SIGV4_HTTP_X_AMZ_SECURITY_TOKEN_HEADER "x-amz-security-token"
#define SIGV4_HTTP_X_AMZ_CONTENT_SHA256_HEADER "x-amz-content-sha256"
#define SIGV4_HTTP_X_AMZ_STORAGE_CLASS_HEADER "x-amz-storage-class"
Copy link
Contributor

Choose a reason for hiding this comment

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

Can these be internal constants instead of exposing in the public API?

* @brief The date in ISO 8601 format, e.g. "20150830T123600Z". This is
* always 16 characters long.
*/
const char * pDateIso8601;
Copy link
Contributor

@aggarw13 aggarw13 Mar 19, 2021

Choose a reason for hiding this comment

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

If the date buffer is fixed, having it defined explicitly would be helpful for the user.

Suggested change
const char * pDateIso8601;
const char pDateIso8601[16];

@sukhmanm sukhmanm closed this Jun 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants