SigV4  v1.0.0
SigV4 Library for AWS Authentication
sigv4.c File Reference

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...
 

Detailed Description

Implements the user-facing functions in sigv4.h.

Function Documentation

◆ intToAscii()

static void intToAscii ( int32_t  value,
char **  pBuffer,
size_t  bufferLen 
)
static

Converts an integer value to its ASCII representation, and stores the result in the provided buffer.

Parameters
[in]valueThe value to convert to ASCII.
[in,out]pBufferThe starting location of the buffer on input, and the ending location on output.
[in]bufferLenWidth of value to write (padded with leading 0s if necessary).

◆ generateCanonicalAndSignedHeaders()

static SigV4Status_t generateCanonicalAndSignedHeaders ( const char *  pHeaders,
size_t  headersLen,
uint32_t  flags,
CanonicalContext_t canonicalRequest,
char **  pSignedHeaders,
size_t *  pSignedHeadersLen 
)
static

Extract all header key-value pairs from the passed headers data and add them to the canonical request.

Parameters
[in]pHeadersHTTP headers to canonicalize.
[in]headersLenLength of HTTP headers to canonicalize.
[in]flagsFlag to indicate if headers are already in the canonical form.
[out]canonicalRequestStruct to maintain intermediary buffer and state of canonicalization.
[out]pSignedHeadersThe starting location of the signed headers.
[out]pSignedHeadersLenThe length of the signed headers.
Returns
Following statuses will be returned by the function: SigV4Success if headers are successfully added to the canonical request. SigV4InsufficientMemory if canonical request buffer cannot accommodate the header. SigV4InvalidParameter if HTTP headers are invalid. SigV4MaxHeaderPairCountExceeded if number of headers that needs to be canonicalized exceed the SIGV4_MAX_HTTP_HEADER_COUNT macro defined in the config file.

◆ appendSignedHeaders()

static SigV4Status_t appendSignedHeaders ( size_t  headerCount,
uint32_t  flags,
CanonicalContext_t canonicalRequest,
char **  pSignedHeaders,
size_t *  pSignedHeadersLen 
)
static

Append Signed Headers to the Canonical Request buffer.

Parameters
[in]headerCountNumber of headers which needs to be appended.
[in]flagsFlag to indicate if headers are already in the canonical form.
[in,out]canonicalRequestStruct to maintain intermediary buffer and state of canonicalization.
[out]pSignedHeadersThe starting location of the signed headers.
[out]pSignedHeadersLenThe length of the signed headers.

◆ appendCanonicalizedHeaders()

static SigV4Status_t appendCanonicalizedHeaders ( size_t  headerCount,
uint32_t  flags,
CanonicalContext_t canonicalRequest 
)
static

Canonicalize headers and append it to the Canonical Request buffer.

Parameters
[in]headerCountNumber of headers which needs to be appended.
[in]flagsFlag to indicate if headers are already in the canonical form.
[in,out]canonicalRequestStruct to maintain intermediary buffer and state of canonicalization.
Returns
Following statuses will be returned by the function: SigV4Success if headers are successfully added to the canonical request. SigV4InsufficientMemory if canonical request buffer cannot accommodate the header.

◆ parseHeaderKeyValueEntries()

static SigV4Status_t parseHeaderKeyValueEntries ( const char *  pHeaders,
size_t  headersDataLen,
uint32_t  flags,
size_t *  headerCount,
CanonicalContext_t canonicalRequest 
)
static

Parse each header key and value pair from HTTP headers.

Parameters
[in]pHeadersHTTP headers to parse.
[in]headersDataLenLength of HTTP headers to parse.
[in]flagsFlag to indicate if headers are already in the canonical form.
[out]headerCountCount of key-value pairs parsed from pData.
[out]canonicalRequestStruct to maintain intermediary buffer and state of canonicalization.
Returns
Following statuses will be returned by the function: SigV4Success if header key or value is successfully added to the canonical request. SigV4InsufficientMemory if canonical request buffer cannot accommodate the header. SigV4MaxHeaderPairCountExceeded if number of key-value entries in the headers data exceeds the SIGV4_MAX_HTTP_HEADER_COUNT macro defined in the config file.

◆ copyHeaderStringToCanonicalBuffer()

