Implements the user-facing functions in sigv4.h. More...
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "sigv4.h"
#include "sigv4_internal.h"
#include "sigv4_quicksort.h"
Functions | |
static void | intToAscii (int32_t value, char **pBuffer, size_t bufferLen) |
Converts an integer value to its ASCII representation, and stores the result in the provided buffer. More... | |
static SigV4Status_t | generateCanonicalAndSignedHeaders (const char *pHeaders, size_t headersLen, uint32_t flags, CanonicalContext_t *canonicalRequest, char **pSignedHeaders, size_t *pSignedHeadersLen) |
Extract all header key-value pairs from the passed headers data and add them to the canonical request. More... | |
static SigV4Status_t | appendSignedHeaders (size_t headerCount, uint32_t flags, CanonicalContext_t *canonicalRequest, char **pSignedHeaders, size_t *pSignedHeadersLen) |
Append Signed Headers to the Canonical Request buffer. More... | |
static SigV4Status_t | appendCanonicalizedHeaders (size_t headerCount, uint32_t flags, CanonicalContext_t *canonicalRequest) |
Canonicalize headers and append it to the Canonical Request buffer. More... | |
static SigV4Status_t | parseHeaderKeyValueEntries (const char *pHeaders, size_t headersDataLen, uint32_t flags, size_t *headerCount, CanonicalContext_t *canonicalRequest) |
Parse each header key and value pair from HTTP headers. More... | |
static SigV4Status_t | copyHeaderStringToCanonicalBuffer (const char *pData, size_t dataLen, uint32_t flags, char separator, CanonicalContext_t *canonicalRequest) |
Copy header key or header value to the Canonical Request buffer. More... | |
static bool | isTrimmableSpace (const char *value, size_t index, size_t valLen, size_t trimmedLength) |
Helper function to determine whether a header string character represents a space that can be trimmed when creating "Canonical Headers". All leading and trailing spaces in the header strings need to be trimmed. Also, sequential spaces in the header value need to be trimmed to a single space. More... | |
static SigV4Status_t | generateCanonicalRequestUntilHeaders (const SigV4Parameters_t *pParams, CanonicalContext_t *pCanonicalContext, char **pSignedHeaders, size_t *pSignedHeadersLen) |
Generate the canonical request but excluding the canonical headers and anything that goes after it. Write it onto pSignedHeaders and update it to point to the next location to write the rest of the canonical request. More... | |
static SigV4Status_t | generateAuthorizationValuePrefix (const SigV4Parameters_t *pParams, const char *pAlgorithm, size_t algorithmLen, const char *pSignedHeaders, size_t signedHeadersLen, char *pAuthBuf, size_t *pAuthPrefixLen) |
Generates the prefix of the Authorization header of the format: "<algorithm> Credential=<access key ID>/<credential scope>, SignedHeaders=<SignedHeaders>, Signature=". More... | |
static SigV4Status_t | writeLineToCanonicalRequest (const char *pLine, size_t lineLen, CanonicalContext_t *pCanonicalContext) |
Write a line in the canonical request. More... | |
static void | setQueryParameterKey (size_t currentParameter, const char *pKey, size_t keyLen, CanonicalContext_t *pCanonicalRequest) |
Set a query parameter key in the canonical request. More... | |
static void | setQueryParameterValue (size_t currentParameter, const char *pValue, size_t valueLen, CanonicalContext_t *pCanonicalRequest) |
Set a query parameter value in the canonical request. More... | |
static int32_t | hmacAddKey (HmacContext_t *pHmacContext, const char *pKey, size_t keyLen, bool isKeyPrefix) |
Generates the key for the HMAC operation. More... | |
static int32_t | hmacIntermediate (HmacContext_t *pHmacContext, const char *pData, size_t dataLen) |
Generates the intermediate hash output in the HMAC signing process. This represents the H( K' ^ i_pad || message ) part of the HMAC algorithm. More... | |
static int32_t | hmacFinal (HmacContext_t *pHmacContext, char *pMac, size_t macLen) |
Generates the end output of the HMAC algorithm. More... | |
static int32_t | completeHmac (HmacContext_t *pHmacContext, const char *pKey, size_t keyLen, const char *pData, size_t dataLen, char *pOutput, size_t outputLen) |
Generates the complete HMAC digest given a key and value, then write the digest in the provided output buffer. More... | |
static int32_t | completeHash (const uint8_t *pInput, size_t inputLen, uint8_t *pOutput, size_t outputLen, const SigV4CryptoInterface_t *pCryptoInterface) |
Generates the complete hash of an input string, then write the digest in the provided output buffer. More... | |
static SigV4Status_t | completeHashAndHexEncode (const char *pInput, size_t inputLen, char *pOutput, size_t *pOutputLen, const SigV4CryptoInterface_t *pCryptoInterface) |
Generate the complete hash of an input string, then write the digest in an intermediary buffer before hex encoding and writing it onto pOutput . More... | |
static size_t | writeStringToSignPrefix (char *pBufStart, const char *pAlgorithm, size_t algorithmLen, const char *pDateIso8601) |
Generate the prefix of the string to sign containing the algorithm and date then write it onto pBufStart . More... | |
static SigV4Status_t | writeStringToSign (const SigV4Parameters_t *pParams, const char *pAlgorithm, size_t algorithmLen, CanonicalContext_t *pCanonicalContext) |
Generate the string to sign and write it onto a SigV4String_t. More... | |
static SigV4Status_t | generateSigningKey (const SigV4Parameters_t *pSigV4Params, HmacContext_t *pHmacContext, SigV4String_t *pSigningKey, size_t *pBytesRemaining) |
Generate the signing key and write it onto a SigV4String_t. More... | |
static void | generateCredentialScope (const SigV4Parameters_t *pSigV4Params, SigV4String_t *pCredScope) |
Format the credential scope for the authorization header. Credential scope includes the access key ID, date, region, and service parameters, and ends with "aws4_request" terminator. More... | |
static SigV4Status_t | checkLeap (const SigV4DateTime_t *pDateElements) |
Check if the date represents a valid leap year day. More... | |
static SigV4Status_t | validateDateTime (const SigV4DateTime_t *pDateElements) |
Verify the date stored in a SigV4DateTime_t date representation. More... | |
static void | addToDate (const char formatChar, int32_t result, SigV4DateTime_t *pDateElements) |
Append the value of a date element to the internal date representation structure. More... | |
static SigV4Status_t | scanValue (const char *pDate, const char formatChar, size_t readLoc, size_t lenToRead, SigV4DateTime_t *pDateElements) |
Interpret the value of the specified characters in date, based on the format specifier, and append to the internal date representation. More... | |
static SigV4Status_t | parseDate (const char *pDate, size_t dateLen, const char *pFormat, size_t formatLen, SigV4DateTime_t *pDateElements) |
Parses date according to format string parameter, and populates date representation struct SigV4DateTime_t with its elements. More... | |
static SigV4Status_t | verifyParamsToGenerateAuthHeaderApi (const SigV4Parameters_t *pParams, const char *pAuthBuf, const size_t *authBufLen, char *const *pSignature, const size_t *signatureLen) |
Verify input parameters to the SigV4_GenerateHTTPAuthorization API. More... | |
static void | assignDefaultArguments (const SigV4Parameters_t *pParams, const char **pAlgorithm, size_t *algorithmLen) |
Assign default arguments based on parameters set in pParams . More... | |
static SigV4Status_t | lowercaseHexEncode (const SigV4String_t *pInputStr, SigV4String_t *pHexOutput) |
Hex digest of provided string parameter. More... | |
static size_t | sizeNeededForCredentialScope (const SigV4Parameters_t *pSigV4Params) |
Calculate number of bytes needed for the credential scope. More... | |
static size_t | copyString (char *destination, const char *source, size_t length) |
Copy a string into a char * buffer. More... | |
SigV4Status_t | SigV4_AwsIotDateToIso8601 (const char *pDate, size_t dateLen, char *pDateISO8601, size_t dateISO8601Len) |
Parse the date header value from the AWS IoT response, and generate the formatted ISO 8601 date required for authentication. More... | |
SigV4Status_t | SigV4_GenerateHTTPAuthorization (const SigV4Parameters_t *pParams, char *pAuthBuf, size_t *authBufLen, char **pSignature, size_t *signatureLen) |
Generates the HTTP Authorization header value. More... | |
Implements the user-facing functions in sigv4.h.
|
static |
Converts an integer value to its ASCII representation, and stores the result in the provided buffer.
[in] | value | The value to convert to ASCII. |
[in,out] | pBuffer | The starting location of the buffer on input, and the ending location on output. |
[in] | bufferLen | Width of value to write (padded with leading 0s if necessary). |
|
static |
Extract all header key-value pairs from the passed headers data and add them to the canonical request.
[in] | pHeaders | HTTP headers to canonicalize. |
[in] | headersLen | Length of HTTP headers to canonicalize. |
[in] | flags | Flag to indicate if headers are already in the canonical form. |
[out] | canonicalRequest | Struct to maintain intermediary buffer and state of canonicalization. |
[out] | pSignedHeaders | The starting location of the signed headers. |
[out] | pSignedHeadersLen | The length of the signed headers. |
|
static |
Append Signed Headers to the Canonical Request buffer.
[in] | headerCount | Number of headers which needs to be appended. |
[in] | flags | Flag to indicate if headers are already in the canonical form. |
[in,out] | canonicalRequest | Struct to maintain intermediary buffer and state of canonicalization. |
[out] | pSignedHeaders | The starting location of the signed headers. |
[out] | pSignedHeadersLen | The length of the signed headers. |
|
static |
Canonicalize headers and append it to the Canonical Request buffer.
[in] | headerCount | Number of headers which needs to be appended. |
[in] | flags | Flag to indicate if headers are already in the canonical form. |
[in,out] | canonicalRequest | Struct to maintain intermediary buffer and state of canonicalization. |
|
static |
Parse each header key and value pair from HTTP headers.
[in] | pHeaders | HTTP headers to parse. |
[in] | headersDataLen | Length of HTTP headers to parse. |
[in] | flags | Flag to indicate if headers are already in the canonical form. |
[out] | headerCount | Count of key-value pairs parsed from pData. |
[out] | canonicalRequest | Struct to maintain intermediary buffer and state of canonicalization. |
|
static |
Copy header key or header value to the Canonical Request buffer.
[in] | pData | Header Key or value to be copied to the canonical request. |
[in] | dataLen | Length of Header Key or value. |
[in] | flags | Flag to indicate if headers are already in the canonical form. |
[in] | separator | Character separating the multiple key-value pairs or key and values. |
[in,out] | canonicalRequest | Struct to maintain intermediary buffer and state of canonicalization. |
|
static |
Helper function to determine whether a header string character represents a space that can be trimmed when creating "Canonical Headers". All leading and trailing spaces in the header strings need to be trimmed. Also, sequential spaces in the header value need to be trimmed to a single space.
Example of modifying header field for Canonical Headers: Actual header pair: | Modifier header pair My-Header2: "a b c"
| my-header2:"a b c"
[in] | value | Header value or key string to be trimmed. |
[in] | index | Index of current character. |
[in] | valLen | Length of the string. |
[in] | trimmedLength | Current length of trimmed string. |
true
if the character needs to be trimmed, else false
.
|
static |
Generate the canonical request but excluding the canonical headers and anything that goes after it. Write it onto pSignedHeaders
and update it to point to the next location to write the rest of the canonical request.
[in] | pParams | The application-defined parameters used to generate the canonical request. |
[in] | pCanonicalContext | The context of the canonical request. |
[in,out] | pSignedHeaders | The location to start writing the canonical request and becomes the location to write the rest of it when this function returns. |
[in,out] | pSignedHeadersLen | The amount of buffer available and becomes the number of bytes actually written when this function returns. |
|
static |
Generates the prefix of the Authorization header of the format: "<algorithm> Credential=<access key ID>/<credential scope>, SignedHeaders=<SignedHeaders>, Signature=".
[in] | pParams | The application-defined parameters used to generate the canonical request. |
[in] | pAlgorithm | The signing algorithm used for SigV4 authentication. |
[in] | algorithmLen | The length of pAlgorithm . |
[in] | pSignedHeaders | The signed headers of the SigV4 request. |
[in] | signedHeadersLen | The length of pSignedHeaders . |
[in,out] | pAuthBuf | The authorization buffer where to write the prefix. Pointer is updated with the next location to write the value of the signature. |
[in,out] | pAuthPrefixLen | On input, it should contain the total length of pAuthBuf . On output, this will be filled with the length of the Authorization header, if operation is successful. |
pAuthBuf
is insufficient to store the entire authorization header value (i.e. Prefix + HexEncoded Signature); otherwise SigV4Success.
|
static |
Write a line in the canonical request.
[in] | pLine | The line to write to the canonical request. |
[in] | lineLen | The length of pLine |
[in,out] | pCanonicalContext | The canonical context where the line should be written. |
|
static |
Set a query parameter key in the canonical request.
[in] | currentParameter | The index of the query key to set |
[in] | pKey | The pointer to the query key |
[in] | keyLen | The length of pKey |
[in,out] | pCanonicalRequest | The canonical request containing the query parameter array of keys and values |
|
static |
Set a query parameter value in the canonical request.
[in] | currentParameter | The index of the query value to set |
[in] | pValue | The pointer to the query value |
[in] | valueLen | The length of pValue |
[in,out] | pCanonicalRequest | The canonical request containing the query parameter array of keys and values |
|
static |
Generates the key for the HMAC operation.
[in] | pHmacContext | The context used for HMAC calculation. |
[in] | pKey | The key used as input for HMAC calculation. |
[in] | keyLen | The length of pKey . |
[in] | isKeyPrefix | Flag to indicate whether the passed key is prefix of a complete key for an HMAC operation. If this is a prefix, then it will be stored in cache for use with remaining part of the key that will be provided in a subsequent call to hmacAddKey. |
|
static |
Generates the intermediate hash output in the HMAC signing process. This represents the H( K' ^ i_pad || message ) part of the HMAC algorithm.
[in] | pHmacContext | The context used for HMAC calculation. |
[in] | pData | The data used as input for HMAC calculation. |
[in] | dataLen | The length of pData . |
|
static |
Generates the end output of the HMAC algorithm.
This represents the second hash operation in the HMAC algorithm: H( K' ^ o_pad || Intermediate Hash Output ) where the Intermediate Hash Output is generated from the call to hmacIntermediate.
[in] | pHmacContext | The context used for HMAC calculation. |
[out] | pMac | The buffer onto which to write the HMAC digest. |
[in] | macLen | The length of pMac . |
|
static |
Generates the complete HMAC digest given a key and value, then write the digest in the provided output buffer.
[in] | pHmacContext | The context used for the current HMAC calculation. |
[in] | pKey | The key passed as input to the HMAC function. |
[in] | keyLen | The length of pKey . |
[in] | pData | The data passed as input to the HMAC function. |
[in] | dataLen | The length of pData . |
[out] | pOutput | The buffer onto which to write the HMAC digest. |
[out] | outputLen | The length of pOutput and must be greater than pCryptoInterface->hashDigestLen for this function to succeed. |
|
static |
Generates the complete hash of an input string, then write the digest in the provided output buffer.
[in] | pInput | The data passed as input to the hash function. |
[in] | inputLen | The length of pInput . |
[out] | pOutput | The buffer onto which to write the hash. |
[out] | outputLen | The length of pOutput and must be greater than pCryptoInterface->hashDigestLen for this function to succeed. |
[in] | pCryptoInterface | The interface used to call hash functions. |
|
static |
Generate the complete hash of an input string, then write the digest in an intermediary buffer before hex encoding and writing it onto pOutput
.
[in] | pInput | The data passed as input to the hash function. |
[in] | inputLen | The length of pInput . |
[out] | pOutput | The buffer onto which to write the hex-encoded hash. |
[out] | pOutputLen | The length of pOutput and must be greater than pCryptoInterface->hashDigestLen * 2 for this function to succeed. |
[in] | pCryptoInterface | The interface used to call hash functions. |
|
static |
Generate the prefix of the string to sign containing the algorithm and date then write it onto pBufStart
.
pBufStart
in order to write the algorithm and date.[in] | pBufStart | The starting location of the buffer to write the string to sign. |
[in] | pAlgorithm | The algorithm used for generating the SigV4 signature. |
[in] | algorithmLen | The length of pAlgorithm . |
[in] | pDateIso8601 | The date used as part of the string to sign. |
pBufStart
.
|
static |
Generate the string to sign and write it onto a SigV4String_t.
[in] | pParams | The application-defined parameters used to generate the string to sign. |
[in] | pAlgorithm | The algorithm used for generating the SigV4 signature. |
[in] | algorithmLen | The length of pAlgorithm . |
[in,out] | pCanonicalContext | The context of the canonical request. |
|
static |
Generate the signing key and write it onto a SigV4String_t.
[in] | pSigV4Params | The application-defined parameters used to generate the signing key. |
[in] | pHmacContext | The context used for the current HMAC calculation. |
[out] | pSigningKey | The SigV4String_t onto which the signing key will be written. |
[in,out] | pBytesRemaining | The number of bytes remaining in the canonical buffer. |
pSigningKey
was insufficient to fit the actual signing key, SigV4Success otherwise.
|
static |
Format the credential scope for the authorization header. Credential scope includes the access key ID, date, region, and service parameters, and ends with "aws4_request" terminator.
[in] | pSigV4Params | The application parameters defining the credential's scope. |
[in,out] | pCredScope | The credential scope in the SigV4 format. |
|
static |
Check if the date represents a valid leap year day.
[in] | pDateElements | The date representation to be verified. |
|
static |
Verify the date stored in a SigV4DateTime_t date representation.
[in] | pDateElements | The date representation to be verified. |
|
static |
Append the value of a date element to the internal date representation structure.
[in] | formatChar | The specifier identifying the struct member to fill. |
[in] | result | The value to assign to the specified struct member. |
[out] | pDateElements | The date representation structure to modify. |
|
static |
Interpret the value of the specified characters in date, based on the format specifier, and append to the internal date representation.
[in] | pDate | The date to be parsed. |
[in] | formatChar | The format specifier used to interpret characters. |
[in] | readLoc | The index of pDate to read from. |
[in] | lenToRead | The number of characters to read. |
[out] | pDateElements | The date representation to modify. |
|
static |
Parses date according to format string parameter, and populates date representation struct SigV4DateTime_t with its elements.
[in] | pDate | The date to be parsed. |
[in] | dateLen | Length of pDate, the date to be formatted. |
[in] | pFormat | The format string used to extract date pDateElements from pDate. This string, among other characters, may contain specifiers of the form "%LV", where L is the number of characters to be read, and V is one of {Y, M, D, h, m, s, *}, representing a year, month, day, hour, minute, second, or skipped (un-parsed) value, respectively. |
[in] | formatLen | Length of the format string pFormat. |
[out] | pDateElements | The deconstructed date representation of pDate. |
|
static |
Verify input parameters to the SigV4_GenerateHTTPAuthorization API.
[in] | pParams | Complete SigV4 configurations passed by application. |
[in] | pAuthBuf | The user-supplied buffer for filling Authorization Header. |
[in] | authBufLen | The user-supplied size value of pAuthBuf buffer. |
[in] | pSignature | The user-supplied pointer memory to store starting location of Signature in Authorization Buffer. |
[in] | signatureLen | The user-supplied pointer to store length of Signature. |
|
static |
Assign default arguments based on parameters set in pParams
.
[in] | pParams | Complete SigV4 configurations passed by application. |
[out] | pAlgorithm | The algorithm used for SigV4 authentication. |
[out] | algorithmLen | The length of pAlgorithm . |
|
static |
Hex digest of provided string parameter.
[in] | pInputStr | String to encode. |
[out] | pHexOutput | Hex representation of pInputStr . |
|
static |
Calculate number of bytes needed for the credential scope.
[in] | pSigV4Params | SigV4 configurations passed by application. |
|
static |
Copy a string into a char * buffer.
length
bytes.[in] | destination | The buffer to write. |
[in] | source | String to copy. |
[in] | length | Number of characters to copy. |
length
The number of characters written from source
into destination
. SigV4Status_t SigV4_AwsIotDateToIso8601 | ( | const char * | pDate, |
size_t | dateLen, | ||
char * | pDateISO8601, | ||
size_t | dateISO8601Len | ||
) |
Parse the date header value from the AWS IoT response, and generate the formatted ISO 8601 date required for authentication.
This is an optional utility function available to the application, to assist with formatting of the date header obtained from AWS IoT (when requesting a temporary token or sending a POST request).
AWS SigV4 authentication requires an ISO 8601 date to be present in the "x-amz-date" request header, as well as in the credential scope (must be identical). For additional information on date handling, please see https://docs.aws.amazon.com/general/latest/gr/sigv4-date-handling.html.
Acceptable Input Formats:
Formatted Output:
[in] | pDate | The date header (in RFC 3339 or RFC 5322 formats). An acceptable date header can be found in the HTTP response returned by AWS IoT. This value should use UTC (with no time-zone offset), and be exactly 20 or 29 characters in length (excluding the null character), to comply with RFC 3339 and RFC 5322 formats, respectively. |
[in] | dateLen | The length of the pDate header value. Must be either SIGV4_EXPECTED_LEN_RFC_3339 or SIGV4_EXPECTED_LEN_RFC_5322, for valid input parameters. |
[out] | pDateISO8601 | The formatted ISO8601-compliant date. The date value written to this buffer will be exactly 16 characters in length, to comply with the ISO8601 standard required for SigV4 authentication. |
[in] | dateISO8601Len | The length of buffer pDateISO8601. Must be at least SIGV4_ISO_STRING_LEN bytes, for valid input parameters. |
Example
SigV4Status_t SigV4_GenerateHTTPAuthorization | ( | const SigV4Parameters_t * | pParams, |
char * | pAuthBuf, | ||
size_t * | authBufLen, | ||
char ** | pSignature, | ||
size_t * | signatureLen | ||
) |
Generates the HTTP Authorization header value.
[in] | pParams | Parameters for generating the SigV4 signature. |
[out] | pAuthBuf | Buffer to hold the generated Authorization header value. |
[in,out] | authBufLen | Input: the length of pAuthBuf , output: the length of the authorization value written to the buffer. |
[out] | pSignature | Location of the signature in the authorization string. |
[out] | signatureLen | The length of pSignature . |
Example