1 /*
2 * XML Security Library (http://www.aleksey.com/xmlsec).
3 *
4 *
5 * This is free software; see Copyright file in the source
6 * distribution for preciese wording.
7 *
8 * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9 */
10 /**
11 * SECTION:ciphers
12 * @Short_description: Ciphers transforms implementation for GCrypt.
13 * @Stability: Private
14 *
15 */
16
17 #include "globals.h"
18
19 #include <string.h>
20
21 #include <gcrypt.h>
22
23 #include <xmlsec/xmlsec.h>
24 #include <xmlsec/keys.h>
25 #include <xmlsec/transforms.h>
26 #include <xmlsec/errors.h>
27
28 #include <xmlsec/gcrypt/crypto.h>
29
30 /**************************************************************************
31 *
32 * Internal GCrypt Block cipher CTX
33 *
34 *****************************************************************************/
35 typedef struct _xmlSecGCryptBlockCipherCtx xmlSecGCryptBlockCipherCtx,
36 *xmlSecGCryptBlockCipherCtxPtr;
37 struct _xmlSecGCryptBlockCipherCtx {
38 int cipher;
39 int mode;
40 gcry_cipher_hd_t cipherCtx;
41 xmlSecKeyDataId keyId;
42 int keyInitialized;
43 int ctxInitialized;
44 };
45
46 static int xmlSecGCryptBlockCipherCtxInit (xmlSecGCryptBlockCipherCtxPtr ctx,
47 xmlSecBufferPtr in,
48 xmlSecBufferPtr out,
49 int encrypt,
50 const xmlChar* cipherName,
51 xmlSecTransformCtxPtr transformCtx);
52 static int xmlSecGCryptBlockCipherCtxUpdate (xmlSecGCryptBlockCipherCtxPtr ctx,
53 xmlSecBufferPtr in,
54 xmlSecBufferPtr out,
55 int encrypt,
56 const xmlChar* cipherName,
57 xmlSecTransformCtxPtr transformCtx);
58 static int xmlSecGCryptBlockCipherCtxFinal (xmlSecGCryptBlockCipherCtxPtr ctx,
59 xmlSecBufferPtr in,
60 xmlSecBufferPtr out,
61 int encrypt,
62 const xmlChar* cipherName,
63 xmlSecTransformCtxPtr transformCtx);
64 static int
xmlSecGCryptBlockCipherCtxInit(xmlSecGCryptBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)65 xmlSecGCryptBlockCipherCtxInit(xmlSecGCryptBlockCipherCtxPtr ctx,
66 xmlSecBufferPtr in, xmlSecBufferPtr out,
67 int encrypt,
68 const xmlChar* cipherName,
69 xmlSecTransformCtxPtr transformCtx) {
70 gcry_err_code_t err;
71 int blockLen;
72 int ret;
73
74 xmlSecAssert2(ctx != NULL, -1);
75 xmlSecAssert2(ctx->cipher != 0, -1);
76 xmlSecAssert2(ctx->cipherCtx != NULL, -1);
77 xmlSecAssert2(ctx->keyInitialized != 0, -1);
78 xmlSecAssert2(ctx->ctxInitialized == 0, -1);
79 xmlSecAssert2(in != NULL, -1);
80 xmlSecAssert2(out != NULL, -1);
81 xmlSecAssert2(transformCtx != NULL, -1);
82
83 /* iv len == block len */
84 blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
85 xmlSecAssert2(blockLen > 0, -1);
86
87 if(encrypt) {
88 xmlSecByte* iv;
89 xmlSecSize outSize;
90
91 /* allocate space for IV */
92 outSize = xmlSecBufferGetSize(out);
93 ret = xmlSecBufferSetSize(out, outSize + blockLen);
94 if(ret < 0) {
95 xmlSecInternalError2("xmlSecBufferSetSize", cipherName,
96 "size=%d", outSize + blockLen);
97 return(-1);
98 }
99 iv = xmlSecBufferGetData(out) + outSize;
100
101 /* generate and use random iv */
102 gcry_randomize(iv, blockLen, GCRY_STRONG_RANDOM);
103 err = gcry_cipher_setiv(ctx->cipherCtx, iv, blockLen);
104 if(err != GPG_ERR_NO_ERROR) {
105 xmlSecGCryptError("gcry_cipher_setiv", err,
106 cipherName);
107 return(-1);
108 }
109 } else {
110 /* if we don't have enough data, exit and hope that
111 * we'll have iv next time */
112 if(xmlSecBufferGetSize(in) < (xmlSecSize)blockLen) {
113 return(0);
114 }
115 xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1);
116
117 /* set iv */
118 err = gcry_cipher_setiv(ctx->cipherCtx, xmlSecBufferGetData(in), blockLen);
119 if(err != GPG_ERR_NO_ERROR) {
120 xmlSecGCryptError("gcry_cipher_setiv", err,
121 cipherName);
122 return(-1);
123 }
124
125 /* and remove from input */
126 ret = xmlSecBufferRemoveHead(in, blockLen);
127 if(ret < 0) {
128 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName,
129 "size=%d", blockLen);
130 return(-1);
131 }
132 }
133
134 ctx->ctxInitialized = 1;
135 return(0);
136 }
137
138 static int
xmlSecGCryptBlockCipherCtxUpdate(xmlSecGCryptBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)139 xmlSecGCryptBlockCipherCtxUpdate(xmlSecGCryptBlockCipherCtxPtr ctx,
140 xmlSecBufferPtr in, xmlSecBufferPtr out,
141 int encrypt,
142 const xmlChar* cipherName,
143 xmlSecTransformCtxPtr transformCtx) {
144 xmlSecSize inSize, inBlocks, outSize;
145 int blockLen;
146 xmlSecByte* outBuf;
147 gcry_err_code_t err;
148 int ret;
149
150 xmlSecAssert2(ctx != NULL, -1);
151 xmlSecAssert2(ctx->cipher != 0, -1);
152 xmlSecAssert2(ctx->cipherCtx != NULL, -1);
153 xmlSecAssert2(ctx->ctxInitialized != 0, -1);
154 xmlSecAssert2(in != NULL, -1);
155 xmlSecAssert2(out != NULL, -1);
156 xmlSecAssert2(transformCtx != NULL, -1);
157
158 blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
159 xmlSecAssert2(blockLen > 0, -1);
160
161 inSize = xmlSecBufferGetSize(in);
162 outSize = xmlSecBufferGetSize(out);
163
164 if(inSize < (xmlSecSize)blockLen) {
165 return(0);
166 }
167
168 if(encrypt) {
169 inBlocks = inSize / ((xmlSecSize)blockLen);
170 } else {
171 /* we want to have the last block in the input buffer
172 * for padding check */
173 inBlocks = (inSize - 1) / ((xmlSecSize)blockLen);
174 }
175 inSize = inBlocks * ((xmlSecSize)blockLen);
176
177 /* we write out the input size plus may be one block */
178 ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen);
179 if(ret < 0) {
180 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName,
181 "size=%d", outSize + inSize + blockLen);
182 return(-1);
183 }
184 outBuf = xmlSecBufferGetData(out) + outSize;
185
186 if(encrypt) {
187 err = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
188 xmlSecBufferGetData(in), inSize);
189 if(err != GPG_ERR_NO_ERROR) {
190 xmlSecGCryptError("gcry_cipher_encrypt", err,
191 cipherName);
192 return(-1);
193 }
194 } else {
195 err = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
196 xmlSecBufferGetData(in), inSize);
197 if(err != GPG_ERR_NO_ERROR) {
198 xmlSecGCryptError("gcry_cipher_decrypt", err,
199 cipherName);
200 return(-1);
201 }
202 }
203
204 /* set correct output buffer size */
205 ret = xmlSecBufferSetSize(out, outSize + inSize);
206 if(ret < 0) {
207 xmlSecInternalError2("xmlSecBufferSetSize", cipherName,
208 "size=%d", outSize + inSize);
209 return(-1);
210 }
211
212 /* remove the processed block from input */
213 ret = xmlSecBufferRemoveHead(in, inSize);
214 if(ret < 0) {
215 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName,
216 "size=%d", inSize);
217 return(-1);
218 }
219 return(0);
220 }
221
222 static int
xmlSecGCryptBlockCipherCtxFinal(xmlSecGCryptBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)223 xmlSecGCryptBlockCipherCtxFinal(xmlSecGCryptBlockCipherCtxPtr ctx,
224 xmlSecBufferPtr in,
225 xmlSecBufferPtr out,
226 int encrypt,
227 const xmlChar* cipherName,
228 xmlSecTransformCtxPtr transformCtx) {
229 xmlSecSize inSize, outSize;
230 int blockLen, outLen = 0;
231 xmlSecByte* inBuf;
232 xmlSecByte* outBuf;
233 gcry_err_code_t err;
234 int ret;
235
236 xmlSecAssert2(ctx != NULL, -1);
237 xmlSecAssert2(ctx->cipher != 0, -1);
238 xmlSecAssert2(ctx->cipherCtx != NULL, -1);
239 xmlSecAssert2(ctx->ctxInitialized != 0, -1);
240 xmlSecAssert2(in != NULL, -1);
241 xmlSecAssert2(out != NULL, -1);
242 xmlSecAssert2(transformCtx != NULL, -1);
243
244 blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
245 xmlSecAssert2(blockLen > 0, -1);
246
247 inSize = xmlSecBufferGetSize(in);
248 outSize = xmlSecBufferGetSize(out);
249
250 if(encrypt != 0) {
251 xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1);
252
253 /* create padding */
254 ret = xmlSecBufferSetMaxSize(in, blockLen);
255 if(ret < 0) {
256 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName,
257 "size=%d", blockLen);
258 return(-1);
259 }
260 inBuf = xmlSecBufferGetData(in);
261
262 /* create random padding */
263 if((xmlSecSize)blockLen > (inSize + 1)) {
264 gcry_randomize(inBuf + inSize, blockLen - inSize - 1,
265 GCRY_STRONG_RANDOM); /* as usual, we are paranoid */
266 }
267 inBuf[blockLen - 1] = blockLen - inSize;
268 inSize = blockLen;
269 } else {
270 if(inSize != (xmlSecSize)blockLen) {
271 xmlSecInvalidSizeError("Input data", inSize, blockLen, cipherName);
272 return(-1);
273 }
274 }
275
276 /* process last block */
277 ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen);
278 if(ret < 0) {
279 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName,
280 "size=%d", outSize + 2 * blockLen);
281 return(-1);
282 }
283 outBuf = xmlSecBufferGetData(out) + outSize;
284
285 if(encrypt) {
286 err = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
287 xmlSecBufferGetData(in), inSize);
288 if(err != GPG_ERR_NO_ERROR) {
289 xmlSecGCryptError("gcry_cipher_encrypt", err,
290 cipherName);
291 return(-1);
292 }
293 } else {
294 err = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
295 xmlSecBufferGetData(in), inSize);
296 if(err != GPG_ERR_NO_ERROR) {
297 xmlSecGCryptError("gcry_cipher_decrypt", err,
298 cipherName);
299 return(-1);
300 }
301 }
302
303 if(encrypt == 0) {
304 /* check padding */
305 if(inSize < outBuf[blockLen - 1]) {
306 xmlSecInvalidSizeLessThanError("Input data padding",
307 inSize, outBuf[blockLen - 1], cipherName);
308 return(-1);
309 }
310 outLen = inSize - outBuf[blockLen - 1];
311 } else {
312 outLen = inSize;
313 }
314
315 /* set correct output buffer size */
316 ret = xmlSecBufferSetSize(out, outSize + outLen);
317 if(ret < 0) {
318 xmlSecInternalError2("xmlSecBufferSetSize", cipherName,
319 "size=%d", outSize + outLen);
320 return(-1);
321 }
322
323 /* remove the processed block from input */
324 ret = xmlSecBufferRemoveHead(in, inSize);
325 if(ret < 0) {
326 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName,
327 "size=%d", inSize);
328 return(-1);
329 }
330
331
332 /* set correct output buffer size */
333 ret = xmlSecBufferSetSize(out, outSize + outLen);
334 if(ret < 0) {
335 xmlSecInternalError2("xmlSecBufferSetSize", cipherName,
336 "size=%d", outSize + outLen);
337 return(-1);
338 }
339
340 /* remove the processed block from input */
341 ret = xmlSecBufferRemoveHead(in, inSize);
342 if(ret < 0) {
343 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName,
344 "size=%d", inSize);
345 return(-1);
346 }
347
348 return(0);
349 }
350
351
352 /******************************************************************************
353 *
354 * Block Cipher transforms
355 *
356 * xmlSecGCryptBlockCipherCtx block is located after xmlSecTransform structure
357 *
358 *****************************************************************************/
359 #define xmlSecGCryptBlockCipherSize \
360 (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptBlockCipherCtx))
361 #define xmlSecGCryptBlockCipherGetCtx(transform) \
362 ((xmlSecGCryptBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
363
364 static int xmlSecGCryptBlockCipherInitialize (xmlSecTransformPtr transform);
365 static void xmlSecGCryptBlockCipherFinalize (xmlSecTransformPtr transform);
366 static int xmlSecGCryptBlockCipherSetKeyReq (xmlSecTransformPtr transform,
367 xmlSecKeyReqPtr keyReq);
368 static int xmlSecGCryptBlockCipherSetKey (xmlSecTransformPtr transform,
369 xmlSecKeyPtr key);
370 static int xmlSecGCryptBlockCipherExecute (xmlSecTransformPtr transform,
371 int last,
372 xmlSecTransformCtxPtr transformCtx);
373 static int xmlSecGCryptBlockCipherCheckId (xmlSecTransformPtr transform);
374
375
376
377 static int
xmlSecGCryptBlockCipherCheckId(xmlSecTransformPtr transform)378 xmlSecGCryptBlockCipherCheckId(xmlSecTransformPtr transform) {
379 #ifndef XMLSEC_NO_DES
380 if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDes3CbcId)) {
381 return(1);
382 }
383 #endif /* XMLSEC_NO_DES */
384
385 #ifndef XMLSEC_NO_AES
386 if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes128CbcId) ||
387 xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes192CbcId) ||
388 xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes256CbcId)) {
389
390 return(1);
391 }
392 #endif /* XMLSEC_NO_AES */
393
394 return(0);
395 }
396
397 static int
xmlSecGCryptBlockCipherInitialize(xmlSecTransformPtr transform)398 xmlSecGCryptBlockCipherInitialize(xmlSecTransformPtr transform) {
399 xmlSecGCryptBlockCipherCtxPtr ctx;
400 gcry_error_t err;
401
402 xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1);
403 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1);
404
405 ctx = xmlSecGCryptBlockCipherGetCtx(transform);
406 xmlSecAssert2(ctx != NULL, -1);
407
408 memset(ctx, 0, sizeof(xmlSecGCryptBlockCipherCtx));
409
410 #ifndef XMLSEC_NO_DES
411 if(transform->id == xmlSecGCryptTransformDes3CbcId) {
412 ctx->cipher = GCRY_CIPHER_3DES;
413 ctx->mode = GCRY_CIPHER_MODE_CBC;
414 ctx->keyId = xmlSecGCryptKeyDataDesId;
415 } else
416 #endif /* XMLSEC_NO_DES */
417
418 #ifndef XMLSEC_NO_AES
419 if(transform->id == xmlSecGCryptTransformAes128CbcId) {
420 ctx->cipher = GCRY_CIPHER_AES128;
421 ctx->mode = GCRY_CIPHER_MODE_CBC;
422 ctx->keyId = xmlSecGCryptKeyDataAesId;
423 } else if(transform->id == xmlSecGCryptTransformAes192CbcId) {
424 ctx->cipher = GCRY_CIPHER_AES192;
425 ctx->mode = GCRY_CIPHER_MODE_CBC;
426 ctx->keyId = xmlSecGCryptKeyDataAesId;
427 } else if(transform->id == xmlSecGCryptTransformAes256CbcId) {
428 ctx->cipher = GCRY_CIPHER_AES256;
429 ctx->mode = GCRY_CIPHER_MODE_CBC;
430 ctx->keyId = xmlSecGCryptKeyDataAesId;
431 } else
432 #endif /* XMLSEC_NO_AES */
433
434 if(1) {
435 xmlSecInvalidTransfromError(transform)
436 return(-1);
437 }
438
439 err = gcry_cipher_open(&ctx->cipherCtx, ctx->cipher, ctx->mode, GCRY_CIPHER_SECURE); /* we are paranoid */
440 if(err != GPG_ERR_NO_ERROR) {
441 xmlSecGCryptError("gcry_cipher_open", err,
442 xmlSecTransformGetName(transform));
443 return(-1);
444 }
445 return(0);
446 }
447
448 static void
xmlSecGCryptBlockCipherFinalize(xmlSecTransformPtr transform)449 xmlSecGCryptBlockCipherFinalize(xmlSecTransformPtr transform) {
450 xmlSecGCryptBlockCipherCtxPtr ctx;
451
452 xmlSecAssert(xmlSecGCryptBlockCipherCheckId(transform));
453 xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize));
454
455 ctx = xmlSecGCryptBlockCipherGetCtx(transform);
456 xmlSecAssert(ctx != NULL);
457
458 if(ctx->cipherCtx != NULL) {
459 gcry_cipher_close(ctx->cipherCtx);
460 }
461
462 memset(ctx, 0, sizeof(xmlSecGCryptBlockCipherCtx));
463 }
464
465 static int
xmlSecGCryptBlockCipherSetKeyReq(xmlSecTransformPtr transform,xmlSecKeyReqPtr keyReq)466 xmlSecGCryptBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
467 xmlSecGCryptBlockCipherCtxPtr ctx;
468
469 xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1);
470 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
471 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1);
472 xmlSecAssert2(keyReq != NULL, -1);
473
474 ctx = xmlSecGCryptBlockCipherGetCtx(transform);
475 xmlSecAssert2(ctx != NULL, -1);
476 xmlSecAssert2(ctx->cipher != 0, -1);
477 xmlSecAssert2(ctx->keyId != NULL, -1);
478
479 keyReq->keyId = ctx->keyId;
480 keyReq->keyType = xmlSecKeyDataTypeSymmetric;
481 if(transform->operation == xmlSecTransformOperationEncrypt) {
482 keyReq->keyUsage = xmlSecKeyUsageEncrypt;
483 } else {
484 keyReq->keyUsage = xmlSecKeyUsageDecrypt;
485 }
486
487 keyReq->keyBitsSize = 8 * gcry_cipher_get_algo_keylen(ctx->cipher);
488 return(0);
489 }
490
491 static int
xmlSecGCryptBlockCipherSetKey(xmlSecTransformPtr transform,xmlSecKeyPtr key)492 xmlSecGCryptBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
493 xmlSecGCryptBlockCipherCtxPtr ctx;
494 xmlSecBufferPtr buffer;
495 xmlSecSize keySize;
496 gcry_err_code_t err;
497
498 xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1);
499 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
500 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1);
501 xmlSecAssert2(key != NULL, -1);
502
503 ctx = xmlSecGCryptBlockCipherGetCtx(transform);
504 xmlSecAssert2(ctx != NULL, -1);
505 xmlSecAssert2(ctx->cipherCtx != NULL, -1);
506 xmlSecAssert2(ctx->cipher != 0, -1);
507 xmlSecAssert2(ctx->keyInitialized == 0, -1);
508 xmlSecAssert2(ctx->keyId != NULL, -1);
509 xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
510
511 keySize = gcry_cipher_get_algo_keylen(ctx->cipher);
512 xmlSecAssert2(keySize > 0, -1);
513
514 buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
515 xmlSecAssert2(buffer != NULL, -1);
516
517 if(xmlSecBufferGetSize(buffer) < keySize) {
518 xmlSecInvalidKeyDataSizeError(xmlSecBufferGetSize(buffer), keySize,
519 xmlSecTransformGetName(transform));
520 return(-1);
521 }
522
523 xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1);
524 err = gcry_cipher_setkey(ctx->cipherCtx, xmlSecBufferGetData(buffer), keySize);
525 if(err != GPG_ERR_NO_ERROR) {
526 xmlSecGCryptError("gcry_cipher_setkey", err,
527 xmlSecTransformGetName(transform));
528 return(-1);
529 }
530
531 ctx->keyInitialized = 1;
532 return(0);
533 }
534
535 static int
xmlSecGCryptBlockCipherExecute(xmlSecTransformPtr transform,int last,xmlSecTransformCtxPtr transformCtx)536 xmlSecGCryptBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
537 xmlSecGCryptBlockCipherCtxPtr ctx;
538 xmlSecBufferPtr in, out;
539 int ret;
540
541 xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1);
542 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
543 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1);
544 xmlSecAssert2(transformCtx != NULL, -1);
545
546 in = &(transform->inBuf);
547 out = &(transform->outBuf);
548
549 ctx = xmlSecGCryptBlockCipherGetCtx(transform);
550 xmlSecAssert2(ctx != NULL, -1);
551
552 if(transform->status == xmlSecTransformStatusNone) {
553 transform->status = xmlSecTransformStatusWorking;
554 }
555
556 if(transform->status == xmlSecTransformStatusWorking) {
557 if(ctx->ctxInitialized == 0) {
558 ret = xmlSecGCryptBlockCipherCtxInit(ctx, in, out,
559 (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
560 xmlSecTransformGetName(transform), transformCtx);
561 if(ret < 0) {
562 xmlSecInternalError("xmlSecGCryptBlockCipherCtxInit",
563 xmlSecTransformGetName(transform));
564 return(-1);
565 }
566 }
567 if((ctx->ctxInitialized == 0) && (last != 0)) {
568 xmlSecInvalidDataError("not enough data to initialize transform",
569 xmlSecTransformGetName(transform));
570 return(-1);
571 }
572 if(ctx->ctxInitialized != 0) {
573 ret = xmlSecGCryptBlockCipherCtxUpdate(ctx, in, out,
574 (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
575 xmlSecTransformGetName(transform), transformCtx);
576 if(ret < 0) {
577 xmlSecInternalError("xmlSecGCryptBlockCipherCtxUpdate",
578 xmlSecTransformGetName(transform));
579 return(-1);
580 }
581 }
582
583 if(last) {
584 ret = xmlSecGCryptBlockCipherCtxFinal(ctx, in, out,
585 (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
586 xmlSecTransformGetName(transform), transformCtx);
587 if(ret < 0) {
588 xmlSecInternalError("xmlSecGCryptBlockCipherCtxFinal",
589 xmlSecTransformGetName(transform));
590 return(-1);
591 }
592 transform->status = xmlSecTransformStatusFinished;
593 }
594 } else if(transform->status == xmlSecTransformStatusFinished) {
595 /* the only way we can get here is if there is no input */
596 xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
597 } else if(transform->status == xmlSecTransformStatusNone) {
598 /* the only way we can get here is if there is no enough data in the input */
599 xmlSecAssert2(last == 0, -1);
600 } else {
601 xmlSecInvalidTransfromStatusError(transform);
602 return(-1);
603 }
604
605 return(0);
606 }
607
608
609 #ifndef XMLSEC_NO_AES
610 /*********************************************************************
611 *
612 * AES CBC cipher transforms
613 *
614 ********************************************************************/
615 static xmlSecTransformKlass xmlSecGCryptAes128CbcKlass = {
616 /* klass/object sizes */
617 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
618 xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */
619
620 xmlSecNameAes128Cbc, /* const xmlChar* name; */
621 xmlSecHrefAes128Cbc, /* const xmlChar* href; */
622 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
623
624 xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
625 xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
626 NULL, /* xmlSecTransformNodeReadMethod readNode; */
627 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
628 xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
629 xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
630 NULL, /* xmlSecTransformValidateMethod validate; */
631 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
632 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
633 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
634 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
635 NULL, /* xmlSecTransformPopXmlMethod popXml; */
636 xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
637
638 NULL, /* void* reserved0; */
639 NULL, /* void* reserved1; */
640 };
641
642 /**
643 * xmlSecGCryptTransformAes128CbcGetKlass:
644 *
645 * AES 128 CBC encryption transform klass.
646 *
647 * Returns: pointer to AES 128 CBC encryption transform.
648 */
649 xmlSecTransformId
xmlSecGCryptTransformAes128CbcGetKlass(void)650 xmlSecGCryptTransformAes128CbcGetKlass(void) {
651 return(&xmlSecGCryptAes128CbcKlass);
652 }
653
654 static xmlSecTransformKlass xmlSecGCryptAes192CbcKlass = {
655 /* klass/object sizes */
656 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
657 xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */
658
659 xmlSecNameAes192Cbc, /* const xmlChar* name; */
660 xmlSecHrefAes192Cbc, /* const xmlChar* href; */
661 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
662
663 xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
664 xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
665 NULL, /* xmlSecTransformNodeReadMethod readNode; */
666 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
667 xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
668 xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
669 NULL, /* xmlSecTransformValidateMethod validate; */
670 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
671 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
672 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
673 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
674 NULL, /* xmlSecTransformPopXmlMethod popXml; */
675 xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
676
677 NULL, /* void* reserved0; */
678 NULL, /* void* reserved1; */
679 };
680
681 /**
682 * xmlSecGCryptTransformAes192CbcGetKlass:
683 *
684 * AES 192 CBC encryption transform klass.
685 *
686 * Returns: pointer to AES 192 CBC encryption transform.
687 */
688 xmlSecTransformId
xmlSecGCryptTransformAes192CbcGetKlass(void)689 xmlSecGCryptTransformAes192CbcGetKlass(void) {
690 return(&xmlSecGCryptAes192CbcKlass);
691 }
692
693 static xmlSecTransformKlass xmlSecGCryptAes256CbcKlass = {
694 /* klass/object sizes */
695 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
696 xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */
697
698 xmlSecNameAes256Cbc, /* const xmlChar* name; */
699 xmlSecHrefAes256Cbc, /* const xmlChar* href; */
700 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
701
702 xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
703 xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
704 NULL, /* xmlSecTransformNodeReadMethod readNode; */
705 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
706 xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
707 xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
708 NULL, /* xmlSecTransformValidateMethod validate; */
709 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
710 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
711 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
712 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
713 NULL, /* xmlSecTransformPopXmlMethod popXml; */
714 xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
715
716 NULL, /* void* reserved0; */
717 NULL, /* void* reserved1; */
718 };
719
720 /**
721 * xmlSecGCryptTransformAes256CbcGetKlass:
722 *
723 * AES 256 CBC encryption transform klass.
724 *
725 * Returns: pointer to AES 256 CBC encryption transform.
726 */
727 xmlSecTransformId
xmlSecGCryptTransformAes256CbcGetKlass(void)728 xmlSecGCryptTransformAes256CbcGetKlass(void) {
729 return(&xmlSecGCryptAes256CbcKlass);
730 }
731
732 #endif /* XMLSEC_NO_AES */
733
734 #ifndef XMLSEC_NO_DES
735 static xmlSecTransformKlass xmlSecGCryptDes3CbcKlass = {
736 /* klass/object sizes */
737 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
738 xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */
739
740 xmlSecNameDes3Cbc, /* const xmlChar* name; */
741 xmlSecHrefDes3Cbc, /* const xmlChar* href; */
742 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
743
744 xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
745 xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
746 NULL, /* xmlSecTransformNodeReadMethod readNode; */
747 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
748 xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
749 xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
750 NULL, /* xmlSecTransformValidateMethod validate; */
751 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
752 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
753 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
754 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
755 NULL, /* xmlSecTransformPopXmlMethod popXml; */
756 xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
757
758 NULL, /* void* reserved0; */
759 NULL, /* void* reserved1; */
760 };
761
762 /**
763 * xmlSecGCryptTransformDes3CbcGetKlass:
764 *
765 * Triple DES CBC encryption transform klass.
766 *
767 * Returns: pointer to Triple DES encryption transform.
768 */
769 xmlSecTransformId
xmlSecGCryptTransformDes3CbcGetKlass(void)770 xmlSecGCryptTransformDes3CbcGetKlass(void) {
771 return(&xmlSecGCryptDes3CbcKlass);
772 }
773 #endif /* XMLSEC_NO_DES */
774
775