static SigV4Status_t copyHeaderStringToCanonicalBuffer ( const char *  pData,
size_t  dataLen,
uint32_t  flags,
char  separator,
CanonicalContext_t canonicalRequest 
)
static

Copy header key or header value to the Canonical Request buffer.

Parameters
[in]pDataHeader Key or value to be copied to the canonical request.
[in]dataLenLength of Header Key or value.
[in]flagsFlag to indicate if headers are already in the canonical form.
[in]separatorCharacter separating the multiple key-value pairs or key and values.
[in,out]canonicalRequestStruct to maintain intermediary buffer and state of canonicalization.
Returns
Following statuses will be returned by the function: SigV4Success if the headers are successfully added to the canonical request. SigV4InsufficientMemory if canonical request buffer cannot accommodate the header.

◆ isTrimmableSpace()

static bool isTrimmableSpace ( const char *  value,
size_t  index,
size_t  valLen,
size_t  trimmedLength 
)
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"

Parameters
[in]valueHeader value or key string to be trimmed.
[in]indexIndex of current character.
[in]valLenLength of the string.
[in]trimmedLengthCurrent length of trimmed string.
Returns
true if the character needs to be trimmed, else false.

◆ generateCanonicalRequestUntilHeaders()

static SigV4Status_t generateCanonicalRequestUntilHeaders ( const SigV4Parameters_t pParams,
CanonicalContext_t pCanonicalContext,
char **  pSignedHeaders,
size_t *  pSignedHeadersLen 
)
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.

Parameters
[in]pParamsThe application-defined parameters used to generate the canonical request.
[in]pCanonicalContextThe context of the canonical request.
[in,out]pSignedHeadersThe location to start writing the canonical request and becomes the location to write the rest of it when this function returns.
[in,out]pSignedHeadersLenThe amount of buffer available and becomes the number of bytes actually written when this function returns.
Returns
SigV4InsufficientMemory if the length of the canonical request output buffer cannot fit the actual request before the headers, SigV4Success otherwise.

◆ generateAuthorizationValuePrefix()

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 
)
static

Generates the prefix of the Authorization header of the format: "<algorithm> Credential=<access key ID>/<credential scope>, SignedHeaders=<SignedHeaders>, Signature=".

Parameters
[in]pParamsThe application-defined parameters used to generate the canonical request.
[in]pAlgorithmThe signing algorithm used for SigV4 authentication.
[in]algorithmLenThe length of pAlgorithm.
[in]pSignedHeadersThe signed headers of the SigV4 request.
[in]signedHeadersLenThe length of pSignedHeaders.
[in,out]pAuthBufThe authorization buffer where to write the prefix. Pointer is updated with the next location to write the value of the signature.
[in,out]pAuthPrefixLenOn 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.
Returns
SigV4InsufficientMemory if the length of the authorization buffer, pAuthBuf is insufficient to store the entire authorization header value (i.e. Prefix + HexEncoded Signature); otherwise SigV4Success.

◆ writeLineToCanonicalRequest()

static SigV4Status_t writeLineToCanonicalRequest ( const char *  pLine,
size_t  lineLen,
CanonicalContext_t pCanonicalContext 
)
static

Write a line in the canonical request.

Note
Used whenever there are components of the request that are already canonicalized.
Parameters
[in]pLineThe line to write to the canonical request.
[in]lineLenThe length of pLine
[in,out]pCanonicalContextThe canonical context where the line should be written.
Returns
SigV4InsufficientMemory if the length of the canonical request buffer cannot write the desired line, SigV4Success otherwise.

◆ setQueryParameterKey()

static void setQueryParameterKey ( size_t  currentParameter,
const char *  pKey,
size_t  keyLen,
CanonicalContext_t pCanonicalRequest 
)
static

Set a query parameter key in the canonical request.

Parameters
[in]currentParameterThe index of the query key to set
[in]pKeyThe pointer to the query key
[in]keyLenThe length of pKey
[in,out]pCanonicalRequestThe canonical request containing the query parameter array of keys and values

◆ setQueryParameterValue()

static void setQueryParameterValue ( size_t  currentParameter,
const char *  pValue,
size_t  valueLen,
CanonicalContext_t pCanonicalRequest 
)
static

