|
1 /* |
|
2 * Copyright (c) 2002-2008 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: Class representing metering report request |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include <e32std.h> |
|
22 #include "base64.h" |
|
23 #include "MeteringReportReq.h" |
|
24 #include "RoapLog.h" |
|
25 |
|
26 using namespace Roap; |
|
27 |
|
28 // LOCAL CONSTANTS AND MACROS |
|
29 // XML tag related literals |
|
30 // Warning: these literals are very fragile in respect to XML canonicalisation. |
|
31 _LIT8(KReqHeader, "<roap:meteringReportSubmit xmlns:roap=\"urn:oma:bac:dldrm:roap-1.0\""); |
|
32 _LIT8(KReqNonceTrigger, " triggerNonce=\""); |
|
33 _LIT8(KReqNonceTriggerEnd, "\""); |
|
34 _LIT8(KReqHeaderEnd, ">"); |
|
35 _LIT8(KReqDeviceId, "<deviceID><keyIdentifier xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"roap:X509SPKIHash\"><hash>"); |
|
36 _LIT8(KReqDeviceIdEnd, "</hash></keyIdentifier></deviceID>"); |
|
37 _LIT8(KReqRiId, "<riID><keyIdentifier xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"roap:X509SPKIHash\"><hash>"); |
|
38 _LIT8(KReqRiIdEnd, "</hash></keyIdentifier></riID>"); |
|
39 _LIT8(KReqNonce, "<nonce>"); |
|
40 _LIT8(KReqNonceEnd, "</nonce>"); |
|
41 _LIT8(KReqTime, "<time>"); |
|
42 _LIT8(KReqTimeEnd, "</time>"); |
|
43 _LIT8(KReqMeteringReport, "<meteringReport>"); |
|
44 |
|
45 _LIT8(KReqReportHeader, |
|
46 "<encryptedMeteringReport>\ |
|
47 <xenc:EncryptedData xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\"\ |
|
48 Type=\"http://www.w3.org/2001/04/xmlenc#Content\">\ |
|
49 <xenc:EncryptionMethod\ |
|
50 Algorithm=\"http://www.w3.org/2001/04/xmlenc#aes128-cbc\">\ |
|
51 </xenc:EncryptionMethod>"); |
|
52 |
|
53 _LIT8(KReqKeyInfo, "<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\ |
|
54 <ds:RetrievalMethod URI=\"#K_MEK_and_K_MAC\"></ds:RetrievalMethod>\ |
|
55 </ds:KeyInfo>"); |
|
56 |
|
57 _LIT8(KReqCipherDataStart, "<xenc:CipherData><xenc:CipherValue>"); |
|
58 _LIT8(KReqCipherDataEnd, "</xenc:CipherValue></xenc:CipherData></xenc:EncryptedData></encryptedMeteringReport>"); |
|
59 |
|
60 _LIT8(KReqEncKeyAndMethod, "<encKey Id=\"K_MEK_and_K_MAC\"><xenc:EncryptionMethod\ |
|
61 xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\" Algorithm=\"" ); |
|
62 |
|
63 _LIT8(KReqEncKeyAndMethodAfterAlgorithm, "\"></xenc:EncryptionMethod>"); |
|
64 |
|
65 _LIT8(KReqEncKeyInfoStart, "<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">"); |
|
66 |
|
67 // Note the two versions below are because of different namespace |
|
68 // normalisation of element roap:X509SPKIHash on canonicalisation of |
|
69 // whole request to be signed and on canonicalisation of element |
|
70 // <meteringReport> to be MAC calculated. |
|
71 // when changing one of these another one must be cahnges too. |
|
72 // |
|
73 // This version is used when canonicalisation is performed over |
|
74 // <roap:meteringReportSubmit> |
|
75 // |
|
76 _LIT8(KReqRoapX509AndHash, "<roap:X509SPKIHash><hash>"); |
|
77 // |
|
78 // |
|
79 // This version is used when canonicalisation is taken over <meteringReport> |
|
80 // (on MAC calculation) |
|
81 // |
|
82 _LIT8(KReqRoapX509AndHashNs, "<roap:X509SPKIHash xmlns:roap=\"urn:oma:bac:dldrm:roap-1.0\"><hash>"); |
|
83 |
|
84 |
|
85 _LIT8(KReqEncKeyInfoEnd, "</hash></roap:X509SPKIHash></ds:KeyInfo>\ |
|
86 <xenc:CipherData xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\"><xenc:CipherValue>"); |
|
87 |
|
88 _LIT8(KReqCipherValueEnd, "</xenc:CipherValue></xenc:CipherData></encKey>"); |
|
89 _LIT8(KReqMacStart, "<mac>"); |
|
90 _LIT8(KReqMacEnd, "</mac>"); |
|
91 _LIT8(KReqReportHeaderEnd, "</meteringReport>"); |
|
92 _LIT8(KReqCertChain, "<certificateChain>"); |
|
93 _LIT8(KReqCert, "<certificate>"); |
|
94 _LIT8(KReqCertEnd, "</certificate>"); |
|
95 _LIT8(KReqCertChainEnd, "</certificateChain>"); |
|
96 _LIT8(KReqSig, "<signature>"); |
|
97 _LIT8(KReqSigEnd, "</signature></roap:meteringReportSubmit>"); |
|
98 // literals for key transport scheme |
|
99 _LIT8( KOmaKdf, "http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-1#rsaes-kem-kdf2-kw-aes128"); |
|
100 _LIT8( KCmlaIp1, "http://www.cm-la.com/tech/cmlaip/cmlaip#cmlaip-1"); |
|
101 // ============================ LOCAL FUNCTIONS =============================== |
|
102 |
|
103 // ---------------------------------------------------------------------------- |
|
104 // MeteringReportElementAsTextL |
|
105 // |
|
106 // write content of to given flat buffer |
|
107 // Used from MessageAsXmlL and from InsertMacL |
|
108 // Note content depends on value of |
|
109 // ---------------------------------------------------------------------------- |
|
110 LOCAL_C inline void MeteringReportElementAsTextL( |
|
111 CBufFlat*& aBuf, |
|
112 const Roap::CMeteringReportReq& aReq |
|
113 ) |
|
114 { |
|
115 Roap::CRoapMessage::BufAppendL( aBuf, KReqMeteringReport ); |
|
116 Roap::CRoapMessage::BufAppendL( aBuf, KReqReportHeader ); |
|
117 |
|
118 Roap::CRoapMessage::BufAppendL( aBuf, KReqKeyInfo ); |
|
119 |
|
120 Roap::CRoapMessage::BufAppendL( aBuf, KReqCipherDataStart ); |
|
121 |
|
122 // actual encrypted metering data |
|
123 if ( aReq.iCipherValue ) |
|
124 { |
|
125 Roap::CRoapMessage::BufAppendBase64L( aBuf, *aReq.iCipherValue ); |
|
126 } |
|
127 |
|
128 Roap::CRoapMessage::BufAppendL( aBuf, KReqCipherDataEnd ); |
|
129 |
|
130 Roap::CRoapMessage::BufAppendL( aBuf, KReqEncKeyAndMethod ); |
|
131 |
|
132 // Select KDF algorithm in use |
|
133 if ( aReq.iAlgorithmInUse == ECmlaIp1 ) |
|
134 { |
|
135 Roap::CRoapMessage::BufAppendL( aBuf, KCmlaIp1 ); |
|
136 } |
|
137 else if ( aReq.iAlgorithmInUse == EOma ) |
|
138 { |
|
139 Roap::CRoapMessage::BufAppendL( aBuf, KOmaKdf ); |
|
140 } |
|
141 else |
|
142 { |
|
143 User::Leave( KErrNotSupported ); |
|
144 } |
|
145 Roap::CRoapMessage::BufAppendL( aBuf, KReqEncKeyAndMethodAfterAlgorithm ); |
|
146 Roap::CRoapMessage::BufAppendL( aBuf, KReqEncKeyInfoStart ); |
|
147 |
|
148 if ( aReq.iMac ) |
|
149 { |
|
150 // used as part of roap:Meteringreport submit |
|
151 // so namespace ROAP already defined in container element |
|
152 Roap::CRoapMessage::BufAppendL( aBuf, KReqRoapX509AndHash ); |
|
153 } |
|
154 else |
|
155 { |
|
156 // used in mac calculation |
|
157 // canonical form requires namespace definition for namespace roap |
|
158 Roap::CRoapMessage::BufAppendL( aBuf, KReqRoapX509AndHashNs ); |
|
159 } |
|
160 |
|
161 // Insert 128-bit encrypted encryption key PKI hash |
|
162 Roap::CRoapMessage::BufAppendBase64L( aBuf, aReq.iEncKeyHash ); |
|
163 |
|
164 |
|
165 Roap::CRoapMessage::BufAppendL( aBuf, KReqEncKeyInfoEnd ); |
|
166 |
|
167 // key wrapping info |
|
168 Roap::CRoapMessage::BufAppendBase64L( aBuf, *aReq.iEncryptedMekAndMak ); |
|
169 |
|
170 Roap::CRoapMessage::BufAppendL( aBuf, KReqCipherValueEnd ); |
|
171 |
|
172 // Insert 128-bit encrypted MAC value |
|
173 if ( aReq.iMac ) |
|
174 { |
|
175 Roap::CRoapMessage::BufAppendL( aBuf, KReqMacStart ); |
|
176 Roap::CRoapMessage::BufAppendBase64L( aBuf, *aReq.iMac ); |
|
177 Roap::CRoapMessage::BufAppendL( aBuf, KReqMacEnd ); |
|
178 } |
|
179 Roap::CRoapMessage::BufAppendL( aBuf, KReqReportHeaderEnd ); |
|
180 } |
|
181 |
|
182 // ----------------------------------------------------------------------------- |
|
183 // CalculateMacL |
|
184 // ----------------------------------------------------------------------------- |
|
185 // |
|
186 LOCAL_C HBufC8* CalculateMacL(const TDesC8& aElement, const TDesC8& aMacKey ) |
|
187 { |
|
188 |
|
189 LOG( _L8( "CalculateMacL" ) ); |
|
190 LOG( _L8( "aMacKey" ) ); |
|
191 LOGHEX( aMacKey.Ptr(), aMacKey.Length() ); |
|
192 LOG( _L8( "aElement" ) ); |
|
193 LOGHEX( aElement.Ptr(), aElement.Length() ); |
|
194 if( !aMacKey.Length() || !aElement.Length() ) |
|
195 { |
|
196 User::Leave(KErrArgument); |
|
197 } |
|
198 |
|
199 CHMAC* hMac = NULL; |
|
200 CSHA1* sha = NULL; |
|
201 TPtrC8 hmac_value( KNullDesC8 ); |
|
202 TPtrC8 sha1_value( KNullDesC8 ); |
|
203 HBufC8* macValue = NULL; |
|
204 |
|
205 sha = CSHA1::NewL(); |
|
206 CleanupStack::PushL( sha ); |
|
207 hMac = CHMAC::NewL( aMacKey, sha ); |
|
208 CleanupStack::Pop( sha ); // sha is now owned by hMac |
|
209 CleanupStack::PushL( hMac ); |
|
210 hMac->Update( aElement ); |
|
211 hmac_value.Set( hMac->Final() ); |
|
212 |
|
213 macValue = hmac_value.AllocL(); |
|
214 LOG( _L8( "macValue" ) ); |
|
215 LOGHEX( macValue->Ptr(), macValue->Length() ); |
|
216 |
|
217 CleanupStack::PopAndDestroy( hMac ); |
|
218 return macValue; |
|
219 } |
|
220 |
|
221 |
|
222 // ============================ MEMBER FUNCTIONS =============================== |
|
223 |
|
224 // ----------------------------------------------------------------------------- |
|
225 // CRightsReq::CRightsReq |
|
226 // C++ default constructor can NOT contain any code, that |
|
227 // might leave. |
|
228 // ----------------------------------------------------------------------------- |
|
229 // |
|
230 CMeteringReportReq::CMeteringReportReq(): |
|
231 iNonce(NULL), |
|
232 iReportNonce(NULL), |
|
233 iSignature(NULL), |
|
234 iCipherValue(NULL), |
|
235 iMac(NULL), |
|
236 iTriggerNonce(NULL) |
|
237 { |
|
238 } |
|
239 |
|
240 // ----------------------------------------------------------------------------- |
|
241 // CRightsReq::ConstructL |
|
242 // Symbian 2nd phase constructor can leave. |
|
243 // ----------------------------------------------------------------------------- |
|
244 // |
|
245 void CMeteringReportReq::ConstructL() |
|
246 { |
|
247 iTime.UniversalTime(); |
|
248 } |
|
249 |
|
250 // ----------------------------------------------------------------------------- |
|
251 // CRightsReq::NewL |
|
252 // Two-phased constructor. |
|
253 // ----------------------------------------------------------------------------- |
|
254 // |
|
255 CMeteringReportReq* CMeteringReportReq::NewL() |
|
256 { |
|
257 CMeteringReportReq* self = new( ELeave ) CMeteringReportReq; |
|
258 |
|
259 CleanupStack::PushL( self ); |
|
260 self->ConstructL(); |
|
261 CleanupStack::Pop( self ); |
|
262 |
|
263 return self; |
|
264 } |
|
265 |
|
266 |
|
267 // Destructor |
|
268 CMeteringReportReq::~CMeteringReportReq() |
|
269 { |
|
270 if ( iCertificateChain.Count() ) |
|
271 { |
|
272 iCertificateChain.ResetAndDestroy(); |
|
273 } |
|
274 delete iSignature; |
|
275 delete iTriggerNonce; |
|
276 delete iCipherValue; |
|
277 delete iEncryptedMekAndMak; |
|
278 delete iMac; |
|
279 } |
|
280 |
|
281 |
|
282 // ----------------------------------------------------------------------------- |
|
283 // CRightsReq::MessageAsXmlL |
|
284 // Gives XML representation of meteringreport request |
|
285 // (other items were commented in a header). |
|
286 // ----------------------------------------------------------------------------- |
|
287 // |
|
288 HBufC8* CMeteringReportReq::MessageAsXmlL(void) |
|
289 { |
|
290 HBufC8* r( NULL ); |
|
291 CBufFlat* b( CBufFlat::NewL( 128 ) ); |
|
292 CleanupStack::PushL( b ); |
|
293 b->InsertL( 0, KReqHeader ); |
|
294 if ( iTriggerNonce ) |
|
295 { |
|
296 BufAppendL( b, KReqNonceTrigger ); |
|
297 BufAppendL( b, *iTriggerNonce ); |
|
298 BufAppendL( b, KReqNonceTriggerEnd ); |
|
299 } |
|
300 BufAppendL( b, KReqHeaderEnd ); |
|
301 |
|
302 BufAppendL( b, KReqDeviceId ); |
|
303 BufAppendBase64L( b, iDeviceId ); |
|
304 BufAppendL( b, KReqDeviceIdEnd ); |
|
305 |
|
306 BufAppendL( b, KReqRiId ); |
|
307 BufAppendBase64L( b, iRiId ); |
|
308 BufAppendL( b, KReqRiIdEnd ); |
|
309 |
|
310 BufAppendL( b, KReqNonce ); |
|
311 BufAppendBase64L( b, iNonce ); |
|
312 BufAppendL( b, KReqNonceEnd ); |
|
313 |
|
314 BufAppendL( b, KReqTime ); |
|
315 BufAppendTimeL( b, iTime ); |
|
316 BufAppendL( b, KReqTimeEnd ); |
|
317 |
|
318 MeteringReportElementAsTextL( b, *this ); |
|
319 |
|
320 if ( iCertificateChain.Count() > 0 ) |
|
321 { |
|
322 BufAppendL( b, KReqCertChain ); |
|
323 for ( TInt i( 0 ); i < iCertificateChain.Count(); i++ ) |
|
324 { |
|
325 BufAppendL( b, KReqCert ); |
|
326 BufAppendBase64L( b, *iCertificateChain[ i ] ); |
|
327 BufAppendL( b, KReqCertEnd ); |
|
328 } |
|
329 BufAppendL( b, KReqCertChainEnd ); |
|
330 } |
|
331 |
|
332 BufAppendL(b, KReqSig); |
|
333 BufAppendL(b, KReqSigEnd); |
|
334 |
|
335 r = b->Ptr( 0 ).AllocL(); |
|
336 CleanupStack::PopAndDestroy( b ); |
|
337 return r; |
|
338 } |
|
339 |
|
340 // ----------------------------------------------------------------------------- |
|
341 // CMeteringReportReq::InsertMacL( const TDesC8& aMac ) |
|
342 // Calculate MAC -value over <encryptedMeteringReport> |
|
343 // (other items were commented in a header). |
|
344 // ----------------------------------------------------------------------------- |
|
345 // |
|
346 void CMeteringReportReq::InsertMacL( const TDesC8& aMacKey ) |
|
347 { |
|
348 CBufFlat* b( CBufFlat::NewL( 128 ) ); |
|
349 CleanupStack::PushL( b ); |
|
350 |
|
351 |
|
352 MeteringReportElementAsTextL( b, *this ); |
|
353 |
|
354 // Calculate MAC -value over <encryptedMeteringReport> |
|
355 // without the actual <mac> -element |
|
356 |
|
357 iMac = CalculateMacL( b->Ptr( 0 ), aMacKey ); |
|
358 CleanupStack::PopAndDestroy( b ); |
|
359 return; |
|
360 } |
|
361 |
|
362 // End of File |