pnpmobileservices/pnpms/PnP/NHwrParser/HttpProvContent.cpp
changeset 0 3ce708148e4d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pnpmobileservices/pnpms/PnP/NHwrParser/HttpProvContent.cpp	Thu Dec 17 08:40:12 2009 +0200
@@ -0,0 +1,361 @@
+/*
+* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of PnPMS components
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <hash.h>
+
+#include "HttpProvContent.h"
+#include "HttpProvContentType.h"
+#include "NHwrParserLogger.h"
+#include "HttpProvHeaders.h"
+#include "PnpUtilImpl.h"
+
+// CONSTANTS
+
+// Number of BCD digits in byte
+const TInt KNumDigitsInByte = 2;
+
+// Number of bits in half-byte
+const TInt KNumBitsInNibble = 4;
+
+// Ascii code for zero
+const TUint8 KZero = '0';
+
+// Padding half-byte
+const TUint8 KPadNibble = 0xf;
+
+// First nibble
+const TUint8 KFirstNibble = 0x1;
+
+// Parity bit number in first nibble
+const TUint KParityBitNum = 3;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHttpProvContent::CHttpProvContent
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CHttpProvContent::CHttpProvContent() : iAuthenticated( EFalse)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpProvContent::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CHttpProvContent::ConstructL( const TPtrC8 aContent )
+    {
+    iContent.Set( aContent );
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpProvContent::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CHttpProvContent* CHttpProvContent::NewL(const TPtrC8 aContent)
+    {
+    LOGSTRING( "CHttpProvContent::NewL()" );
+    CHttpProvContent* self = NewLC(aContent);
+    CleanupStack::Pop();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpProvContent::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CHttpProvContent* CHttpProvContent::NewLC(const TPtrC8 aContent)
+    {
+    LOGSTRING( "CHttpProvContent::NewLC()" );
+    CHttpProvContent* self = new(ELeave) CHttpProvContent; 
+    CleanupStack::PushL(self);
+    self->ConstructL(aContent);
+    return self;
+    }
+
+// Destructor
+CHttpProvContent::~CHttpProvContent()
+    {
+    LOGSTRING( "~CHttpProvContent - done" );
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpProvContent::AuthenticateL
+// -----------------------------------------------------------------------------
+//
+TInt CHttpProvContent::AuthenticateL( const CHttpProvHeaders& aHeaders, CHttpProvContentType& aContentType )
+    {
+    LOGSTRING( "CHttpProvContent::AuthenticateL" );
+
+    TInt result( KHttpProvAuthResultAuthenticated );
+
+    CPnpUtilImpl* pnpUtil = CPnpUtilImpl::NewLC();
+
+    TInt token = 0;
+    TBuf8<4> tokenbuf;    // Token cannot be more the 4 characters long
+    tokenbuf.Zero();
+
+    RMobilePhone::TMobilePhoneSubscriberId imsi;
+    //    util->Imsi(imsi);
+    //    RDebug::Print(imsi);
+    
+    // Create space for key
+    HBufC8* key = HBufC8::NewLC( Max( 1, imsi.MaxLength() + tokenbuf.MaxLength() ) );
+    TPtr8 keyPtr( key->Des() );
+
+    LOGSTRING2( "Content type SEC: %i", aContentType.SEC() );
+
+    // We support only security type NETWPIN
+    switch( aContentType.SEC() )
+        {
+        case KSECUSERPIN:
+            {
+            LOGSTRING("KSECUSERPIN");
+            // Get token saved by ConfManager    
+            TInt err = pnpUtil->GetTokenValue( token );
+            tokenbuf.AppendNum(token);
+            if( err != KErrNone )
+                {
+                result = KHttpProvAuthResultTokenExpired;
+                }
+            else if( tokenbuf.Length() == 0 )
+                {
+                result = KHttpProvAuthResultPinRequired;
+                }
+
+            keyPtr.Copy( tokenbuf );
+            if( result == KHttpProvAuthResultAuthenticated )
+                AuthenticateSenderL( *key, aContentType, result );
+            break;
+            }
+
+        case KSECUSERNETWPIN:
+            {
+            LOGSTRING("KSECUSERNETWPIN");
+            // Get token saved by ConfManager    
+            TInt err = pnpUtil->GetTokenValue( token );
+            tokenbuf.AppendNum(token);
+            if( err != KErrNone )
+                {
+                result = KHttpProvAuthResultTokenExpired;
+                }
+            else if( tokenbuf.Length() == 0 )
+                {
+                result = KHttpProvAuthResultPinRequired;
+                }
+
+            ConvertIMSIL( imsi, keyPtr );
+            keyPtr.Append( tokenbuf );
+
+            if( result == KHttpProvAuthResultAuthenticated )
+                AuthenticateSenderL( *key, aContentType, result );
+            break;
+            }
+
+        case KSECUSERPINMAC:
+            {
+            LOGSTRING("KSECUSERPINMAC");
+            // Get token saved by ConfManager    
+            TInt err = pnpUtil->GetTokenValue( token );
+            tokenbuf.AppendNum(token);
+            if( err != KErrNone )
+                {
+                result = KHttpProvAuthResultTokenExpired;
+                }
+            else if( tokenbuf.Length() == 0 )
+                {
+                result = KHttpProvAuthResultPinRequired;
+                }
+
+            keyPtr.Copy( tokenbuf );
+
+            if( result == KHttpProvAuthResultAuthenticated )
+                AuthenticateSenderL( *key, aContentType, result );
+            break;
+            }
+        case KSECPKA:
+            {
+            LOGSTRING("KSECPKA");
+            LOGSTRING( "Get nonce" );
+            TBuf8<KNonceLength> nonce;
+            pnpUtil->GetNonceL( nonce );
+
+            LOGSTRING( "Verify signature" );
+            // Verify digest (Hash value of "nonce:data") and signature of the sender
+            if( !pnpUtil->VerifySignatureL(
+                    aHeaders.GetParamValL( KDigestValue ),
+                    aHeaders.GetParamValL( KSignatureValue ),
+                    iContent,
+                    nonce ) )
+                {
+                LOGSTRING("Signature verify failed");
+                result = KHttpProvAuthResultAuthenticationFailed;
+                }
+            else
+                {
+                LOGSTRING("Signature verified");
+                }
+            break;
+            }
+        default:
+            {
+            LOGSTRING("No authentication");
+            result = KHttpProvAuthResultNoAuthentication;
+            }
+        }
+
+
+    CleanupStack::PopAndDestroy( key ); // key, headerMac
+
+    CleanupStack::PopAndDestroy( pnpUtil );
+
+    LOGSTRING2( "CHttpProvContent::AuthenticateL - done: %i", result );
+    
+    return result;
+    }
+
+void CHttpProvContent::AuthenticateSenderL( const TDesC8& aKey, CHttpProvContentType& aContentType, TInt& aResult )
+    {
+    LOGSTRING( "CHttpProvContent::AuthenticateSenderL" );
+    // The HMAC is in ASCII HEX format. Convert to binary.
+    TPtrC8 mac;
+    aContentType.MACL(mac);
+    LOGSTRING( "mac:" );
+    LOGTEXT( mac );
+    HBufC8* headerMac = PackLC( mac );
+    CMessageDigest* digest = CSHA1::NewL();
+    CleanupStack::PushL( digest );
+
+    if( aContentType.SEC() == KSECUSERPINMAC )
+        {
+        // key C is a concatenation of pin K and digest m
+        TPtrC8 K( aKey.Left( aKey.Length()/2 ) );
+        TPtrC8 m( aKey.Right( aKey.Length()/2 ) );
+
+        // M' = HMAC-SHA(K, A)
+        CHMAC* hmac = CHMAC::NewL( K, digest );
+        // Ownership of digest is transferred to hmac created above
+        CleanupStack::Pop( digest );
+        CleanupStack::PushL( hmac );
+        TPtrC8 MM( hmac->Hash( iContent ) );
+
+        // Create m' (renamed to mm)
+        HBufC8* mm = HBufC8::NewLC( m.Length() );
+        TPtr8 ptr( mm->Des() );
+        for( TInt i( 0 ); i < m.Length(); i++ )
+            {
+            ptr.Append( (MM[i]%10)+KZero );
+            }
+
+        // Compare the MACs and mark the message as authenticated
+        if( *mm != m )
+            {
+            aResult = KHttpProvAuthResultAuthenticationFailed;
+            }
+        CleanupStack::PopAndDestroy( mm );
+        CleanupStack::PopAndDestroy( hmac );
+        }
+    else
+        {
+        // Create the HMAC from body
+        CHMAC* hmac = CHMAC::NewL( aKey, digest );
+        LOGTEXT( aKey );
+        // Ownership of digest is transferred to hmac created above
+        CleanupStack::Pop( digest );
+        CleanupStack::PushL( hmac );
+
+        // Compare the MACs and mark the message as authenticated
+        TPtrC8 temp = hmac->Hash( iContent );
+        if( headerMac->Length() == 0 
+            || temp != *headerMac )
+            {
+            LOGSTRING( "KHttpProvAuthResultAuthenticationFailed" );
+            aResult = KHttpProvAuthResultAuthenticationFailed;
+            }
+        CleanupStack::PopAndDestroy( hmac );
+        }
+    CleanupStack::PopAndDestroy( headerMac );
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpProvContent::PackLC
+// -----------------------------------------------------------------------------
+//
+HBufC8* CHttpProvContent::PackLC( const TDesC8& aHex ) const
+    {
+    HBufC8* bin = HBufC8::NewLC( aHex.Length()/2 );
+    TPtr8 binPtr( bin->Des() );
+    for( TInt i( 0 ); i < aHex.Length()/2; i++ )
+        {
+        TLex8 lex( aHex.Mid( i*2, 2 ) );
+        TUint8 byte( 0 );
+        User::LeaveIfError( lex.Val( byte, EHex ) );
+        binPtr.Append( TUint8( byte ) );
+        }
+
+    return bin;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpProvContent::ConvertIMSIL
+// -----------------------------------------------------------------------------
+//
+void CHttpProvContent::ConvertIMSIL( const TDesC& aIMSI, TPtr8& aKey ) const
+    {
+    TUint8 parity( TUint8((aIMSI.Length() % 2) << KParityBitNum) );
+
+    if( aIMSI.Length() == 0 )
+        {
+        aKey.Append( (KPadNibble<<KNumBitsInNibble) + KFirstNibble + parity );
+        return;
+        }
+
+    // First byte contains just a header and one digit
+    TInt first( aIMSI[0] - KZero );
+    aKey.Append( (first<<KNumBitsInNibble) | KFirstNibble | parity );
+
+    // Use semi-octet or BCD packing of IMSI. It means that one byte contains two
+    // decimal numbers, each in its own nibble.
+    for( TInt i( 1 ); i < aIMSI.Length(); i += KNumDigitsInByte )
+        {
+        TInt first( aIMSI[i] - KZero );
+        TInt second( 0 );
+
+        if( aIMSI.Length() == i+1 )
+            {
+            second = KPadNibble;
+            }
+        else
+            {
+            second = aIMSI[i+1] - KZero;
+            }
+
+        aKey.Append( (second<<KNumBitsInNibble) + first );
+        }
+    }
+
+
+//  End of File