Set a query parameter value in the canonical request.

Parameters
[in]currentParameterThe index of the query value to set
[in]pValueThe pointer to the query value
[in]valueLenThe length of pValue
[in,out]pCanonicalRequestThe canonical request containing the query parameter array of keys and values

◆ hmacAddKey()

static int32_t hmacAddKey ( HmacContext_t pHmacContext,
const char *  pKey,
size_t  keyLen,
bool  isKeyPrefix 
)
static

Generates the key for the HMAC operation.

Note
This function can be called multiple times before calling hmacIntermediate. Appending multiple substrings, then calling hmacAddKey on the appended string is also equivalent to calling hmacAddKey on each individual substring.
This function accepts a const char * so that string literals can be passed in.
Parameters
[in]pHmacContextThe context used for HMAC calculation.
[in]pKeyThe key used as input for HMAC calculation.
[in]keyLenThe length of pKey.
[in]isKeyPrefixFlag 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.
Returns
Zero on success, all other return values are failures.

◆ hmacIntermediate()

static int32_t hmacIntermediate ( HmacContext_t pHmacContext,
const char *  pData,
size_t  dataLen 
)
static

Generates the intermediate hash output in the HMAC signing process. This represents the H( K' ^ i_pad || message ) part of the HMAC algorithm.

Note
This MUST be ONLY called after hmacAddKey; otherwise results in undefined behavior. Likewise, one SHOULD NOT call hmacAddKey after calling hmacIntermediate. One must call hmacFinal first before calling hmacAddKey again.
Parameters
[in]pHmacContextThe context used for HMAC calculation.
[in]pDataThe data used as input for HMAC calculation.
[in]dataLenThe length of pData.
Returns
Zero on success, all other return values are failures.

◆ hmacFinal()

static int32_t hmacFinal ( HmacContext_t pHmacContext,
char *  pMac,
size_t  macLen 
)
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.

Parameters
[in]pHmacContextThe context used for HMAC calculation.
[out]pMacThe buffer onto which to write the HMAC digest.
[in]macLenThe length of pMac.
Returns
Zero on success, all other return values are failures.

◆ completeHmac()

static int32_t completeHmac ( HmacContext_t pHmacContext,
const char *  pKey,
size_t  keyLen,
const char *  pData,
size_t  dataLen,
char *  pOutput,
size_t  outputLen 
)
static

Generates the complete HMAC digest given a key and value, then write the digest in the provided output buffer.

Parameters
[in]pHmacContextThe context used for the current HMAC calculation.
[in]pKeyThe key passed as input to the HMAC function.
[in]keyLenThe length of pKey.
[in]pDataThe data passed as input to the HMAC function.
[in]dataLenThe length of pData.
[out]pOutputThe buffer onto which to write the HMAC digest.
[out]outputLenThe length of pOutput and must be greater than pCryptoInterface->hashDigestLen for this function to succeed.
Returns
Zero on success, all other return values are failures.

◆ completeHash()

static int32_t completeHash ( const uint8_t *  pInput,
size_t  inputLen,
uint8_t *  pOutput,
size_t  outputLen,
const SigV4CryptoInterface_t pCryptoInterface 
)
static

Generates the complete hash of an input string, then write the digest in the provided output buffer.

Note
Unlike completeHashAndHexEncode, this function will not encode the hash and will simply output the bytes written by the hash function.
Parameters
[in]pInputThe data passed as input to the hash function.
[in]inputLenThe length of pInput.
[out]pOutputThe buffer onto which to write the hash.
[out]outputLenThe length of pOutput and must be greater than pCryptoInterface->hashDigestLen for this function to succeed.
[in]pCryptoInterfaceThe interface used to call hash functions.
Returns
Zero on success, all other return values are failures.

◆ completeHashAndHexEncode()

static SigV4Status_t completeHashAndHexEncode ( const char *  pInput,
size_t  inputLen,
char *  pOutput,
size_t *  pOutputLen,
const SigV4CryptoInterface_t pCryptoInterface 
)
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.

Parameters
[in]pInputThe data passed as input to the hash function.
[in]inputLenThe length of pInput.
[out]pOutputThe buffer onto which to write the hex-encoded hash.
[out]pOutputLenThe length of pOutput and must be greater than pCryptoInterface->hashDigestLen * 2 for this function to succeed.
[in]pCryptoInterfaceThe interface used to call hash functions.
Returns
Zero on success, all other return values are failures.

◆ writeStringToSignPrefix()

static size_t writeStringToSignPrefix ( char *  pBufStart,
const char *  pAlgorithm,
size_t  algorithmLen,
const char *  pDateIso8601 
)
static

Generate the prefix of the string to sign containing the algorithm and date then write it onto pBufStart.

Note
This function assumes that enough bytes remain in pBufStart in order to write the algorithm and date.
Parameters
[in]pBufStartThe starting location of the buffer to write the string to sign.
[in]pAlgorithmThe algorithm used for generating the SigV4 signature.
[in]algorithmLenThe length of pAlgorithm.
[in]pDateIso8601The date used as part of the string to sign.
Returns
The number of bytes written to pBufStart.

◆ writeStringToSign()

static SigV4Status_t writeStringToSign ( const SigV4Parameters_t pParams,
const char *  pAlgorithm,
size_t  algorithmLen,
CanonicalContext_t pCanonicalContext 
)
static

Generate the string to sign and write it onto a SigV4String_t.

Parameters
[in]pParamsThe application-defined parameters used to generate the string to sign.
[in]pAlgorithmThe algorithm used for generating the SigV4 signature.
[in]algorithmLenThe length of pAlgorithm.
[in,out]pCanonicalContextThe context of the canonical request.
Returns
SigV4InsufficientMemory if the length of the canonical request output buffer cannot fit the string to sign, SigV4Success otherwise.

◆ generateSigningKey()

static SigV4Status_t generateSigningKey ( const SigV4Parameters_t pSigV4Params,
HmacContext_t pHmacContext,
SigV4String_t pSigningKey,
size_t *  pBytesRemaining 
)
static

Generate the signing key and write it onto a SigV4String_t.

Parameters
[in]pSigV4ParamsThe application-defined parameters used to generate the signing key.
[in]pHmacContextThe context used for the current HMAC calculation.
[out]pSigningKeyThe SigV4String_t onto which the signing key will be written.
[in,out]pBytesRemainingThe number of bytes remaining in the canonical buffer.
Returns
SigV4InsufficientMemory if the length of pSigningKey was insufficient to fit the actual signing key, SigV4Success otherwise.

◆ generateCredentialScope()

static void generateCredentialScope ( const SigV4Parameters_t pSigV4Params,
SigV4String_t pCredScope 
)
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.

Parameters
[in]pSigV4ParamsThe application parameters defining the credential's scope.
[in,out]pCredScopeThe credential scope in the SigV4 format.

◆ checkLeap()

static SigV4Status_t checkLeap ( const SigV4DateTime_t pDateElements)
static

Check if the date represents a valid leap year day.

Parameters
[in]pDateElementsThe date representation to be verified.
Returns
SigV4Success if the date corresponds to a valid leap year, SigV4ISOFormattingError otherwise.

◆ validateDateTime()

static SigV4Status_t validateDateTime ( const SigV4DateTime_t pDateElements)
static

Verify the date stored in a SigV4DateTime_t date representation.

Parameters
[in]pDateElementsThe date representation to be verified.
Returns
SigV4Success if the date is valid, and SigV4ISOFormattingError if any member of SigV4DateTime_t is invalid or represents an out-of-range date.

◆ addToDate()

static void addToDate ( const char  formatChar,
int32_t  result,
SigV4DateTime_t pDateElements 
)
static

Append the value of a date element to the internal date representation structure.

Parameters
[in]formatCharThe specifier identifying the struct member to fill.
[in]resultThe value to assign to the specified struct member.
[out]pDateElementsThe date representation structure to modify.

◆ scanValue()

static SigV4Status_t scanValue ( const char *  pDate,
const char  formatChar,
size_t  readLoc,
size_t  lenToRead,
SigV4DateTime_t pDateElements 
)
static

Interpret the value of the specified characters in date, based on the format specifier, and append to the internal date representation.

Parameters
[in]pDateThe date to be parsed.
[in]formatCharThe format specifier used to interpret characters.
[in]readLocThe index of pDate to read from.
[in]lenToReadThe number of characters to read.
[out]pDateElementsThe date representation to modify.
Returns
SigV4Success if parsing succeeded, SigV4ISOFormattingError if the characters read did not match the format specifier.

◆ parseDate()

static SigV4Status_t parseDate ( const char *  pDate,
size_t  dateLen,
const char *  pFormat,
size_t  formatLen,
SigV4DateTime_t pDateElements 
)
static

Parses date according to format string parameter, and populates date representation struct SigV4DateTime_t with its elements.

Parameters
[in]pDateThe date to be parsed.
[in]dateLenLength of pDate, the date to be formatted.
[in]pFormatThe 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]formatLenLength of the format string pFormat.
[out]pDateElementsThe deconstructed date representation of pDate.
Returns
SigV4Success if all format specifiers were matched successfully, SigV4ISOFormattingError otherwise.

