pnpmobileservices/pnpms/PnP/NHwrParser/HttpProvContent.cpp
changeset 0 3ce708148e4d
equal deleted inserted replaced
-1:000000000000 0:3ce708148e4d
       
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Implementation of PnPMS components
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <hash.h>
       
    22 
       
    23 #include "HttpProvContent.h"
       
    24 #include "HttpProvContentType.h"
       
    25 #include "NHwrParserLogger.h"
       
    26 #include "HttpProvHeaders.h"
       
    27 #include "PnpUtilImpl.h"
       
    28 
       
    29 // CONSTANTS
       
    30 
       
    31 // Number of BCD digits in byte
       
    32 const TInt KNumDigitsInByte = 2;
       
    33 
       
    34 // Number of bits in half-byte
       
    35 const TInt KNumBitsInNibble = 4;
       
    36 
       
    37 // Ascii code for zero
       
    38 const TUint8 KZero = '0';
       
    39 
       
    40 // Padding half-byte
       
    41 const TUint8 KPadNibble = 0xf;
       
    42 
       
    43 // First nibble
       
    44 const TUint8 KFirstNibble = 0x1;
       
    45 
       
    46 // Parity bit number in first nibble
       
    47 const TUint KParityBitNum = 3;
       
    48 
       
    49 
       
    50 // ============================ MEMBER FUNCTIONS ===============================
       
    51 
       
    52 // -----------------------------------------------------------------------------
       
    53 // CHttpProvContent::CHttpProvContent
       
    54 // C++ default constructor can NOT contain any code, that
       
    55 // might leave.
       
    56 // -----------------------------------------------------------------------------
       
    57 //
       
    58 CHttpProvContent::CHttpProvContent() : iAuthenticated( EFalse)
       
    59     {
       
    60     }
       
    61 
       
    62 // -----------------------------------------------------------------------------
       
    63 // CHttpProvContent::ConstructL
       
    64 // Symbian 2nd phase constructor can leave.
       
    65 // -----------------------------------------------------------------------------
       
    66 //
       
    67 void CHttpProvContent::ConstructL( const TPtrC8 aContent )
       
    68     {
       
    69     iContent.Set( aContent );
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // CHttpProvContent::NewL
       
    74 // Two-phased constructor.
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 CHttpProvContent* CHttpProvContent::NewL(const TPtrC8 aContent)
       
    78     {
       
    79     LOGSTRING( "CHttpProvContent::NewL()" );
       
    80     CHttpProvContent* self = NewLC(aContent);
       
    81     CleanupStack::Pop();
       
    82     return self;
       
    83     }
       
    84 
       
    85 // -----------------------------------------------------------------------------
       
    86 // CHttpProvContent::NewLC
       
    87 // Two-phased constructor.
       
    88 // -----------------------------------------------------------------------------
       
    89 //
       
    90 CHttpProvContent* CHttpProvContent::NewLC(const TPtrC8 aContent)
       
    91     {
       
    92     LOGSTRING( "CHttpProvContent::NewLC()" );
       
    93     CHttpProvContent* self = new(ELeave) CHttpProvContent; 
       
    94     CleanupStack::PushL(self);
       
    95     self->ConstructL(aContent);
       
    96     return self;
       
    97     }
       
    98 
       
    99 // Destructor
       
   100 CHttpProvContent::~CHttpProvContent()
       
   101     {
       
   102     LOGSTRING( "~CHttpProvContent - done" );
       
   103     }
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // CHttpProvContent::AuthenticateL
       
   107 // -----------------------------------------------------------------------------
       
   108 //
       
   109 TInt CHttpProvContent::AuthenticateL( const CHttpProvHeaders& aHeaders, CHttpProvContentType& aContentType )
       
   110     {
       
   111     LOGSTRING( "CHttpProvContent::AuthenticateL" );
       
   112 
       
   113     TInt result( KHttpProvAuthResultAuthenticated );
       
   114 
       
   115     CPnpUtilImpl* pnpUtil = CPnpUtilImpl::NewLC();
       
   116 
       
   117     TInt token = 0;
       
   118     TBuf8<4> tokenbuf;    // Token cannot be more the 4 characters long
       
   119     tokenbuf.Zero();
       
   120 
       
   121     RMobilePhone::TMobilePhoneSubscriberId imsi;
       
   122     //    util->Imsi(imsi);
       
   123     //    RDebug::Print(imsi);
       
   124     
       
   125     // Create space for key
       
   126     HBufC8* key = HBufC8::NewLC( Max( 1, imsi.MaxLength() + tokenbuf.MaxLength() ) );
       
   127     TPtr8 keyPtr( key->Des() );
       
   128 
       
   129     LOGSTRING2( "Content type SEC: %i", aContentType.SEC() );
       
   130 
       
   131     // We support only security type NETWPIN
       
   132     switch( aContentType.SEC() )
       
   133         {
       
   134         case KSECUSERPIN:
       
   135             {
       
   136             LOGSTRING("KSECUSERPIN");
       
   137             // Get token saved by ConfManager    
       
   138             TInt err = pnpUtil->GetTokenValue( token );
       
   139             tokenbuf.AppendNum(token);
       
   140             if( err != KErrNone )
       
   141                 {
       
   142                 result = KHttpProvAuthResultTokenExpired;
       
   143                 }
       
   144             else if( tokenbuf.Length() == 0 )
       
   145                 {
       
   146                 result = KHttpProvAuthResultPinRequired;
       
   147                 }
       
   148 
       
   149             keyPtr.Copy( tokenbuf );
       
   150             if( result == KHttpProvAuthResultAuthenticated )
       
   151                 AuthenticateSenderL( *key, aContentType, result );
       
   152             break;
       
   153             }
       
   154 
       
   155         case KSECUSERNETWPIN:
       
   156             {
       
   157             LOGSTRING("KSECUSERNETWPIN");
       
   158             // Get token saved by ConfManager    
       
   159             TInt err = pnpUtil->GetTokenValue( token );
       
   160             tokenbuf.AppendNum(token);
       
   161             if( err != KErrNone )
       
   162                 {
       
   163                 result = KHttpProvAuthResultTokenExpired;
       
   164                 }
       
   165             else if( tokenbuf.Length() == 0 )
       
   166                 {
       
   167                 result = KHttpProvAuthResultPinRequired;
       
   168                 }
       
   169 
       
   170             ConvertIMSIL( imsi, keyPtr );
       
   171             keyPtr.Append( tokenbuf );
       
   172 
       
   173             if( result == KHttpProvAuthResultAuthenticated )
       
   174                 AuthenticateSenderL( *key, aContentType, result );
       
   175             break;
       
   176             }
       
   177 
       
   178         case KSECUSERPINMAC:
       
   179             {
       
   180             LOGSTRING("KSECUSERPINMAC");
       
   181             // Get token saved by ConfManager    
       
   182             TInt err = pnpUtil->GetTokenValue( token );
       
   183             tokenbuf.AppendNum(token);
       
   184             if( err != KErrNone )
       
   185                 {
       
   186                 result = KHttpProvAuthResultTokenExpired;
       
   187                 }
       
   188             else if( tokenbuf.Length() == 0 )
       
   189                 {
       
   190                 result = KHttpProvAuthResultPinRequired;
       
   191                 }
       
   192 
       
   193             keyPtr.Copy( tokenbuf );
       
   194 
       
   195             if( result == KHttpProvAuthResultAuthenticated )
       
   196                 AuthenticateSenderL( *key, aContentType, result );
       
   197             break;
       
   198             }
       
   199         case KSECPKA:
       
   200             {
       
   201             LOGSTRING("KSECPKA");
       
   202             LOGSTRING( "Get nonce" );
       
   203             TBuf8<KNonceLength> nonce;
       
   204             pnpUtil->GetNonceL( nonce );
       
   205 
       
   206             LOGSTRING( "Verify signature" );
       
   207             // Verify digest (Hash value of "nonce:data") and signature of the sender
       
   208             if( !pnpUtil->VerifySignatureL(
       
   209                     aHeaders.GetParamValL( KDigestValue ),
       
   210                     aHeaders.GetParamValL( KSignatureValue ),
       
   211                     iContent,
       
   212                     nonce ) )
       
   213                 {
       
   214                 LOGSTRING("Signature verify failed");
       
   215                 result = KHttpProvAuthResultAuthenticationFailed;
       
   216                 }
       
   217             else
       
   218                 {
       
   219                 LOGSTRING("Signature verified");
       
   220                 }
       
   221             break;
       
   222             }
       
   223         default:
       
   224             {
       
   225             LOGSTRING("No authentication");
       
   226             result = KHttpProvAuthResultNoAuthentication;
       
   227             }
       
   228         }
       
   229 
       
   230 
       
   231     CleanupStack::PopAndDestroy( key ); // key, headerMac
       
   232 
       
   233     CleanupStack::PopAndDestroy( pnpUtil );
       
   234 
       
   235     LOGSTRING2( "CHttpProvContent::AuthenticateL - done: %i", result );
       
   236     
       
   237     return result;
       
   238     }
       
   239 
       
   240 void CHttpProvContent::AuthenticateSenderL( const TDesC8& aKey, CHttpProvContentType& aContentType, TInt& aResult )
       
   241     {
       
   242     LOGSTRING( "CHttpProvContent::AuthenticateSenderL" );
       
   243     // The HMAC is in ASCII HEX format. Convert to binary.
       
   244     TPtrC8 mac;
       
   245     aContentType.MACL(mac);
       
   246     LOGSTRING( "mac:" );
       
   247     LOGTEXT( mac );
       
   248     HBufC8* headerMac = PackLC( mac );
       
   249     CMessageDigest* digest = CSHA1::NewL();
       
   250     CleanupStack::PushL( digest );
       
   251 
       
   252     if( aContentType.SEC() == KSECUSERPINMAC )
       
   253         {
       
   254         // key C is a concatenation of pin K and digest m
       
   255         TPtrC8 K( aKey.Left( aKey.Length()/2 ) );
       
   256         TPtrC8 m( aKey.Right( aKey.Length()/2 ) );
       
   257 
       
   258         // M' = HMAC-SHA(K, A)
       
   259         CHMAC* hmac = CHMAC::NewL( K, digest );
       
   260         // Ownership of digest is transferred to hmac created above
       
   261         CleanupStack::Pop( digest );
       
   262         CleanupStack::PushL( hmac );
       
   263         TPtrC8 MM( hmac->Hash( iContent ) );
       
   264 
       
   265         // Create m' (renamed to mm)
       
   266         HBufC8* mm = HBufC8::NewLC( m.Length() );
       
   267         TPtr8 ptr( mm->Des() );
       
   268         for( TInt i( 0 ); i < m.Length(); i++ )
       
   269             {
       
   270             ptr.Append( (MM[i]%10)+KZero );
       
   271             }
       
   272 
       
   273         // Compare the MACs and mark the message as authenticated
       
   274         if( *mm != m )
       
   275             {
       
   276             aResult = KHttpProvAuthResultAuthenticationFailed;
       
   277             }
       
   278         CleanupStack::PopAndDestroy( mm );
       
   279         CleanupStack::PopAndDestroy( hmac );
       
   280         }
       
   281     else
       
   282         {
       
   283         // Create the HMAC from body
       
   284         CHMAC* hmac = CHMAC::NewL( aKey, digest );
       
   285         LOGTEXT( aKey );
       
   286         // Ownership of digest is transferred to hmac created above
       
   287         CleanupStack::Pop( digest );
       
   288         CleanupStack::PushL( hmac );
       
   289 
       
   290         // Compare the MACs and mark the message as authenticated
       
   291         TPtrC8 temp = hmac->Hash( iContent );
       
   292         if( headerMac->Length() == 0 
       
   293             || temp != *headerMac )
       
   294             {
       
   295             LOGSTRING( "KHttpProvAuthResultAuthenticationFailed" );
       
   296             aResult = KHttpProvAuthResultAuthenticationFailed;
       
   297             }
       
   298         CleanupStack::PopAndDestroy( hmac );
       
   299         }
       
   300     CleanupStack::PopAndDestroy( headerMac );
       
   301     }
       
   302 
       
   303 // -----------------------------------------------------------------------------
       
   304 // CHttpProvContent::PackLC
       
   305 // -----------------------------------------------------------------------------
       
   306 //
       
   307 HBufC8* CHttpProvContent::PackLC( const TDesC8& aHex ) const
       
   308     {
       
   309     HBufC8* bin = HBufC8::NewLC( aHex.Length()/2 );
       
   310     TPtr8 binPtr( bin->Des() );
       
   311     for( TInt i( 0 ); i < aHex.Length()/2; i++ )
       
   312         {
       
   313         TLex8 lex( aHex.Mid( i*2, 2 ) );
       
   314         TUint8 byte( 0 );
       
   315         User::LeaveIfError( lex.Val( byte, EHex ) );
       
   316         binPtr.Append( TUint8( byte ) );
       
   317         }
       
   318 
       
   319     return bin;
       
   320     }
       
   321 
       
   322 // -----------------------------------------------------------------------------
       
   323 // CHttpProvContent::ConvertIMSIL
       
   324 // -----------------------------------------------------------------------------
       
   325 //
       
   326 void CHttpProvContent::ConvertIMSIL( const TDesC& aIMSI, TPtr8& aKey ) const
       
   327     {
       
   328     TUint8 parity( TUint8((aIMSI.Length() % 2) << KParityBitNum) );
       
   329 
       
   330     if( aIMSI.Length() == 0 )
       
   331         {
       
   332         aKey.Append( (KPadNibble<<KNumBitsInNibble) + KFirstNibble + parity );
       
   333         return;
       
   334         }
       
   335 
       
   336     // First byte contains just a header and one digit
       
   337     TInt first( aIMSI[0] - KZero );
       
   338     aKey.Append( (first<<KNumBitsInNibble) | KFirstNibble | parity );
       
   339 
       
   340     // Use semi-octet or BCD packing of IMSI. It means that one byte contains two
       
   341     // decimal numbers, each in its own nibble.
       
   342     for( TInt i( 1 ); i < aIMSI.Length(); i += KNumDigitsInByte )
       
   343         {
       
   344         TInt first( aIMSI[i] - KZero );
       
   345         TInt second( 0 );
       
   346 
       
   347         if( aIMSI.Length() == i+1 )
       
   348             {
       
   349             second = KPadNibble;
       
   350             }
       
   351         else
       
   352             {
       
   353             second = aIMSI[i+1] - KZero;
       
   354             }
       
   355 
       
   356         aKey.Append( (second<<KNumBitsInNibble) + first );
       
   357         }
       
   358     }
       
   359 
       
   360 
       
   361 //  End of File