omadrm/drmengine/roap/src/MeteringReportReq.cpp
changeset 0 95b198f216e5
child 12 8a03a285ab14
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/roap/src/MeteringReportReq.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,362 @@
+/*
+* Copyright (c) 2002-2008 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:  Class representing metering report request
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include "base64.h"
+#include "MeteringReportReq.h"
+#include "RoapLog.h"
+
+using namespace Roap;
+
+// LOCAL CONSTANTS AND MACROS
+// XML tag related literals
+// Warning: these literals are very fragile in respect to XML canonicalisation.
+_LIT8(KReqHeader, "<roap:meteringReportSubmit xmlns:roap=\"urn:oma:bac:dldrm:roap-1.0\"");
+_LIT8(KReqNonceTrigger, " triggerNonce=\"");
+_LIT8(KReqNonceTriggerEnd, "\"");
+_LIT8(KReqHeaderEnd, ">");
+_LIT8(KReqDeviceId, "<deviceID><keyIdentifier xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"roap:X509SPKIHash\"><hash>");
+_LIT8(KReqDeviceIdEnd, "</hash></keyIdentifier></deviceID>");
+_LIT8(KReqRiId, "<riID><keyIdentifier xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"roap:X509SPKIHash\"><hash>");
+_LIT8(KReqRiIdEnd, "</hash></keyIdentifier></riID>");
+_LIT8(KReqNonce, "<nonce>");
+_LIT8(KReqNonceEnd, "</nonce>");
+_LIT8(KReqTime, "<time>");
+_LIT8(KReqTimeEnd, "</time>");
+_LIT8(KReqMeteringReport, "<meteringReport>");
+
+_LIT8(KReqReportHeader,
+"<encryptedMeteringReport>\
+<xenc:EncryptedData xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\"\
+ Type=\"http://www.w3.org/2001/04/xmlenc#Content\">\
+<xenc:EncryptionMethod\
+ Algorithm=\"http://www.w3.org/2001/04/xmlenc#aes128-cbc\">\
+</xenc:EncryptionMethod>");
+
+_LIT8(KReqKeyInfo, "<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\
+<ds:RetrievalMethod URI=\"#K_MEK_and_K_MAC\"></ds:RetrievalMethod>\
+</ds:KeyInfo>");
+
+_LIT8(KReqCipherDataStart, "<xenc:CipherData><xenc:CipherValue>");
+_LIT8(KReqCipherDataEnd, "</xenc:CipherValue></xenc:CipherData></xenc:EncryptedData></encryptedMeteringReport>");
+
+_LIT8(KReqEncKeyAndMethod, "<encKey Id=\"K_MEK_and_K_MAC\"><xenc:EncryptionMethod\
+ xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\" Algorithm=\"" );
+
+_LIT8(KReqEncKeyAndMethodAfterAlgorithm, "\"></xenc:EncryptionMethod>");
+
+_LIT8(KReqEncKeyInfoStart, "<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">");
+
+// Note the two versions below are because of different namespace
+// normalisation of element roap:X509SPKIHash on canonicalisation of
+// whole request to be signed and on canonicalisation of element 
+// <meteringReport> to be MAC calculated.
+// when changing one of these another one must be cahnges too.
+//
+// This version is used when canonicalisation is performed over
+// <roap:meteringReportSubmit>
+//
+_LIT8(KReqRoapX509AndHash, "<roap:X509SPKIHash><hash>");
+//
+//
+// This version is used when canonicalisation is taken over <meteringReport>
+// (on MAC calculation)
+//
+_LIT8(KReqRoapX509AndHashNs, "<roap:X509SPKIHash xmlns:roap=\"urn:oma:bac:dldrm:roap-1.0\"><hash>");
+
+
+_LIT8(KReqEncKeyInfoEnd, "</hash></roap:X509SPKIHash></ds:KeyInfo>\
+<xenc:CipherData xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\"><xenc:CipherValue>");
+
+_LIT8(KReqCipherValueEnd, "</xenc:CipherValue></xenc:CipherData></encKey>");
+_LIT8(KReqMacStart, "<mac>");
+_LIT8(KReqMacEnd, "</mac>");
+_LIT8(KReqReportHeaderEnd, "</meteringReport>");
+_LIT8(KReqCertChain, "<certificateChain>");
+_LIT8(KReqCert, "<certificate>");
+_LIT8(KReqCertEnd, "</certificate>");
+_LIT8(KReqCertChainEnd, "</certificateChain>");
+_LIT8(KReqSig, "<signature>");
+_LIT8(KReqSigEnd, "</signature></roap:meteringReportSubmit>");
+// literals for key transport scheme
+_LIT8( KOmaKdf, "http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-1#rsaes-kem-kdf2-kw-aes128");
+_LIT8( KCmlaIp1, "http://www.cm-la.com/tech/cmlaip/cmlaip#cmlaip-1");
+// ============================ LOCAL FUNCTIONS ===============================
+
+// ----------------------------------------------------------------------------
+// MeteringReportElementAsTextL
+//
+// write content of to given flat buffer 
+// Used from MessageAsXmlL and from InsertMacL
+// Note content depends on value of 
+// ----------------------------------------------------------------------------
+LOCAL_C inline void MeteringReportElementAsTextL(
+    CBufFlat*& aBuf,
+    const Roap::CMeteringReportReq& aReq
+    )
+    {
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqMeteringReport );
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqReportHeader );
+
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqKeyInfo );
+
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqCipherDataStart );
+
+    // actual encrypted metering data
+    if ( aReq.iCipherValue )
+        {
+        Roap::CRoapMessage::BufAppendBase64L( aBuf, *aReq.iCipherValue );
+        }
+
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqCipherDataEnd );
+
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqEncKeyAndMethod );
+
+    // Select KDF algorithm in use
+    if ( aReq.iAlgorithmInUse == ECmlaIp1 )
+        {
+        Roap::CRoapMessage::BufAppendL( aBuf, KCmlaIp1 );
+        }
+    else if ( aReq.iAlgorithmInUse == EOma )
+        {
+        Roap::CRoapMessage::BufAppendL( aBuf, KOmaKdf );
+        }
+    else
+        {
+        User::Leave( KErrNotSupported );
+        }
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqEncKeyAndMethodAfterAlgorithm );
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqEncKeyInfoStart );
+
+    if ( aReq.iMac )
+        {
+        // used as part of roap:Meteringreport submit
+        // so namespace ROAP already defined in container element
+        Roap::CRoapMessage::BufAppendL( aBuf, KReqRoapX509AndHash );
+        }
+    else
+        {
+        // used in mac calculation 
+        // canonical form requires namespace definition for namespace roap
+        Roap::CRoapMessage::BufAppendL( aBuf, KReqRoapX509AndHashNs );
+        }
+
+    // Insert 128-bit encrypted encryption key PKI hash
+    Roap::CRoapMessage::BufAppendBase64L( aBuf, aReq.iEncKeyHash );
+
+
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqEncKeyInfoEnd );
+
+    // key wrapping info
+    Roap::CRoapMessage::BufAppendBase64L( aBuf, *aReq.iEncryptedMekAndMak );
+
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqCipherValueEnd );    
+
+    // Insert 128-bit encrypted MAC value
+    if ( aReq.iMac )
+        {
+        Roap::CRoapMessage::BufAppendL( aBuf, KReqMacStart );
+        Roap::CRoapMessage::BufAppendBase64L( aBuf, *aReq.iMac );
+        Roap::CRoapMessage::BufAppendL( aBuf, KReqMacEnd );
+        }
+    Roap::CRoapMessage::BufAppendL( aBuf, KReqReportHeaderEnd );
+    }
+
+// -----------------------------------------------------------------------------
+// CalculateMacL
+// -----------------------------------------------------------------------------
+//
+LOCAL_C HBufC8* CalculateMacL(const TDesC8& aElement, const TDesC8& aMacKey )
+    {
+
+    LOG( _L8( "CalculateMacL" ) );
+    LOG( _L8( "aMacKey" ) );
+    LOGHEX( aMacKey.Ptr(), aMacKey.Length() );
+    LOG( _L8( "aElement" ) );
+    LOGHEX( aElement.Ptr(), aElement.Length() );
+    if( !aMacKey.Length() || !aElement.Length() )
+        {
+        User::Leave(KErrArgument);
+        }
+
+    CHMAC* hMac = NULL;
+    CSHA1* sha = NULL;
+    TPtrC8 hmac_value( KNullDesC8 );
+    TPtrC8 sha1_value( KNullDesC8 );
+    HBufC8* macValue = NULL;
+
+    sha = CSHA1::NewL();
+    CleanupStack::PushL( sha );
+    hMac = CHMAC::NewL( aMacKey, sha );
+    CleanupStack::Pop( sha ); // sha is now owned by hMac
+    CleanupStack::PushL( hMac );
+    hMac->Update( aElement );
+    hmac_value.Set( hMac->Final() );
+
+    macValue = hmac_value.AllocL();
+    LOG( _L8( "macValue" ) );
+    LOGHEX( macValue->Ptr(), macValue->Length() );
+
+    CleanupStack::PopAndDestroy( hMac );
+    return macValue;
+    }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CRightsReq::CRightsReq
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CMeteringReportReq::CMeteringReportReq():
+    iNonce(NULL),
+    iReportNonce(NULL),
+    iSignature(NULL),
+    iCipherValue(NULL),
+    iMac(NULL),
+    iTriggerNonce(NULL)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CRightsReq::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CMeteringReportReq::ConstructL()
+    {
+    iTime.UniversalTime();
+    }
+
+// -----------------------------------------------------------------------------
+// CRightsReq::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMeteringReportReq* CMeteringReportReq::NewL()
+    {
+    CMeteringReportReq* self = new( ELeave ) CMeteringReportReq;
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+
+// Destructor
+CMeteringReportReq::~CMeteringReportReq()
+    {
+    if ( iCertificateChain.Count() )
+        {
+        iCertificateChain.ResetAndDestroy();
+        }
+    delete iSignature;
+    delete iTriggerNonce;
+    delete iCipherValue;
+    delete iEncryptedMekAndMak;
+    delete iMac;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CRightsReq::MessageAsXmlL
+// Gives XML representation of meteringreport request
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMeteringReportReq::MessageAsXmlL(void)
+    {
+    HBufC8* r( NULL );
+    CBufFlat* b( CBufFlat::NewL( 128 ) );
+    CleanupStack::PushL( b );
+    b->InsertL( 0, KReqHeader );
+    if ( iTriggerNonce )
+        {
+        BufAppendL( b, KReqNonceTrigger );
+        BufAppendL( b, *iTriggerNonce );
+        BufAppendL( b, KReqNonceTriggerEnd );
+        }
+    BufAppendL( b, KReqHeaderEnd );
+
+    BufAppendL( b, KReqDeviceId );
+    BufAppendBase64L( b, iDeviceId );
+    BufAppendL( b, KReqDeviceIdEnd );
+
+    BufAppendL( b, KReqRiId );
+    BufAppendBase64L( b, iRiId );
+    BufAppendL( b, KReqRiIdEnd );
+
+    BufAppendL( b, KReqNonce );
+    BufAppendBase64L( b, iNonce );
+    BufAppendL( b, KReqNonceEnd );
+
+    BufAppendL( b, KReqTime );
+    BufAppendTimeL( b, iTime );
+    BufAppendL( b, KReqTimeEnd );
+
+    MeteringReportElementAsTextL( b, *this );
+
+    if ( iCertificateChain.Count() > 0 )
+        {
+        BufAppendL( b, KReqCertChain );
+        for ( TInt i( 0 ); i < iCertificateChain.Count(); i++ )
+            {
+            BufAppendL( b, KReqCert );
+            BufAppendBase64L( b, *iCertificateChain[ i ] );
+            BufAppendL( b, KReqCertEnd );
+            }
+        BufAppendL( b, KReqCertChainEnd );
+        }
+
+    BufAppendL(b, KReqSig);
+    BufAppendL(b, KReqSigEnd);
+
+    r = b->Ptr( 0 ).AllocL();
+    CleanupStack::PopAndDestroy( b );
+    return r;
+    }
+
+// -----------------------------------------------------------------------------
+// CMeteringReportReq::InsertMacL( const TDesC8& aMac )
+// Calculate MAC -value over <encryptedMeteringReport>
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMeteringReportReq::InsertMacL( const TDesC8& aMacKey )
+    {
+    CBufFlat* b( CBufFlat::NewL( 128 ) );
+    CleanupStack::PushL( b );
+
+
+    MeteringReportElementAsTextL( b, *this );
+
+    // Calculate MAC -value over <encryptedMeteringReport>
+    // without the actual <mac> -element
+
+    iMac = CalculateMacL( b->Ptr( 0 ), aMacKey );
+    CleanupStack::PopAndDestroy( b );
+    return;
+    }
+
+//  End of File