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