SigV4Status_t SigV4_GenerateHTTPAuthorization()

in source/sigv4.c [3121:3228]


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;
    size_t uxBufferLen;

    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 Authorization header value. */
    if( returnStatus == SigV4Success )
    {
        LogDebug( ( "Generated Canonical Request: %.*s",
                    ( unsigned int ) ( canonicalContext.uxCursorIndex ),
                    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 = ( char * ) &( canonicalContext.pBufProcessing[ canonicalContext.uxCursorIndex ] );
        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 )
    {
        uxBufferLen = canonicalContext.uxCursorIndex;
        returnStatus = ( completeHmac( &hmacContext,
                                       signingKey.pData,
                                       signingKey.dataLen,
                                       ( char * ) canonicalContext.pBufProcessing,
                                       uxBufferLen,
                                       ( char * ) &( canonicalContext.pBufProcessing[ canonicalContext.uxCursorIndex ] ),
                                       pParams->pCryptoInterface->hashDigestLen ) != 0 )
                       ? SigV4HashError : SigV4Success;
    }

    /* Hex-encode the final signature beforehand to its precalculated
     * location in the buffer provided for the Authorization header value. */
    if( returnStatus == SigV4Success )
    {
        SigV4String_t originalHmac;
        SigV4String_t hexEncodedHmac;
        originalHmac.pData = ( char * ) &( canonicalContext.pBufProcessing[ canonicalContext.uxCursorIndex ] );
        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;
}