◆ verifyParamsToGenerateAuthHeaderApi()

static SigV4Status_t verifyParamsToGenerateAuthHeaderApi ( const SigV4Parameters_t pParams,
const char *  pAuthBuf,
const size_t *  authBufLen,
char *const *  pSignature,
const size_t *  signatureLen 
)
static

Verify input parameters to the SigV4_GenerateHTTPAuthorization API.

Parameters
[in]pParamsComplete SigV4 configurations passed by application.
[in]pAuthBufThe user-supplied buffer for filling Authorization Header.
[in]authBufLenThe user-supplied size value of pAuthBuf buffer.
[in]pSignatureThe user-supplied pointer memory to store starting location of Signature in Authorization Buffer.
[in]signatureLenThe user-supplied pointer to store length of Signature.
Returns
SigV4Success if successful, SigV4InvalidParameter otherwise.

◆ assignDefaultArguments()

static void assignDefaultArguments ( const SigV4Parameters_t pParams,
const char **  pAlgorithm,
size_t *  algorithmLen 
)
static

Assign default arguments based on parameters set in pParams.

Parameters
[in]pParamsComplete SigV4 configurations passed by application.
[out]pAlgorithmThe algorithm used for SigV4 authentication.
[out]algorithmLenThe length of pAlgorithm.

