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