|
1 /** |
|
2 * XMLSec library |
|
3 * |
|
4 * This is free software; see Copyright file in the source |
|
5 * distribution for preciese wording. |
|
6 * |
|
7 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> |
|
8 * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
9 */ |
|
10 #include "xmlsecc_globals.h" |
|
11 |
|
12 #include <string.h> |
|
13 #include "xmlsecc_config.h" |
|
14 #include "xmlsec_xmlsec.h" |
|
15 #include "xmlsec_keys.h" |
|
16 #include "xmlsec_transforms.h" |
|
17 #include "xmlsec_errors.h" |
|
18 |
|
19 #include "xmlsecc_crypto.h" |
|
20 #include "xmlsecc_cryptowrapper.h" // replace gnutils/gnutls.h |
|
21 |
|
22 /************************************************************************** |
|
23 * |
|
24 * Internal SymbianCrypto Block cipher CTX |
|
25 * |
|
26 *****************************************************************************/ |
|
27 xmlSecTransformGetDataTypeMethod const xmlSecCrpytoGetDataTypeMethod = xmlSecTransformDefaultGetDataType; |
|
28 xmlSecTransformPushBinMethod const xmlSecCryptoPushBinMethod = xmlSecTransformDefaultPushBin; |
|
29 xmlSecTransformPopBinMethod const xmlSecCryptoPopBinMethod = xmlSecTransformDefaultPopBin; |
|
30 |
|
31 typedef struct _xmlSecSymbianCryptoBlockCipherCtx xmlSecSymbianCryptoBlockCipherCtx, |
|
32 *xmlSecSymbianCryptoBlockCipherCtxPtr; |
|
33 struct _xmlSecSymbianCryptoBlockCipherCtx { |
|
34 int cipher; |
|
35 int mode; |
|
36 ScCipherHd cipherCtx; |
|
37 //sc_cipher_hd_t cipherCtx; |
|
38 xmlSecKeyDataId keyId; |
|
39 int keyInitialized; |
|
40 int ctxInitialized; |
|
41 }; |
|
42 |
|
43 static int xmlSecSymbianCryptoBlockCipherCtxInit (xmlSecSymbianCryptoBlockCipherCtxPtr ctx, |
|
44 xmlSecBufferPtr in, |
|
45 xmlSecBufferPtr out, |
|
46 int encrypt, |
|
47 const xmlChar* cipherName, |
|
48 xmlSecTransformCtxPtr transformCtx); |
|
49 static int xmlSecSymbianCryptoBlockCipherCtxUpdate (xmlSecSymbianCryptoBlockCipherCtxPtr ctx, |
|
50 xmlSecBufferPtr in, |
|
51 xmlSecBufferPtr out, |
|
52 int encrypt, |
|
53 const xmlChar* cipherName, |
|
54 xmlSecTransformCtxPtr transformCtx); |
|
55 static int xmlSecSymbianCryptoBlockCipherCtxFinal (xmlSecSymbianCryptoBlockCipherCtxPtr ctx, |
|
56 xmlSecBufferPtr in, |
|
57 xmlSecBufferPtr out, |
|
58 int encrypt, |
|
59 const xmlChar* cipherName, |
|
60 xmlSecTransformCtxPtr transformCtx); |
|
61 static int |
|
62 xmlSecSymbianCryptoBlockCipherCtxInit(xmlSecSymbianCryptoBlockCipherCtxPtr ctx, |
|
63 xmlSecBufferPtr in, xmlSecBufferPtr out, |
|
64 int encrypt, |
|
65 const xmlChar* cipherName, |
|
66 xmlSecTransformCtxPtr transformCtx) { |
|
67 int blockLen; |
|
68 int ret; |
|
69 |
|
70 xmlSecAssert2(ctx, -1); |
|
71 xmlSecAssert2(ctx->cipher != 0, -1); |
|
72 xmlSecAssert2(ctx->cipherCtx, -1); |
|
73 xmlSecAssert2(ctx->keyInitialized != 0, -1); |
|
74 xmlSecAssert2(ctx->ctxInitialized == 0, -1); |
|
75 xmlSecAssert2(in, -1); |
|
76 xmlSecAssert2(out, -1); |
|
77 xmlSecAssert2(transformCtx, -1); |
|
78 |
|
79 /* iv len == block len */ |
|
80 blockLen = sc_cipher_get_algo_blklen(ctx->cipher); |
|
81 xmlSecAssert2(blockLen > 0, -1); |
|
82 set_ctx_blocksize(ctx->cipherCtx, blockLen); //set blocksize |
|
83 |
|
84 if(encrypt) { |
|
85 xmlSecByte* iv; |
|
86 xmlSecSize outSize; |
|
87 |
|
88 /* allocate space for IV */ |
|
89 outSize = xmlSecBufferGetSize(out); |
|
90 ret = xmlSecBufferSetSize(out, outSize + blockLen); |
|
91 if(ret < 0) { |
|
92 xmlSecError(XMLSEC_ERRORS_HERE, |
|
93 xmlSecErrorsSafeString(cipherName), |
|
94 "xmlSecBufferSetSize", |
|
95 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
96 "size=%d", outSize + blockLen); |
|
97 return(-1); |
|
98 } |
|
99 iv = xmlSecBufferGetData(out) + outSize; |
|
100 |
|
101 /* generate and use random iv */ |
|
102 ret = sc_randomize(iv, blockLen, SC_STRONG_RANDOM); |
|
103 if( ret != 0 ) { |
|
104 xmlSecError(XMLSEC_ERRORS_HERE, |
|
105 xmlSecErrorsSafeString(cipherName), |
|
106 "sc_randomize", |
|
107 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
108 "ret=%d", ret); |
|
109 return( -1 ); |
|
110 } |
|
111 ret = sc_cipher_setiv(ctx->cipherCtx, iv, blockLen); |
|
112 if(ret != 0) { |
|
113 xmlSecError(XMLSEC_ERRORS_HERE, |
|
114 xmlSecErrorsSafeString(cipherName), |
|
115 "sc_cipher_setiv", |
|
116 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
117 "ret=%d", ret); |
|
118 return(-1); |
|
119 } |
|
120 } else { |
|
121 /* if we don't have enough data, exit and hope that |
|
122 * we'll have iv next time */ |
|
123 if(xmlSecBufferGetSize(in) < (xmlSecSize)blockLen) { |
|
124 return(0); |
|
125 } |
|
126 xmlSecAssert2(xmlSecBufferGetData(in), -1); |
|
127 |
|
128 /* set iv */ |
|
129 ret = sc_cipher_setiv(ctx->cipherCtx, xmlSecBufferGetData(in), blockLen); |
|
130 if(ret != 0) { |
|
131 xmlSecError(XMLSEC_ERRORS_HERE, |
|
132 xmlSecErrorsSafeString(cipherName), |
|
133 "sc_cipher_setiv", |
|
134 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
135 "ret=%d", ret); |
|
136 return(-1); |
|
137 } |
|
138 |
|
139 /* and remove from input */ |
|
140 ret = xmlSecBufferRemoveHead(in, blockLen); |
|
141 if(ret < 0) { |
|
142 xmlSecError(XMLSEC_ERRORS_HERE, |
|
143 xmlSecErrorsSafeString(cipherName), |
|
144 "xmlSecBufferRemoveHead", |
|
145 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
146 "size=%d", blockLen); |
|
147 return(-1); |
|
148 } |
|
149 } |
|
150 |
|
151 ctx->ctxInitialized = 1; |
|
152 return(0); |
|
153 } |
|
154 |
|
155 static int |
|
156 xmlSecSymbianCryptoBlockCipherCtxUpdate(xmlSecSymbianCryptoBlockCipherCtxPtr ctx, |
|
157 xmlSecBufferPtr in, xmlSecBufferPtr out, |
|
158 int encrypt, |
|
159 const xmlChar* cipherName, |
|
160 xmlSecTransformCtxPtr transformCtx) { |
|
161 xmlSecSize inSize, inBlocks, outSize; |
|
162 int blockLen; |
|
163 xmlSecByte* outBuf; |
|
164 int ret; |
|
165 |
|
166 xmlSecAssert2(ctx, -1); |
|
167 xmlSecAssert2(ctx->cipher != 0, -1); |
|
168 xmlSecAssert2(ctx->cipherCtx, -1); |
|
169 xmlSecAssert2(ctx->ctxInitialized != 0, -1); |
|
170 xmlSecAssert2(in, -1); |
|
171 xmlSecAssert2(out, -1); |
|
172 xmlSecAssert2(transformCtx, -1); |
|
173 |
|
174 blockLen = sc_cipher_get_algo_blklen(ctx->cipher); |
|
175 xmlSecAssert2(blockLen > 0, -1); |
|
176 |
|
177 inSize = xmlSecBufferGetSize(in); |
|
178 outSize = xmlSecBufferGetSize(out); |
|
179 |
|
180 if(inSize < (xmlSecSize)blockLen) { |
|
181 return(0); |
|
182 } |
|
183 |
|
184 if(encrypt) { |
|
185 inBlocks = inSize / ((xmlSecSize)blockLen); |
|
186 } else { |
|
187 /* we want to have the last block in the input buffer |
|
188 * for padding check */ |
|
189 inBlocks = (inSize - 1) / ((xmlSecSize)blockLen); |
|
190 } |
|
191 inSize = inBlocks * ((xmlSecSize)blockLen); |
|
192 |
|
193 /* we write out the input size plus may be one block */ |
|
194 ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen); |
|
195 if(ret < 0) { |
|
196 xmlSecError(XMLSEC_ERRORS_HERE, |
|
197 xmlSecErrorsSafeString(cipherName), |
|
198 "xmlSecBufferSetMaxSize", |
|
199 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
200 "size=%d", outSize + inSize + blockLen); |
|
201 return(-1); |
|
202 } |
|
203 outBuf = xmlSecBufferGetData(out) + outSize; |
|
204 |
|
205 if(encrypt) { |
|
206 ret = sc_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen, |
|
207 xmlSecBufferGetData(in), inSize, NOTLAST); |
|
208 if(ret != 0) { |
|
209 xmlSecError(XMLSEC_ERRORS_HERE, |
|
210 xmlSecErrorsSafeString(cipherName), |
|
211 "sc_cipher_encrypt", |
|
212 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
213 "ret=%d", ret); |
|
214 return(-1); |
|
215 } |
|
216 } else { |
|
217 ret = sc_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen, |
|
218 xmlSecBufferGetData(in), inSize, NULL, NOTLAST); |
|
219 if(ret != 0) { |
|
220 xmlSecError(XMLSEC_ERRORS_HERE, |
|
221 xmlSecErrorsSafeString(cipherName), |
|
222 "sc_cipher_decrypt", |
|
223 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
224 "ret=%d", ret); |
|
225 return(-1); |
|
226 } |
|
227 } |
|
228 |
|
229 /* set correct output buffer size */ |
|
230 ret = xmlSecBufferSetSize(out, outSize + inSize); |
|
231 if(ret < 0) { |
|
232 xmlSecError(XMLSEC_ERRORS_HERE, |
|
233 xmlSecErrorsSafeString(cipherName), |
|
234 "xmlSecBufferSetSize", |
|
235 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
236 "size=%d", outSize + inSize); |
|
237 return(-1); |
|
238 } |
|
239 |
|
240 /* remove the processed block from input */ |
|
241 ret = xmlSecBufferRemoveHead(in, inSize); |
|
242 if(ret < 0) { |
|
243 xmlSecError(XMLSEC_ERRORS_HERE, |
|
244 xmlSecErrorsSafeString(cipherName), |
|
245 "xmlSecBufferRemoveHead", |
|
246 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
247 "size=%d", inSize); |
|
248 return(-1); |
|
249 } |
|
250 return(0); |
|
251 } |
|
252 |
|
253 static int |
|
254 xmlSecSymbianCryptoBlockCipherCtxFinal(xmlSecSymbianCryptoBlockCipherCtxPtr ctx, |
|
255 xmlSecBufferPtr in, |
|
256 xmlSecBufferPtr out, |
|
257 int encrypt, |
|
258 const xmlChar* cipherName, |
|
259 xmlSecTransformCtxPtr transformCtx) { |
|
260 xmlSecSize inSize, outSize; |
|
261 int blockLen, outLen = 0; |
|
262 xmlSecByte* inBuf; |
|
263 xmlSecByte* outBuf; |
|
264 int ret; |
|
265 |
|
266 xmlSecAssert2(ctx, -1); |
|
267 xmlSecAssert2(ctx->cipher != 0, -1); |
|
268 xmlSecAssert2(ctx->cipherCtx, -1); |
|
269 xmlSecAssert2(ctx->ctxInitialized != 0, -1); |
|
270 xmlSecAssert2(in, -1); |
|
271 xmlSecAssert2(out, -1); |
|
272 xmlSecAssert2(transformCtx, -1); |
|
273 |
|
274 blockLen = sc_cipher_get_algo_blklen(ctx->cipher); |
|
275 xmlSecAssert2(blockLen > 0, -1); |
|
276 |
|
277 inSize = xmlSecBufferGetSize(in); |
|
278 outSize = xmlSecBufferGetSize(out); |
|
279 |
|
280 if(encrypt != 0) { |
|
281 xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1); |
|
282 |
|
283 /* create padding */ |
|
284 ret = xmlSecBufferSetMaxSize(in, blockLen); |
|
285 if(ret < 0) { |
|
286 xmlSecError(XMLSEC_ERRORS_HERE, |
|
287 xmlSecErrorsSafeString(cipherName), |
|
288 "xmlSecBufferSetMaxSize", |
|
289 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
290 "size=%d", blockLen); |
|
291 return(-1); |
|
292 } |
|
293 inBuf = xmlSecBufferGetData(in); |
|
294 |
|
295 } else { |
|
296 if(inSize != (xmlSecSize)blockLen) { |
|
297 xmlSecError(XMLSEC_ERRORS_HERE, |
|
298 xmlSecErrorsSafeString(cipherName), |
|
299 NULL, |
|
300 XMLSEC_ERRORS_R_INVALID_DATA, |
|
301 "data=%d;block=%d", inSize, blockLen); |
|
302 return(-1); |
|
303 } |
|
304 } |
|
305 |
|
306 /* process last block */ |
|
307 ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen); |
|
308 if(ret < 0) { |
|
309 xmlSecError(XMLSEC_ERRORS_HERE, |
|
310 xmlSecErrorsSafeString(cipherName), |
|
311 "xmlSecBufferSetMaxSize", |
|
312 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
313 "size=%d", outSize + 2 * blockLen); |
|
314 return(-1); |
|
315 } |
|
316 outBuf = xmlSecBufferGetData(out) + outSize; |
|
317 |
|
318 if(encrypt) { |
|
319 ret = sc_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen, |
|
320 xmlSecBufferGetData(in), inSize, ISLAST); |
|
321 if(ret != 0) { |
|
322 xmlSecError(XMLSEC_ERRORS_HERE, |
|
323 xmlSecErrorsSafeString(cipherName), |
|
324 "sc_cipher_encrypt", |
|
325 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
326 "ret=%d", ret); |
|
327 return(-1); |
|
328 } |
|
329 |
|
330 if((xmlSecSize)blockLen >= (inSize + 1)) |
|
331 { |
|
332 // Symbian should have done the padding, |
|
333 //we should re-align inSize so that higher layer won't break |
|
334 inSize = blockLen; |
|
335 } |
|
336 |
|
337 } else { |
|
338 ret = sc_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen, |
|
339 xmlSecBufferGetData(in), inSize, &outLen, ISLAST); |
|
340 if(ret != 0) { |
|
341 xmlSecError(XMLSEC_ERRORS_HERE, |
|
342 xmlSecErrorsSafeString(cipherName), |
|
343 "sc_cipher_decrypt", |
|
344 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
345 "ret=%d", ret); |
|
346 return(-1); |
|
347 } |
|
348 } |
|
349 |
|
350 if(encrypt == 0) { |
|
351 /* check padding */ |
|
352 if(inSize < outBuf[blockLen - 1]) { |
|
353 xmlSecError(XMLSEC_ERRORS_HERE, |
|
354 xmlSecErrorsSafeString(cipherName), |
|
355 NULL, |
|
356 XMLSEC_ERRORS_R_INVALID_DATA, |
|
357 "padding=%d;buffer=%d", |
|
358 outBuf[blockLen - 1], inSize); |
|
359 return(-1); |
|
360 } |
|
361 // outLen is explicitely written and returned from sc_cipher_decrypt() |
|
362 // outLen = inSize - outBuf[blockLen - 1]; |
|
363 } else { |
|
364 outLen = inSize; |
|
365 } |
|
366 |
|
367 /* set correct output buffer size */ |
|
368 ret = xmlSecBufferSetSize(out, outSize + outLen); |
|
369 if(ret < 0) { |
|
370 xmlSecError(XMLSEC_ERRORS_HERE, |
|
371 xmlSecErrorsSafeString(cipherName), |
|
372 "xmlSecBufferSetSize", |
|
373 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
374 "size=%d", outSize + outLen); |
|
375 return(-1); |
|
376 } |
|
377 |
|
378 /* remove the processed block from input */ |
|
379 ret = xmlSecBufferRemoveHead(in, inSize); |
|
380 if(ret < 0) { |
|
381 xmlSecError(XMLSEC_ERRORS_HERE, |
|
382 xmlSecErrorsSafeString(cipherName), |
|
383 "xmlSecBufferRemoveHead", |
|
384 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
385 "size=%d", inSize); |
|
386 return(-1); |
|
387 } |
|
388 |
|
389 |
|
390 return(0); |
|
391 } |
|
392 |
|
393 |
|
394 /****************************************************************************** |
|
395 * |
|
396 * Block Cipher transforms |
|
397 * |
|
398 * xmlSecSymbianCryptoBlockCipherCtx block is located after xmlSecTransform structure |
|
399 * |
|
400 *****************************************************************************/ |
|
401 #define xmlSecSymbianCryptoBlockCipherSize \ |
|
402 (sizeof(xmlSecTransform) + sizeof(xmlSecSymbianCryptoBlockCipherCtx)) |
|
403 #define xmlSecSymbianCryptoBlockCipherGetCtx(transform) \ |
|
404 ((xmlSecSymbianCryptoBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) |
|
405 |
|
406 static int xmlSecSymbianCryptoBlockCipherInitialize (xmlSecTransformPtr transform); |
|
407 static void xmlSecSymbianCryptoBlockCipherFinalize (xmlSecTransformPtr transform); |
|
408 static int xmlSecSymbianCryptoBlockCipherSetKeyReq (xmlSecTransformPtr transform, |
|
409 xmlSecKeyReqPtr keyReq); |
|
410 static int xmlSecSymbianCryptoBlockCipherSetKey (xmlSecTransformPtr transform, |
|
411 xmlSecKeyPtr key); |
|
412 static int xmlSecSymbianCryptoBlockCipherExecute (xmlSecTransformPtr transform, |
|
413 int last, |
|
414 xmlSecTransformCtxPtr transformCtx); |
|
415 static int xmlSecSymbianCryptoBlockCipherCheckId (xmlSecTransformPtr transform); |
|
416 |
|
417 |
|
418 |
|
419 static int |
|
420 xmlSecSymbianCryptoBlockCipherCheckId(xmlSecTransformPtr transform) { |
|
421 #ifndef XMLSEC_NO_DES |
|
422 if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformDes3CbcId)) { |
|
423 return(1); |
|
424 } |
|
425 #endif /* XMLSEC_NO_DES */ |
|
426 |
|
427 #ifndef XMLSEC_NO_AES |
|
428 if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformAes128CbcId) || |
|
429 xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformAes192CbcId) || |
|
430 xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformAes256CbcId)) { |
|
431 |
|
432 return(1); |
|
433 } |
|
434 #endif /* XMLSEC_NO_AES */ |
|
435 |
|
436 return(0); |
|
437 } |
|
438 |
|
439 static int |
|
440 xmlSecSymbianCryptoBlockCipherInitialize(xmlSecTransformPtr transform) { |
|
441 xmlSecSymbianCryptoBlockCipherCtxPtr ctx; |
|
442 #ifndef XMLSEC_GNUTLS_OLD |
|
443 //gpg_err_code_t ret; |
|
444 //sc_error_t ret; |
|
445 int ret; |
|
446 #endif /* XMLSEC_GNUTLS_OLD */ |
|
447 |
|
448 xmlSecAssert2(xmlSecSymbianCryptoBlockCipherCheckId(transform), -1); |
|
449 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize), -1); |
|
450 |
|
451 ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); |
|
452 xmlSecAssert2(ctx, -1); |
|
453 |
|
454 memset(ctx, 0, sizeof(xmlSecSymbianCryptoBlockCipherCtx)); |
|
455 |
|
456 #ifndef XMLSEC_NO_DES |
|
457 if(transform->id == xmlSecSymbianCryptoTransformDes3CbcId) { |
|
458 ctx->cipher = SC_CIPHER_3DES; |
|
459 ctx->mode = SC_CIPHER_MODE_CBC; |
|
460 ctx->keyId = xmlSecSymbianCryptoKeyDataDesId; |
|
461 } else |
|
462 #endif /* XMLSEC_NO_DES */ |
|
463 |
|
464 #ifndef XMLSEC_NO_AES |
|
465 if(transform->id == xmlSecSymbianCryptoTransformAes128CbcId) { |
|
466 ctx->cipher = SC_CIPHER_AES128; |
|
467 ctx->mode = SC_CIPHER_MODE_CBC; |
|
468 ctx->keyId = xmlSecSymbianCryptoKeyDataAesId; |
|
469 } else if(transform->id == xmlSecSymbianCryptoTransformAes192CbcId) { |
|
470 ctx->cipher = SC_CIPHER_AES192; |
|
471 ctx->mode = SC_CIPHER_MODE_CBC; |
|
472 ctx->keyId = xmlSecSymbianCryptoKeyDataAesId; |
|
473 } else if(transform->id == xmlSecSymbianCryptoTransformAes256CbcId) { |
|
474 ctx->cipher = SC_CIPHER_AES256; |
|
475 ctx->mode = SC_CIPHER_MODE_CBC; |
|
476 ctx->keyId = xmlSecSymbianCryptoKeyDataAesId; |
|
477 } else |
|
478 #endif /* XMLSEC_NO_AES */ |
|
479 |
|
480 if(1) { |
|
481 xmlSecError(XMLSEC_ERRORS_HERE, |
|
482 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
483 NULL, |
|
484 XMLSEC_ERRORS_R_INVALID_TRANSFORM, |
|
485 XMLSEC_ERRORS_NO_MESSAGE); |
|
486 return(-1); |
|
487 } |
|
488 |
|
489 #ifndef XMLSEC_GNUTLS_OLD |
|
490 ret = sc_cipher_open(&ctx->cipherCtx, ctx->cipher, ctx->mode, SC_CIPHER_SECURE); /* we are paranoid */ |
|
491 if(ret != 0/*GPG_ERR_NO_ERROR*/) { |
|
492 #else /* XMLSEC_GNUTLS_OLD */ |
|
493 ctx->cipherCtx = sc_cipher_open(ctx->cipher, ctx->mode, SC_CIPHER_SECURE); /* we are paranoid */ |
|
494 if(!ctx->cipherCtx) { |
|
495 #endif /* XMLSEC_GNUTLS_OLD */ |
|
496 xmlSecError(XMLSEC_ERRORS_HERE, |
|
497 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
498 "sc_cipher_open", |
|
499 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
500 XMLSEC_ERRORS_NO_MESSAGE); |
|
501 return(-1); |
|
502 } |
|
503 return(0); |
|
504 } |
|
505 |
|
506 static void |
|
507 xmlSecSymbianCryptoBlockCipherFinalize(xmlSecTransformPtr transform) { |
|
508 xmlSecSymbianCryptoBlockCipherCtxPtr ctx; |
|
509 |
|
510 xmlSecAssert(xmlSecSymbianCryptoBlockCipherCheckId(transform)); |
|
511 xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize)); |
|
512 |
|
513 ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); |
|
514 xmlSecAssert(ctx); |
|
515 |
|
516 if(ctx->cipherCtx) { |
|
517 sc_cipher_close(ctx->cipherCtx); |
|
518 } |
|
519 |
|
520 memset(ctx, 0, sizeof(xmlSecSymbianCryptoBlockCipherCtx)); |
|
521 } |
|
522 |
|
523 static int |
|
524 xmlSecSymbianCryptoBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { |
|
525 xmlSecSymbianCryptoBlockCipherCtxPtr ctx; |
|
526 |
|
527 xmlSecAssert2(xmlSecSymbianCryptoBlockCipherCheckId(transform), -1); |
|
528 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) |
|
529 || (transform->operation == xmlSecTransformOperationDecrypt), -1); |
|
530 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize), -1); |
|
531 xmlSecAssert2(keyReq, -1); |
|
532 |
|
533 ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); |
|
534 xmlSecAssert2(ctx, -1); |
|
535 xmlSecAssert2(ctx->cipher != 0, -1); |
|
536 xmlSecAssert2(ctx->keyId, -1); |
|
537 |
|
538 keyReq->keyId = ctx->keyId; |
|
539 keyReq->keyType = xmlSecKeyDataTypeSymmetric; |
|
540 if(transform->operation == xmlSecTransformOperationEncrypt) { |
|
541 keyReq->keyUsage = xmlSecKeyUsageEncrypt; |
|
542 } else { |
|
543 keyReq->keyUsage = xmlSecKeyUsageDecrypt; |
|
544 } |
|
545 |
|
546 keyReq->keyBitsSize = 8 * sc_cipher_get_algo_keylen(ctx->cipher); |
|
547 return(0); |
|
548 } |
|
549 |
|
550 static int |
|
551 xmlSecSymbianCryptoBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { |
|
552 xmlSecSymbianCryptoBlockCipherCtxPtr ctx; |
|
553 xmlSecBufferPtr buffer; |
|
554 xmlSecSize keySize; |
|
555 int ret; |
|
556 |
|
557 xmlSecAssert2(xmlSecSymbianCryptoBlockCipherCheckId(transform), -1); |
|
558 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) |
|
559 || (transform->operation == xmlSecTransformOperationDecrypt), -1); |
|
560 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize), -1); |
|
561 xmlSecAssert2(key, -1); |
|
562 |
|
563 ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); |
|
564 xmlSecAssert2(ctx, -1); |
|
565 xmlSecAssert2(ctx->cipherCtx, -1); |
|
566 xmlSecAssert2(ctx->cipher != 0, -1); |
|
567 xmlSecAssert2(ctx->keyInitialized == 0, -1); |
|
568 xmlSecAssert2(ctx->keyId, -1); |
|
569 xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1); |
|
570 |
|
571 keySize = sc_cipher_get_algo_keylen(ctx->cipher); |
|
572 xmlSecAssert2(keySize > 0, -1); |
|
573 |
|
574 buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); |
|
575 xmlSecAssert2(buffer, -1); |
|
576 |
|
577 if(xmlSecBufferGetSize(buffer) < keySize) { |
|
578 xmlSecError(XMLSEC_ERRORS_HERE, |
|
579 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
580 NULL, |
|
581 XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, |
|
582 "keySize=%d;expected=%d", |
|
583 xmlSecBufferGetSize(buffer), keySize); |
|
584 return(-1); |
|
585 } |
|
586 |
|
587 xmlSecAssert2(xmlSecBufferGetData(buffer), -1); |
|
588 ret = sc_cipher_setkey(ctx->cipherCtx, xmlSecBufferGetData(buffer), keySize); |
|
589 if(ret != 0) { |
|
590 xmlSecError(XMLSEC_ERRORS_HERE, |
|
591 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
592 "sc_cipher_setkey", |
|
593 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
594 "ret=%d", ret); |
|
595 return(-1); |
|
596 } |
|
597 |
|
598 ctx->keyInitialized = 1; |
|
599 return(0); |
|
600 } |
|
601 |
|
602 static int |
|
603 xmlSecSymbianCryptoBlockCipherExecute(xmlSecTransformPtr transform, |
|
604 int last, |
|
605 xmlSecTransformCtxPtr transformCtx) { |
|
606 xmlSecSymbianCryptoBlockCipherCtxPtr ctx; |
|
607 xmlSecBufferPtr in, out; |
|
608 int ret; |
|
609 |
|
610 xmlSecAssert2(xmlSecSymbianCryptoBlockCipherCheckId(transform), -1); |
|
611 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) |
|
612 || (transform->operation == xmlSecTransformOperationDecrypt), -1); |
|
613 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize), -1); |
|
614 xmlSecAssert2(transformCtx, -1); |
|
615 |
|
616 in = &(transform->inBuf); |
|
617 out = &(transform->outBuf); |
|
618 |
|
619 ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); |
|
620 xmlSecAssert2(ctx, -1); |
|
621 |
|
622 if(transform->status == xmlSecTransformStatusNone) { |
|
623 transform->status = xmlSecTransformStatusWorking; |
|
624 } |
|
625 |
|
626 if(transform->status == xmlSecTransformStatusWorking) { |
|
627 if(ctx->ctxInitialized == 0) { |
|
628 ret = xmlSecSymbianCryptoBlockCipherCtxInit(ctx, in, out, |
|
629 (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, |
|
630 xmlSecTransformGetName(transform), transformCtx); |
|
631 if(ret < 0) { |
|
632 xmlSecError(XMLSEC_ERRORS_HERE, |
|
633 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
634 "xmlSecSymbianCryptoBlockCipherCtxInit", |
|
635 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
636 XMLSEC_ERRORS_NO_MESSAGE); |
|
637 return(-1); |
|
638 } |
|
639 } |
|
640 if((ctx->ctxInitialized == 0) && (last != 0)) { |
|
641 xmlSecError(XMLSEC_ERRORS_HERE, |
|
642 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
643 NULL, |
|
644 XMLSEC_ERRORS_R_INVALID_DATA, |
|
645 "not enough data to initialize transform"); |
|
646 return(-1); |
|
647 } |
|
648 if(ctx->ctxInitialized != 0) { |
|
649 ret = xmlSecSymbianCryptoBlockCipherCtxUpdate(ctx, in, out, |
|
650 (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, |
|
651 xmlSecTransformGetName(transform), transformCtx); |
|
652 if(ret < 0) { |
|
653 xmlSecError(XMLSEC_ERRORS_HERE, |
|
654 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
655 "xmlSecSymbianCryptoBlockCipherCtxUpdate", |
|
656 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
657 XMLSEC_ERRORS_NO_MESSAGE); |
|
658 return(-1); |
|
659 } |
|
660 } |
|
661 |
|
662 if(last) { |
|
663 ret = xmlSecSymbianCryptoBlockCipherCtxFinal(ctx, in, out, |
|
664 (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, |
|
665 xmlSecTransformGetName(transform), transformCtx); |
|
666 if(ret < 0) { |
|
667 xmlSecError(XMLSEC_ERRORS_HERE, |
|
668 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
669 "xmlSecSymbianCryptoBlockCipherCtxFinal", |
|
670 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
671 XMLSEC_ERRORS_NO_MESSAGE); |
|
672 return(-1); |
|
673 } |
|
674 transform->status = xmlSecTransformStatusFinished; |
|
675 } |
|
676 } else if(transform->status == xmlSecTransformStatusFinished) { |
|
677 /* the only way we can get here is if there is no input */ |
|
678 xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1); |
|
679 } else if(transform->status == xmlSecTransformStatusNone) { |
|
680 /* the only way we can get here is if there is no enough data in the input */ |
|
681 xmlSecAssert2(last == 0, -1); |
|
682 } else { |
|
683 xmlSecError(XMLSEC_ERRORS_HERE, |
|
684 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
685 NULL, |
|
686 XMLSEC_ERRORS_R_INVALID_STATUS, |
|
687 "status=%d", transform->status); |
|
688 return(-1); |
|
689 } |
|
690 |
|
691 return(0); |
|
692 } |
|
693 |
|
694 |
|
695 #ifndef XMLSEC_NO_AES |
|
696 /********************************************************************* |
|
697 * |
|
698 * AES CBC cipher transforms |
|
699 * |
|
700 ********************************************************************/ |
|
701 static xmlSecTransformKlass xmlSecSymbianCryptoAes128CbcKlass = { |
|
702 /* klass/object sizes */ |
|
703 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
704 xmlSecSymbianCryptoBlockCipherSize, /* xmlSecSize objSize */ |
|
705 |
|
706 xmlSecNameAes128Cbc, /* const xmlChar* name; */ |
|
707 xmlSecHrefAes128Cbc, /* const xmlChar* href; */ |
|
708 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ |
|
709 |
|
710 xmlSecSymbianCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
711 xmlSecSymbianCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
712 NULL, /* xmlSecTransformNodeReadMethod readNode; */ |
|
713 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
714 xmlSecSymbianCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ |
|
715 xmlSecSymbianCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ |
|
716 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
717 xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
718 xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ |
|
719 xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ |
|
720 NULL, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
721 NULL, /* xmlSecTransformPopXmlMethod popXml; */ |
|
722 xmlSecSymbianCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
723 |
|
724 NULL, /* void* reserved0; */ |
|
725 NULL, /* void* reserved1; */ |
|
726 }; |
|
727 |
|
728 /** |
|
729 * xmlSecSymbianCryptoTransformAes128CbcGetKlass: |
|
730 * |
|
731 * AES 128 CBC encryption transform klass. |
|
732 * |
|
733 * Returns pointer to AES 128 CBC encryption transform. |
|
734 */ |
|
735 EXPORT_C |
|
736 xmlSecTransformId |
|
737 xmlSecSymbianCryptoTransformAes128CbcGetKlass(void) { |
|
738 return(&xmlSecSymbianCryptoAes128CbcKlass); |
|
739 } |
|
740 |
|
741 static xmlSecTransformKlass xmlSecSymbianCryptoAes192CbcKlass = { |
|
742 /* klass/object sizes */ |
|
743 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
744 xmlSecSymbianCryptoBlockCipherSize, /* xmlSecSize objSize */ |
|
745 |
|
746 xmlSecNameAes192Cbc, /* const xmlChar* name; */ |
|
747 xmlSecHrefAes192Cbc, /* const xmlChar* href; */ |
|
748 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ |
|
749 |
|
750 xmlSecSymbianCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
751 xmlSecSymbianCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
752 NULL, /* xmlSecTransformNodeReadMethod readNode; */ |
|
753 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
754 xmlSecSymbianCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ |
|
755 xmlSecSymbianCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ |
|
756 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
757 xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
758 xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ |
|
759 xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ |
|
760 NULL, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
761 NULL, /* xmlSecTransformPopXmlMethod popXml; */ |
|
762 xmlSecSymbianCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
763 |
|
764 NULL, /* void* reserved0; */ |
|
765 NULL, /* void* reserved1; */ |
|
766 }; |
|
767 |
|
768 /** |
|
769 * xmlSecSymbianCryptoTransformAes192CbcGetKlass: |
|
770 * |
|
771 * AES 192 CBC encryption transform klass. |
|
772 * |
|
773 * Returns pointer to AES 192 CBC encryption transform. |
|
774 */ |
|
775 EXPORT_C |
|
776 xmlSecTransformId |
|
777 xmlSecSymbianCryptoTransformAes192CbcGetKlass(void) { |
|
778 return(&xmlSecSymbianCryptoAes192CbcKlass); |
|
779 } |
|
780 |
|
781 static xmlSecTransformKlass xmlSecSymbianCryptoAes256CbcKlass = { |
|
782 /* klass/object sizes */ |
|
783 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
784 xmlSecSymbianCryptoBlockCipherSize, /* xmlSecSize objSize */ |
|
785 |
|
786 xmlSecNameAes256Cbc, /* const xmlChar* name; */ |
|
787 xmlSecHrefAes256Cbc, /* const xmlChar* href; */ |
|
788 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ |
|
789 |
|
790 xmlSecSymbianCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
791 xmlSecSymbianCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
792 NULL, /* xmlSecTransformNodeReadMethod readNode; */ |
|
793 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
794 xmlSecSymbianCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ |
|
795 xmlSecSymbianCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ |
|
796 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
797 xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
798 xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ |
|
799 xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ |
|
800 NULL, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
801 NULL, /* xmlSecTransformPopXmlMethod popXml; */ |
|
802 xmlSecSymbianCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
803 |
|
804 NULL, /* void* reserved0; */ |
|
805 NULL, /* void* reserved1; */ |
|
806 }; |
|
807 |
|
808 /** |
|
809 * xmlSecSymbianCryptoTransformAes256CbcGetKlass: |
|
810 * |
|
811 * AES 256 CBC encryption transform klass. |
|
812 * |
|
813 * Returns pointer to AES 256 CBC encryption transform. |
|
814 */ |
|
815 EXPORT_C |
|
816 xmlSecTransformId |
|
817 xmlSecSymbianCryptoTransformAes256CbcGetKlass(void) { |
|
818 return(&xmlSecSymbianCryptoAes256CbcKlass); |
|
819 } |
|
820 |
|
821 #endif /* XMLSEC_NO_AES */ |
|
822 |
|
823 #ifndef XMLSEC_NO_DES |
|
824 static xmlSecTransformKlass xmlSecSymbianCryptoDes3CbcKlass = { |
|
825 /* klass/object sizes */ |
|
826 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
827 xmlSecSymbianCryptoBlockCipherSize, /* xmlSecSize objSize */ |
|
828 |
|
829 xmlSecNameDes3Cbc, /* const xmlChar* name; */ |
|
830 xmlSecHrefDes3Cbc, /* const xmlChar* href; */ |
|
831 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ |
|
832 |
|
833 xmlSecSymbianCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
834 xmlSecSymbianCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
835 NULL, /* xmlSecTransformNodeReadMethod readNode; */ |
|
836 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
837 xmlSecSymbianCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ |
|
838 xmlSecSymbianCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ |
|
839 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
840 xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
841 xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ |
|
842 xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ |
|
843 NULL, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
844 NULL, /* xmlSecTransformPopXmlMethod popXml; */ |
|
845 xmlSecSymbianCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
846 |
|
847 NULL, /* void* reserved0; */ |
|
848 NULL, /* void* reserved1; */ |
|
849 }; |
|
850 |
|
851 /** |
|
852 * xmlSecSymbianCryptoTransformDes3CbcGetKlass: |
|
853 * |
|
854 * Triple DES CBC encryption transform klass. |
|
855 * |
|
856 * Returns pointer to Triple DES encryption transform. |
|
857 */ |
|
858 EXPORT_C |
|
859 xmlSecTransformId |
|
860 xmlSecSymbianCryptoTransformDes3CbcGetKlass(void) { |
|
861 return(&xmlSecSymbianCryptoDes3CbcKlass); |
|
862 } |
|
863 #endif /* XMLSEC_NO_DES */ |
|
864 |
|
865 |