◆ lowercaseHexEncode()

static SigV4Status_t lowercaseHexEncode ( const SigV4String_t pInputStr,
SigV4String_t pHexOutput 
)
static

Hex digest of provided string parameter.

Parameters
[in]pInputStrString to encode.
[out]pHexOutputHex representation of pInputStr.
Returns
SigV4Success if successful, SigV4InsufficientMemory otherwise.

◆ sizeNeededForCredentialScope()

static size_t sizeNeededForCredentialScope ( const SigV4Parameters_t pSigV4Params)
static

Calculate number of bytes needed for the credential scope.

Note
This does not include the linefeed character.
Parameters
[in]pSigV4ParamsSigV4 configurations passed by application.
Returns
Number of bytes needed for credential scope.

◆ copyString()

static size_t copyString ( char *  destination,
const char *  source,
size_t  length 
)
static

Copy a string into a char * buffer.

Note
This function can be used to copy a string literal without MISRA warnings.
This function assumes the destination buffer is large enough to hold the string to copy, so will always write length bytes.
Parameters
[in]destinationThe buffer to write.
[in]sourceString to copy.
[in]lengthNumber of characters to copy.
Returns
length The number of characters written from source into destination.

◆ SigV4_AwsIotDateToIso8601()

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:

  • RFC 5322 (ex. "Thu, 18 Jan 2018 09:18:06 GMT"), the preferred format in HTTP 'Date' response headers. If using this format, the date parameter should match "***, DD 'MMM' YYYY hh:mm:ss GMT" exactly.
  • RFC 3339 (ex. "2018-01-18T09:18:06Z"), found occasionally in 'Date' and expiration headers. If using this format, the date parameter should match "YYYY-MM-DD'T'hh:mm:ss'Z'" exactly.

Formatted Output:

  • The ISO8601-formatted date will be returned in the form "YYYYMMDD'T'HHMMSS'Z'" (ex. "20180118T091806Z").
Parameters
[in]pDateThe 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]dateLenThe 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]pDateISO8601The 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]dateISO8601LenThe length of buffer pDateISO8601. Must be at least SIGV4_ISO_STRING_LEN bytes, for valid input parameters.
Returns
SigV4Success code if successful, error code otherwise.

