SigV4Status_t SigV4_GenerateHTTPAuthorization()

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;
}