in source/sigv4.c [3181:3288]
SigV4Status_t SigV4_GenerateHTTPAuthorization( const SigV4Parameters_t * pParams,
char * pAuthBuf,
size_t * authBufLen,
char ** pSignature,
size_t * signatureLen )
{
SigV4Status_t returnStatus = SigV4Success;
CanonicalContext_t canonicalContext;
const char * pAlgorithm = NULL;
char * pSignedHeaders = NULL;
size_t algorithmLen = 0U, signedHeadersLen = 0U, authPrefixLen = 0U;
HmacContext_t hmacContext = { 0 };
SigV4String_t signingKey;
ptrdiff_t bufferLen;
returnStatus = verifyParamsToGenerateAuthHeaderApi( pParams,
pAuthBuf, authBufLen,
pSignature, signatureLen );
if( returnStatus == SigV4Success )
{
assignDefaultArguments( pParams, &pAlgorithm, &algorithmLen );
}
if( returnStatus == SigV4Success )
{
returnStatus = generateCanonicalRequestUntilHeaders( pParams, &canonicalContext,
&pSignedHeaders,
&signedHeadersLen );
}
/* Hash and hex-encode the canonical request to the buffer. */
if( returnStatus == SigV4Success )
{
/* Write HTTP request payload hash to the canonical request. */
returnStatus = writePayloadHashToCanonicalRequest( pParams, &canonicalContext );
}
/* Write the prefix of the Authorizaton header value. */
if( returnStatus == SigV4Success )
{
LogDebug( ( "Generated Canonical Request: %.*s",
( unsigned int ) ( ( uint8_t * ) canonicalContext.pBufCur - canonicalContext.pBufProcessing ),
canonicalContext.pBufProcessing ) );
authPrefixLen = *authBufLen;
returnStatus = generateAuthorizationValuePrefix( pParams,
pAlgorithm, algorithmLen,
pSignedHeaders, signedHeadersLen,
pAuthBuf, &authPrefixLen );
}
/* Write string to sign. */
if( returnStatus == SigV4Success )
{
returnStatus = writeStringToSign( pParams, pAlgorithm, algorithmLen, &canonicalContext );
}
/* Write the signing key. The is done by computing the following function
* where the + operator means concatenation:
* HMAC(HMAC(HMAC(HMAC("AWS4" + kSecret,pDate),pRegion),pService),"aws4_request") */
if( returnStatus == SigV4Success )
{
hmacContext.pCryptoInterface = pParams->pCryptoInterface;
signingKey.pData = canonicalContext.pBufCur;
signingKey.dataLen = canonicalContext.bufRemaining;
returnStatus = generateSigningKey( pParams,
&hmacContext,
&signingKey,
&canonicalContext.bufRemaining );
}
/* Use the SigningKey and StringToSign to produce the final signature.
* Note that the StringToSign starts from the beginning of the processing buffer. */
if( returnStatus == SigV4Success )
{
bufferLen = canonicalContext.pBufCur - ( char * ) canonicalContext.pBufProcessing;
returnStatus = ( completeHmac( &hmacContext,
signingKey.pData,
signingKey.dataLen,
( char * ) canonicalContext.pBufProcessing,
( size_t ) bufferLen,
canonicalContext.pBufCur,
pParams->pCryptoInterface->hashDigestLen ) != 0 )
? SigV4HashError : SigV4Success;
}
/* Hex-encode the final signature beforehand to its precalculated
* location in the buffer provided for the Authorizaton header value. */
if( returnStatus == SigV4Success )
{
SigV4String_t originalHmac;
SigV4String_t hexEncodedHmac;
originalHmac.pData = canonicalContext.pBufCur;
originalHmac.dataLen = pParams->pCryptoInterface->hashDigestLen;
hexEncodedHmac.pData = pAuthBuf + authPrefixLen;
/* #authBufLen is an overestimate but the validation was already done earlier. */
hexEncodedHmac.dataLen = *authBufLen;
returnStatus = lowercaseHexEncode( &originalHmac,
&hexEncodedHmac );
*pSignature = hexEncodedHmac.pData;
*signatureLen = hexEncodedHmac.dataLen;
*authBufLen = authPrefixLen + ( pParams->pCryptoInterface->hashDigestLen << 1U );
}
return returnStatus;
}