Git init
[external/xmlsec1.git] / src / gnutls / ciphers.c
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  */
9 #include "globals.h"
10
11 #include <string.h>
12
13 #include <gnutls/gnutls.h>
14 #include <gcrypt.h>
15
16 #include <xmlsec/xmlsec.h>
17 #include <xmlsec/keys.h>
18 #include <xmlsec/transforms.h>
19 #include <xmlsec/errors.h>
20
21 #include <xmlsec/gnutls/crypto.h>
22
23 /**************************************************************************
24  *
25  * Internal GnuTLS Block cipher CTX
26  *
27  *****************************************************************************/
28 typedef struct _xmlSecGnuTLSBlockCipherCtx              xmlSecGnuTLSBlockCipherCtx,
29                                                         *xmlSecGnuTLSBlockCipherCtxPtr;
30 struct _xmlSecGnuTLSBlockCipherCtx {
31     int                 cipher;
32     int                 mode;
33     GcryCipherHd        cipherCtx;
34     xmlSecKeyDataId     keyId;
35     int                 keyInitialized;
36     int                 ctxInitialized;
37 };
38
39 static int      xmlSecGnuTLSBlockCipherCtxInit          (xmlSecGnuTLSBlockCipherCtxPtr ctx,
40                                                          xmlSecBufferPtr in,
41                                                          xmlSecBufferPtr out,
42                                                          int encrypt,
43                                                          const xmlChar* cipherName,
44                                                          xmlSecTransformCtxPtr transformCtx);
45 static int      xmlSecGnuTLSBlockCipherCtxUpdate        (xmlSecGnuTLSBlockCipherCtxPtr ctx,
46                                                          xmlSecBufferPtr in,
47                                                          xmlSecBufferPtr out,
48                                                          int encrypt,
49                                                          const xmlChar* cipherName,
50                                                          xmlSecTransformCtxPtr transformCtx);
51 static int      xmlSecGnuTLSBlockCipherCtxFinal         (xmlSecGnuTLSBlockCipherCtxPtr ctx,
52                                                          xmlSecBufferPtr in,
53                                                          xmlSecBufferPtr out,
54                                                          int encrypt,
55                                                          const xmlChar* cipherName,
56                                                          xmlSecTransformCtxPtr transformCtx);
57 static int 
58 xmlSecGnuTLSBlockCipherCtxInit(xmlSecGnuTLSBlockCipherCtxPtr ctx,
59                                 xmlSecBufferPtr in, xmlSecBufferPtr out,
60                                 int encrypt,
61                                 const xmlChar* cipherName,
62                                 xmlSecTransformCtxPtr transformCtx) {
63     int blockLen;
64     int ret;
65
66     xmlSecAssert2(ctx != NULL, -1);
67     xmlSecAssert2(ctx->cipher != 0, -1);
68     xmlSecAssert2(ctx->cipherCtx != NULL, -1);
69     xmlSecAssert2(ctx->keyInitialized != 0, -1);
70     xmlSecAssert2(ctx->ctxInitialized == 0, -1);
71     xmlSecAssert2(in != NULL, -1);
72     xmlSecAssert2(out != NULL, -1);
73     xmlSecAssert2(transformCtx != NULL, -1);
74
75     /* iv len == block len */
76     blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
77     xmlSecAssert2(blockLen > 0, -1);
78     
79     if(encrypt) {
80         xmlSecByte* iv;
81         xmlSecSize outSize;
82         
83         /* allocate space for IV */     
84         outSize = xmlSecBufferGetSize(out);
85         ret = xmlSecBufferSetSize(out, outSize + blockLen);
86         if(ret < 0) {
87             xmlSecError(XMLSEC_ERRORS_HERE, 
88                         xmlSecErrorsSafeString(cipherName),
89                         "xmlSecBufferSetSize",
90                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
91                         "size=%d", outSize + blockLen);
92             return(-1);
93         }
94         iv = xmlSecBufferGetData(out) + outSize;
95         
96         /* generate and use random iv */
97         gcry_randomize(iv, blockLen, GCRY_STRONG_RANDOM);
98         ret = gcry_cipher_setiv(ctx->cipherCtx, iv, blockLen);
99         if(ret != 0) {
100             xmlSecError(XMLSEC_ERRORS_HERE, 
101                         xmlSecErrorsSafeString(cipherName),
102                         "gcry_cipher_setiv",
103                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
104                         "ret=%d", ret);
105             return(-1);
106         }
107     } else {
108         /* if we don't have enough data, exit and hope that 
109          * we'll have iv next time */
110         if(xmlSecBufferGetSize(in) < (xmlSecSize)blockLen) {
111             return(0);
112         }
113         xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1);
114
115         /* set iv */
116         ret = gcry_cipher_setiv(ctx->cipherCtx, xmlSecBufferGetData(in), blockLen);
117         if(ret != 0) {
118             xmlSecError(XMLSEC_ERRORS_HERE, 
119                         xmlSecErrorsSafeString(cipherName),
120                         "gcry_cipher_setiv",
121                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
122                         "ret=%d", ret);
123             return(-1);
124         }
125         
126         /* and remove from input */
127         ret = xmlSecBufferRemoveHead(in, blockLen);
128         if(ret < 0) {
129             xmlSecError(XMLSEC_ERRORS_HERE, 
130                         xmlSecErrorsSafeString(cipherName),
131                         "xmlSecBufferRemoveHead",
132                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
133                         "size=%d", blockLen);
134             return(-1);
135         }
136     }
137
138     ctx->ctxInitialized = 1;
139     return(0);
140 }
141
142 static int 
143 xmlSecGnuTLSBlockCipherCtxUpdate(xmlSecGnuTLSBlockCipherCtxPtr ctx,
144                                   xmlSecBufferPtr in, xmlSecBufferPtr out,
145                                   int encrypt,
146                                   const xmlChar* cipherName,
147                                   xmlSecTransformCtxPtr transformCtx) {
148     xmlSecSize inSize, inBlocks, outSize;
149     int blockLen;
150     xmlSecByte* outBuf;
151     int ret;
152     
153     xmlSecAssert2(ctx != NULL, -1);
154     xmlSecAssert2(ctx->cipher != 0, -1);
155     xmlSecAssert2(ctx->cipherCtx != NULL, -1);
156     xmlSecAssert2(ctx->ctxInitialized != 0, -1);
157     xmlSecAssert2(in != NULL, -1);
158     xmlSecAssert2(out != NULL, -1);
159     xmlSecAssert2(transformCtx != NULL, -1);
160
161     blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
162     xmlSecAssert2(blockLen > 0, -1);
163
164     inSize = xmlSecBufferGetSize(in);
165     outSize = xmlSecBufferGetSize(out);
166     
167     if(inSize < (xmlSecSize)blockLen) {
168         return(0);
169     }
170
171     if(encrypt) {
172         inBlocks = inSize / ((xmlSecSize)blockLen);
173     } else {
174         /* we want to have the last block in the input buffer 
175          * for padding check */
176         inBlocks = (inSize - 1) / ((xmlSecSize)blockLen);
177     }
178     inSize = inBlocks * ((xmlSecSize)blockLen);
179
180     /* we write out the input size plus may be one block */
181     ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen);
182     if(ret < 0) {
183         xmlSecError(XMLSEC_ERRORS_HERE, 
184                     xmlSecErrorsSafeString(cipherName),
185                     "xmlSecBufferSetMaxSize",
186                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
187                     "size=%d", outSize + inSize + blockLen);
188         return(-1);
189     }
190     outBuf = xmlSecBufferGetData(out) + outSize;
191     
192     if(encrypt) {
193         ret = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
194                                 xmlSecBufferGetData(in), inSize);
195         if(ret != 0) {
196             xmlSecError(XMLSEC_ERRORS_HERE, 
197                         xmlSecErrorsSafeString(cipherName),
198                         "gcry_cipher_encrypt",
199                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
200                         "ret=%d", ret);
201             return(-1);
202         }
203     } else {
204         ret = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
205                                 xmlSecBufferGetData(in), inSize);
206         if(ret != 0) {
207             xmlSecError(XMLSEC_ERRORS_HERE, 
208                         xmlSecErrorsSafeString(cipherName),
209                         "gcry_cipher_decrypt",
210                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
211                         "ret=%d", ret);
212             return(-1);
213         }
214     }
215
216     /* set correct output buffer size */
217     ret = xmlSecBufferSetSize(out, outSize + inSize);
218     if(ret < 0) {
219         xmlSecError(XMLSEC_ERRORS_HERE, 
220                     xmlSecErrorsSafeString(cipherName),
221                     "xmlSecBufferSetSize",
222                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
223                     "size=%d", outSize + inSize);
224         return(-1);
225     }
226         
227     /* remove the processed block from input */
228     ret = xmlSecBufferRemoveHead(in, inSize);
229     if(ret < 0) {
230         xmlSecError(XMLSEC_ERRORS_HERE, 
231                     xmlSecErrorsSafeString(cipherName),
232                     "xmlSecBufferRemoveHead",
233                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
234                     "size=%d", inSize);
235         return(-1);
236     }
237     return(0);
238 }
239
240 static int 
241 xmlSecGnuTLSBlockCipherCtxFinal(xmlSecGnuTLSBlockCipherCtxPtr ctx,
242                                  xmlSecBufferPtr in,
243                                  xmlSecBufferPtr out,
244                                  int encrypt,
245                                  const xmlChar* cipherName,
246                                  xmlSecTransformCtxPtr transformCtx) {
247     xmlSecSize inSize, outSize;
248     int blockLen, outLen = 0;
249     xmlSecByte* inBuf;
250     xmlSecByte* outBuf;
251     int ret;
252     
253     xmlSecAssert2(ctx != NULL, -1);
254     xmlSecAssert2(ctx->cipher != 0, -1);
255     xmlSecAssert2(ctx->cipherCtx != NULL, -1);
256     xmlSecAssert2(ctx->ctxInitialized != 0, -1);
257     xmlSecAssert2(in != NULL, -1);
258     xmlSecAssert2(out != NULL, -1);
259     xmlSecAssert2(transformCtx != NULL, -1);
260
261     blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
262     xmlSecAssert2(blockLen > 0, -1);
263
264     inSize = xmlSecBufferGetSize(in);
265     outSize = xmlSecBufferGetSize(out);
266
267     if(encrypt != 0) {
268         xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1);        
269     
270         /* create padding */
271         ret = xmlSecBufferSetMaxSize(in, blockLen);
272         if(ret < 0) {
273             xmlSecError(XMLSEC_ERRORS_HERE, 
274                         xmlSecErrorsSafeString(cipherName),
275                         "xmlSecBufferSetMaxSize",
276                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
277                         "size=%d", blockLen);
278             return(-1);
279         }
280         inBuf = xmlSecBufferGetData(in);
281
282         /* create random padding */
283         if((xmlSecSize)blockLen > (inSize + 1)) {
284             gcry_randomize(inBuf + inSize, blockLen - inSize - 1, 
285                         GCRY_STRONG_RANDOM); /* as usual, we are paranoid */
286         }
287         inBuf[blockLen - 1] = blockLen - inSize;
288         inSize = blockLen;
289     } else {
290         if(inSize != (xmlSecSize)blockLen) {
291             xmlSecError(XMLSEC_ERRORS_HERE, 
292                         xmlSecErrorsSafeString(cipherName),
293                         NULL,
294                         XMLSEC_ERRORS_R_INVALID_DATA,
295                         "data=%d;block=%d", inSize, blockLen);
296             return(-1);
297         }
298     }
299     
300     /* process last block */
301     ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen);
302     if(ret < 0) {
303         xmlSecError(XMLSEC_ERRORS_HERE, 
304                     xmlSecErrorsSafeString(cipherName),
305                     "xmlSecBufferSetMaxSize",
306                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
307                     "size=%d", outSize + 2 * blockLen);
308         return(-1);
309     }
310     outBuf = xmlSecBufferGetData(out) + outSize;
311
312     if(encrypt) {
313         ret = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
314                                 xmlSecBufferGetData(in), inSize);
315         if(ret != 0) {
316             xmlSecError(XMLSEC_ERRORS_HERE, 
317                         xmlSecErrorsSafeString(cipherName),
318                         "gcry_cipher_encrypt",
319                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
320                         "ret=%d", ret);
321             return(-1);
322         }
323     } else {
324         ret = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
325                                 xmlSecBufferGetData(in), inSize);
326         if(ret != 0) {
327             xmlSecError(XMLSEC_ERRORS_HERE, 
328                         xmlSecErrorsSafeString(cipherName),
329                         "gcry_cipher_decrypt",
330                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
331                         "ret=%d", ret);
332             return(-1);
333         }
334     }
335
336     if(encrypt == 0) {
337         /* check padding */
338         if(inSize < outBuf[blockLen - 1]) {
339             xmlSecError(XMLSEC_ERRORS_HERE,
340                         xmlSecErrorsSafeString(cipherName),
341                         NULL,
342                         XMLSEC_ERRORS_R_INVALID_DATA,
343                         "padding=%d;buffer=%d",
344                         outBuf[blockLen - 1], inSize);
345             return(-1); 
346         }
347         outLen = inSize - outBuf[blockLen - 1];
348     } else {
349         outLen = inSize;
350     }
351
352     /* set correct output buffer size */
353     ret = xmlSecBufferSetSize(out, outSize + outLen);
354     if(ret < 0) {
355         xmlSecError(XMLSEC_ERRORS_HERE, 
356                     xmlSecErrorsSafeString(cipherName),
357                     "xmlSecBufferSetSize",
358                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
359                     "size=%d", outSize + outLen);
360         return(-1);
361     }
362         
363     /* remove the processed block from input */
364     ret = xmlSecBufferRemoveHead(in, inSize);
365     if(ret < 0) {
366         xmlSecError(XMLSEC_ERRORS_HERE, 
367                     xmlSecErrorsSafeString(cipherName),
368                     "xmlSecBufferRemoveHead",
369                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
370                     "size=%d", inSize);
371         return(-1);
372     }
373     
374
375     /* set correct output buffer size */
376     ret = xmlSecBufferSetSize(out, outSize + outLen);
377     if(ret < 0) {
378         xmlSecError(XMLSEC_ERRORS_HERE, 
379                     xmlSecErrorsSafeString(cipherName),
380                     "xmlSecBufferSetSize",
381                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
382                     "size=%d", outSize + outLen);
383         return(-1);
384     }
385
386     /* remove the processed block from input */
387     ret = xmlSecBufferRemoveHead(in, inSize);
388     if(ret < 0) {
389         xmlSecError(XMLSEC_ERRORS_HERE, 
390                     xmlSecErrorsSafeString(cipherName),
391                     "xmlSecBufferRemoveHead",
392                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
393                     "size=%d", inSize);
394         return(-1);
395     }
396
397     return(0);
398 }
399
400
401 /******************************************************************************
402  *
403  *  Block Cipher transforms
404  *
405  * xmlSecGnuTLSBlockCipherCtx block is located after xmlSecTransform structure
406  * 
407  *****************************************************************************/
408 #define xmlSecGnuTLSBlockCipherSize     \
409     (sizeof(xmlSecTransform) + sizeof(xmlSecGnuTLSBlockCipherCtx))
410 #define xmlSecGnuTLSBlockCipherGetCtx(transform) \
411     ((xmlSecGnuTLSBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
412
413 static int      xmlSecGnuTLSBlockCipherInitialize       (xmlSecTransformPtr transform);
414 static void     xmlSecGnuTLSBlockCipherFinalize         (xmlSecTransformPtr transform);
415 static int      xmlSecGnuTLSBlockCipherSetKeyReq        (xmlSecTransformPtr transform, 
416                                                          xmlSecKeyReqPtr keyReq);
417 static int      xmlSecGnuTLSBlockCipherSetKey           (xmlSecTransformPtr transform,
418                                                          xmlSecKeyPtr key);
419 static int      xmlSecGnuTLSBlockCipherExecute          (xmlSecTransformPtr transform,
420                                                          int last,
421                                                          xmlSecTransformCtxPtr transformCtx);
422 static int      xmlSecGnuTLSBlockCipherCheckId          (xmlSecTransformPtr transform);
423                                                          
424
425
426 static int
427 xmlSecGnuTLSBlockCipherCheckId(xmlSecTransformPtr transform) {
428 #ifndef XMLSEC_NO_DES
429     if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformDes3CbcId)) {
430         return(1);
431     }
432 #endif /* XMLSEC_NO_DES */
433
434 #ifndef XMLSEC_NO_AES
435     if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformAes128CbcId) ||
436        xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformAes192CbcId) ||
437        xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformAes256CbcId)) {
438        
439        return(1);
440     }
441 #endif /* XMLSEC_NO_AES */
442     
443     return(0);
444 }
445
446 static int 
447 xmlSecGnuTLSBlockCipherInitialize(xmlSecTransformPtr transform) {
448     xmlSecGnuTLSBlockCipherCtxPtr ctx;
449 #ifndef XMLSEC_GNUTLS_OLD
450     gpg_err_code_t ret;
451 #endif /* XMLSEC_GNUTLS_OLD */
452     
453     xmlSecAssert2(xmlSecGnuTLSBlockCipherCheckId(transform), -1);
454     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize), -1);
455
456     ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
457     xmlSecAssert2(ctx != NULL, -1);
458     
459     memset(ctx, 0, sizeof(xmlSecGnuTLSBlockCipherCtx));
460
461 #ifndef XMLSEC_NO_DES
462     if(transform->id == xmlSecGnuTLSTransformDes3CbcId) {
463         ctx->cipher     = GCRY_CIPHER_3DES;
464         ctx->mode       = GCRY_CIPHER_MODE_CBC;
465         ctx->keyId      = xmlSecGnuTLSKeyDataDesId;
466     } else 
467 #endif /* XMLSEC_NO_DES */
468
469 #ifndef XMLSEC_NO_AES
470     if(transform->id == xmlSecGnuTLSTransformAes128CbcId) {
471         ctx->cipher     = GCRY_CIPHER_AES128;   
472         ctx->mode       = GCRY_CIPHER_MODE_CBC;
473         ctx->keyId      = xmlSecGnuTLSKeyDataAesId;
474     } else if(transform->id == xmlSecGnuTLSTransformAes192CbcId) {
475         ctx->cipher     = GCRY_CIPHER_AES192;   
476         ctx->mode       = GCRY_CIPHER_MODE_CBC;
477         ctx->keyId      = xmlSecGnuTLSKeyDataAesId;
478     } else if(transform->id == xmlSecGnuTLSTransformAes256CbcId) {
479         ctx->cipher     = GCRY_CIPHER_AES256;   
480         ctx->mode       = GCRY_CIPHER_MODE_CBC;
481         ctx->keyId      = xmlSecGnuTLSKeyDataAesId;
482     } else 
483 #endif /* XMLSEC_NO_AES */
484
485     if(1) {
486         xmlSecError(XMLSEC_ERRORS_HERE, 
487                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
488                     NULL,
489                     XMLSEC_ERRORS_R_INVALID_TRANSFORM,
490                     XMLSEC_ERRORS_NO_MESSAGE);
491         return(-1);
492     }        
493
494 #ifndef XMLSEC_GNUTLS_OLD
495     ret = gcry_cipher_open(&ctx->cipherCtx, ctx->cipher, ctx->mode, GCRY_CIPHER_SECURE); /* we are paranoid */
496     if(ret != GPG_ERR_NO_ERROR) {
497 #else /* XMLSEC_GNUTLS_OLD */ 
498     ctx->cipherCtx = gcry_cipher_open(ctx->cipher, ctx->mode, GCRY_CIPHER_SECURE); /* we are paranoid */
499     if(ctx->cipherCtx == NULL) {
500 #endif /* XMLSEC_GNUTLS_OLD */
501         xmlSecError(XMLSEC_ERRORS_HERE, 
502                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
503                     "gcry_cipher_open",
504                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
505                     XMLSEC_ERRORS_NO_MESSAGE);
506         return(-1);
507     }
508     return(0);
509 }
510
511 static void 
512 xmlSecGnuTLSBlockCipherFinalize(xmlSecTransformPtr transform) {
513     xmlSecGnuTLSBlockCipherCtxPtr ctx;
514
515     xmlSecAssert(xmlSecGnuTLSBlockCipherCheckId(transform));
516     xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize));
517
518     ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
519     xmlSecAssert(ctx != NULL);
520
521     if(ctx->cipherCtx != NULL) {
522         gcry_cipher_close(ctx->cipherCtx);
523     }
524     
525     memset(ctx, 0, sizeof(xmlSecGnuTLSBlockCipherCtx));
526 }
527
528 static int  
529 xmlSecGnuTLSBlockCipherSetKeyReq(xmlSecTransformPtr transform,  xmlSecKeyReqPtr keyReq) {
530     xmlSecGnuTLSBlockCipherCtxPtr ctx;
531
532     xmlSecAssert2(xmlSecGnuTLSBlockCipherCheckId(transform), -1);
533     xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
534     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize), -1);
535     xmlSecAssert2(keyReq != NULL, -1);
536
537     ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
538     xmlSecAssert2(ctx != NULL, -1);
539     xmlSecAssert2(ctx->cipher != 0, -1);
540     xmlSecAssert2(ctx->keyId != NULL, -1);
541
542     keyReq->keyId       = ctx->keyId;
543     keyReq->keyType     = xmlSecKeyDataTypeSymmetric;
544     if(transform->operation == xmlSecTransformOperationEncrypt) {
545         keyReq->keyUsage = xmlSecKeyUsageEncrypt;
546     } else {
547         keyReq->keyUsage = xmlSecKeyUsageDecrypt;
548     }
549
550     keyReq->keyBitsSize = 8 * gcry_cipher_get_algo_keylen(ctx->cipher);
551     return(0);
552 }
553
554 static int
555 xmlSecGnuTLSBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
556     xmlSecGnuTLSBlockCipherCtxPtr ctx;
557     xmlSecBufferPtr buffer;
558     xmlSecSize keySize;
559     int ret;
560     
561     xmlSecAssert2(xmlSecGnuTLSBlockCipherCheckId(transform), -1);
562     xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
563     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize), -1);
564     xmlSecAssert2(key != NULL, -1);
565
566     ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
567     xmlSecAssert2(ctx != NULL, -1);
568     xmlSecAssert2(ctx->cipherCtx != NULL, -1);
569     xmlSecAssert2(ctx->cipher != 0, -1);
570     xmlSecAssert2(ctx->keyInitialized == 0, -1);
571     xmlSecAssert2(ctx->keyId != NULL, -1);
572     xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
573
574     keySize = gcry_cipher_get_algo_keylen(ctx->cipher);
575     xmlSecAssert2(keySize > 0, -1);
576
577     buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
578     xmlSecAssert2(buffer != NULL, -1);
579
580     if(xmlSecBufferGetSize(buffer) < keySize) {
581         xmlSecError(XMLSEC_ERRORS_HERE,
582                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
583                     NULL,
584                     XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
585                     "keySize=%d;expected=%d",
586                     xmlSecBufferGetSize(buffer), keySize);
587         return(-1);
588     }
589     
590     xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1);
591     ret = gcry_cipher_setkey(ctx->cipherCtx, xmlSecBufferGetData(buffer), keySize);
592     if(ret != 0) {
593         xmlSecError(XMLSEC_ERRORS_HERE, 
594                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
595                     "gcry_cipher_setkey",
596                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
597                     "ret=%d", ret);
598         return(-1);
599     }
600     
601     ctx->keyInitialized = 1;
602     return(0);
603 }
604
605 static int 
606 xmlSecGnuTLSBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
607     xmlSecGnuTLSBlockCipherCtxPtr ctx;
608     xmlSecBufferPtr in, out;
609     int ret;
610     
611     xmlSecAssert2(xmlSecGnuTLSBlockCipherCheckId(transform), -1);
612     xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
613     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize), -1);
614     xmlSecAssert2(transformCtx != NULL, -1);
615
616     in = &(transform->inBuf);
617     out = &(transform->outBuf);
618
619     ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
620     xmlSecAssert2(ctx != NULL, -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 = xmlSecGnuTLSBlockCipherCtxInit(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                             "xmlSecGnuTLSBlockCipherCtxInit",
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 = xmlSecGnuTLSBlockCipherCtxUpdate(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                             "xmlSecGnuTLSBlockCipherCtxUpdate",
656                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
657                             XMLSEC_ERRORS_NO_MESSAGE);
658                 return(-1);
659             }
660         }
661         
662         if(last) {
663             ret = xmlSecGnuTLSBlockCipherCtxFinal(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                             "xmlSecGnuTLSBlockCipherCtxFinal",
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 xmlSecGnuTLSAes128CbcKlass = {
702     /* klass/object sizes */
703     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
704     xmlSecGnuTLSBlockCipherSize,                /* xmlSecSize objSize */
705
706     xmlSecNameAes128Cbc,                        /* const xmlChar* name; */
707     xmlSecHrefAes128Cbc,                        /* const xmlChar* href; */
708     xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
709
710     xmlSecGnuTLSBlockCipherInitialize,          /* xmlSecTransformInitializeMethod initialize; */
711     xmlSecGnuTLSBlockCipherFinalize,            /* xmlSecTransformFinalizeMethod finalize; */
712     NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
713     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
714     xmlSecGnuTLSBlockCipherSetKeyReq,           /* xmlSecTransformSetKeyMethod setKeyReq; */
715     xmlSecGnuTLSBlockCipherSetKey,              /* xmlSecTransformSetKeyMethod setKey; */
716     NULL,                                       /* xmlSecTransformValidateMethod validate; */
717     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
718     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
719     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
720     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
721     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
722     xmlSecGnuTLSBlockCipherExecute,             /* xmlSecTransformExecuteMethod execute; */
723
724     NULL,                                       /* void* reserved0; */
725     NULL,                                       /* void* reserved1; */
726 };
727
728 /**
729  * xmlSecGnuTLSTransformAes128CbcGetKlass:
730  * 
731  * AES 128 CBC encryption transform klass.
732  * 
733  * Returns: pointer to AES 128 CBC encryption transform.
734  */ 
735 xmlSecTransformId 
736 xmlSecGnuTLSTransformAes128CbcGetKlass(void) {
737     return(&xmlSecGnuTLSAes128CbcKlass);
738 }
739
740 static xmlSecTransformKlass xmlSecGnuTLSAes192CbcKlass = {
741     /* klass/object sizes */
742     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
743     xmlSecGnuTLSBlockCipherSize,                /* xmlSecSize objSize */
744
745     xmlSecNameAes192Cbc,                        /* const xmlChar* name; */
746     xmlSecHrefAes192Cbc,                        /* const xmlChar* href; */
747     xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
748
749     xmlSecGnuTLSBlockCipherInitialize,          /* xmlSecTransformInitializeMethod initialize; */
750     xmlSecGnuTLSBlockCipherFinalize,            /* xmlSecTransformFinalizeMethod finalize; */
751     NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
752     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
753     xmlSecGnuTLSBlockCipherSetKeyReq,           /* xmlSecTransformSetKeyMethod setKeyReq; */
754     xmlSecGnuTLSBlockCipherSetKey,              /* xmlSecTransformSetKeyMethod setKey; */
755     NULL,                                       /* xmlSecTransformValidateMethod validate; */
756     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
757     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
758     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
759     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
760     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
761     xmlSecGnuTLSBlockCipherExecute,             /* xmlSecTransformExecuteMethod execute; */
762     
763     NULL,                                       /* void* reserved0; */
764     NULL,                                       /* void* reserved1; */
765 };
766
767 /**
768  * xmlSecGnuTLSTransformAes192CbcGetKlass:
769  * 
770  * AES 192 CBC encryption transform klass.
771  * 
772  * Returns: pointer to AES 192 CBC encryption transform.
773  */ 
774 xmlSecTransformId 
775 xmlSecGnuTLSTransformAes192CbcGetKlass(void) {
776     return(&xmlSecGnuTLSAes192CbcKlass);
777 }
778
779 static xmlSecTransformKlass xmlSecGnuTLSAes256CbcKlass = {
780     /* klass/object sizes */
781     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
782     xmlSecGnuTLSBlockCipherSize,                /* xmlSecSize objSize */
783
784     xmlSecNameAes256Cbc,                        /* const xmlChar* name; */
785     xmlSecHrefAes256Cbc,                        /* const xmlChar* href; */
786     xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
787
788     xmlSecGnuTLSBlockCipherInitialize,          /* xmlSecTransformInitializeMethod initialize; */
789     xmlSecGnuTLSBlockCipherFinalize,            /* xmlSecTransformFinalizeMethod finalize; */
790     NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
791     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
792     xmlSecGnuTLSBlockCipherSetKeyReq,           /* xmlSecTransformSetKeyMethod setKeyReq; */
793     xmlSecGnuTLSBlockCipherSetKey,              /* xmlSecTransformSetKeyMethod setKey; */
794     NULL,                                       /* xmlSecTransformValidateMethod validate; */
795     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
796     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
797     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
798     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
799     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
800     xmlSecGnuTLSBlockCipherExecute,             /* xmlSecTransformExecuteMethod execute; */
801     
802     NULL,                                       /* void* reserved0; */
803     NULL,                                       /* void* reserved1; */
804 };
805
806 /**
807  * xmlSecGnuTLSTransformAes256CbcGetKlass:
808  * 
809  * AES 256 CBC encryption transform klass.
810  * 
811  * Returns: pointer to AES 256 CBC encryption transform.
812  */ 
813 xmlSecTransformId 
814 xmlSecGnuTLSTransformAes256CbcGetKlass(void) {
815     return(&xmlSecGnuTLSAes256CbcKlass);
816 }
817
818 #endif /* XMLSEC_NO_AES */
819
820 #ifndef XMLSEC_NO_DES
821 static xmlSecTransformKlass xmlSecGnuTLSDes3CbcKlass = {
822     /* klass/object sizes */
823     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
824     xmlSecGnuTLSBlockCipherSize,                /* xmlSecSize objSize */
825
826     xmlSecNameDes3Cbc,                          /* const xmlChar* name; */
827     xmlSecHrefDes3Cbc,                          /* const xmlChar* href; */
828     xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
829
830     xmlSecGnuTLSBlockCipherInitialize,          /* xmlSecTransformInitializeMethod initialize; */
831     xmlSecGnuTLSBlockCipherFinalize,            /* xmlSecTransformFinalizeMethod finalize; */
832     NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
833     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
834     xmlSecGnuTLSBlockCipherSetKeyReq,           /* xmlSecTransformSetKeyMethod setKeyReq; */
835     xmlSecGnuTLSBlockCipherSetKey,              /* xmlSecTransformSetKeyMethod setKey; */
836     NULL,                                       /* xmlSecTransformValidateMethod validate; */
837     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
838     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
839     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
840     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
841     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
842     xmlSecGnuTLSBlockCipherExecute,             /* xmlSecTransformExecuteMethod execute; */
843     
844     NULL,                                       /* void* reserved0; */
845     NULL,                                       /* void* reserved1; */
846 };
847
848 /** 
849  * xmlSecGnuTLSTransformDes3CbcGetKlass:
850  *
851  * Triple DES CBC encryption transform klass.
852  * 
853  * Returns: pointer to Triple DES encryption transform.
854  */
855 xmlSecTransformId 
856 xmlSecGnuTLSTransformDes3CbcGetKlass(void) {
857     return(&xmlSecGnuTLSDes3CbcKlass);
858 }
859 #endif /* XMLSEC_NO_DES */
860