Example

// The following example shows how to use the SigV4_AwsIotDateToIso8601
// function to convert an AWS IoT date header value to a ISO 8601 date.
char pDateISO8601[SIGV4_ISO_STRING_LEN] = {0};
size_t pDateISO8601Len = SIGV4_ISO_STRING_LEN;
// pDate and dateLen are the date header and length which are parsed from
// an AWS IoT Credential Provider HTTP response, using an HTTP library.
status = SigV4_AwsIotDateToIso8601( pDate, dateLen, pDateISO8601, pDateISO8601Len );
if( status != SigV4Success )
{
// Failed to parse date
}

◆ SigV4_GenerateHTTPAuthorization()

SigV4Status_t SigV4_GenerateHTTPAuthorization ( const SigV4Parameters_t pParams,
char *  pAuthBuf,
size_t *  authBufLen,
char **  pSignature,
size_t *  signatureLen 
)

Generates the HTTP Authorization header value.

Note
The API does not support HTTP headers containing empty HTTP header keys or values.
Parameters
[in]pParamsParameters for generating the SigV4 signature.
[out]pAuthBufBuffer to hold the generated Authorization header value.
[in,out]authBufLenInput: the length of pAuthBuf, output: the length of the authorization value written to the buffer.
[out]pSignatureLocation of the signature in the authorization string.
[out]signatureLenThe length of pSignature.
Returns
SigV4Success if successful, error code otherwise.

Example

// The following example shows how to use the SigV4_GenerateHTTPAuthorization
// function to generate the HTTP Authorization header value for HTTP requests
// to AWS services requiring SigV4 authentication.
// Buffer to hold the authorization header.
char pSigv4Auth[ 2048U ];
size_t sigv4AuthLen = sizeof( pSigv4Auth );
// Pointer to signature in the Authorization header that will be populated in
// pSigv4Auth by the SigV4_GenerateHTTPAuthorization API function.
char * signature = NULL;
size_t signatureLen = 0;
SigV4Parameters_t sigv4Params =
{
// Parsed temporary credentials obtained from AWS IoT Credential Provider.
.pCredentials = &sigv4Creds,
// Date in ISO8601 format.
.pDateIso8601 = pDateISO8601,
// The AWS region for the request.
.pRegion = AWS_REGION,
.regionLen = strlen( AWS_REGION ),
// The AWS service for the request.
.pService = AWS_SERVICE_NAME,
.serviceLen = strlen( AWS_SERVICE_NAME ),
// SigV4 crypto interface. See SigV4CryptoInterface_t interface documentation.
.pCryptoInterface = &cryptoInterface,
// HTTP parameters for the HTTP request to generate a SigV4 authorization header for.
.pHttpParameters = &sigv4HttpParams
};
status = SigV4_GenerateHTTPAuthorization( &sigv4Params, pSigv4Auth, &sigv4AuthLen, &signature, &signatureLen );
if( status != SigV4Success )
{
// Failed to generate authorization header.
}
SigV4_GenerateHTTPAuthorization
SigV4Status_t SigV4_GenerateHTTPAuthorization(const SigV4Parameters_t *pParams, char *pAuthBuf, size_t *authBufLen, char **pSignature, size_t *signatureLen)
Generates the HTTP Authorization header value.
Definition: sigv4.c:3000
SigV4Success
@ SigV4Success
The SigV4 Utility library function completed successfully.
Definition: sigv4.h:135
SIGV4_ISO_STRING_LEN
#define SIGV4_ISO_STRING_LEN
Definition: sigv4.h:70
SigV4Parameters_t
Complete configurations required for generating "String to Sign" and "Signing Key" values.
Definition: sigv4.h:369
SigV4Parameters_t::pCredentials
SigV4Credentials_t * pCredentials
The AccessKeyId, SecretAccessKey, and SecurityToken used to generate the Authorization header.
Definition: sigv4.h:374
SigV4_AwsIotDateToIso8601
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 requi...
Definition: sigv4.c:2924
SigV4Status_t
SigV4Status_t
Return status of the SigV4 Utility Library.
Definition: sigv4.h:127