xmlsecurityengine/xmlsec/src/xmlsec_base64.c
changeset 0 e35f40988205
child 24 74f0b3eb154c
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /**
       
     2  * XML Security Library (http://www.aleksey.com/xmlsec).
       
     3  *
       
     4  * Base64 encode/decode transform and utility functions.
       
     5  *
       
     6  * This is free software; see Copyright file in the source
       
     7  * distribution for preciese wording.
       
     8  * 
       
     9  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
       
    10  * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
       
    11  */
       
    12 #include "xmlsec_globals.h"
       
    13 
       
    14 #include <stdlib.h>
       
    15 #include <stdio.h>
       
    16 #include <string.h>
       
    17 
       
    18 #include <libxml2_tree.h>
       
    19 #include <libxml2_globals.h>
       
    20 
       
    21 
       
    22 #include "xmlsec_xmlsec.h"
       
    23 #include "xmlsec_keys.h"
       
    24 #include "xmlsec_transforms.h"
       
    25 #include "xmlsec_base64.h"
       
    26 #include "xmlsec_errors.h"
       
    27 
       
    28 
       
    29 /* 
       
    30  * the table to map numbers to base64 
       
    31  */
       
    32 static const xmlSecByte base64[] =
       
    33 {  
       
    34 /*   0    1    2    3    4    5    6    7   */
       
    35     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 0 */
       
    36     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 1 */
       
    37     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 2 */
       
    38     'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 3 */
       
    39     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 4 */
       
    40     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 5 */
       
    41     'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 6 */
       
    42     '4', '5', '6', '7', '8', '9', '+', '/'  /* 7 */
       
    43 };
       
    44 
       
    45 
       
    46 /* few macros to simplify the code */
       
    47 #define xmlSecBase64Encode1(a) 		(((a) >> 2) & 0x3F)
       
    48 #define xmlSecBase64Encode2(a, b) 	((((a) << 4) & 0x30) + (((b) >> 4) & 0x0F))
       
    49 #define xmlSecBase64Encode3(b, c) 	((((b) << 2) & 0x3c) + (((c) >> 6) & 0x03))
       
    50 #define xmlSecBase64Encode4(c)		((c) & 0x3F)
       
    51 
       
    52 #define xmlSecBase64Decode1(a, b)	(((a) << 2) | (((b) & 0x3F) >> 4))
       
    53 #define xmlSecBase64Decode2(b, c)	(((b) << 4) | (((c) & 0x3F) >> 2))
       
    54 #define xmlSecBase64Decode3(c, d)	(((c) << 6) | ((d) & 0x3F))
       
    55 	
       
    56 #define xmlSecIsBase64Char(ch) 		((((ch) >= 'A') && ((ch) <= 'Z')) || \
       
    57 					 (((ch) >= 'a') && ((ch) <= 'z')) || \
       
    58 					 (((ch) >= '0') && ((ch) <= '9')) || \
       
    59 					 ((ch) == '+') || ((ch) == '/')) 
       
    60 #define xmlSecIsBase64Space(ch)		(((ch) == ' ') || ((ch) == '\t') || \
       
    61 					 ((ch) == '\x0d') || ((ch) == '\x0a'))
       
    62 
       
    63 
       
    64 
       
    65 /***********************************************************************
       
    66  *
       
    67  * Base64 Context
       
    68  *
       
    69  ***********************************************************************/
       
    70 typedef enum {
       
    71     xmlSecBase64StatusConsumeAndNext  = 0,
       
    72     xmlSecBase64StatusConsumeAndRepeat,
       
    73     xmlSecBase64StatusNext,
       
    74     xmlSecBase64StatusDone,
       
    75     xmlSecBase64StatusFailed
       
    76 } xmlSecBase64Status;
       
    77 
       
    78 struct _xmlSecBase64Ctx {
       
    79     int			encode;    
       
    80     int                 inByte;
       
    81     int                 inPos;
       
    82     xmlSecSize		linePos;
       
    83     xmlSecSize		columns;  
       
    84     int                 finished;
       
    85 };
       
    86 
       
    87 static xmlSecBase64Status	xmlSecBase64CtxEncodeByte	(xmlSecBase64CtxPtr ctx, 
       
    88 								 xmlSecByte  inByte, 
       
    89 								 xmlSecByte* outByte);
       
    90 static xmlSecBase64Status	xmlSecBase64CtxEncodeByteFinal	(xmlSecBase64CtxPtr ctx, 
       
    91 								 xmlSecByte* outByte);
       
    92 static xmlSecBase64Status	xmlSecBase64CtxDecodeByte	(xmlSecBase64CtxPtr ctx, 
       
    93 								 xmlSecByte inByte, 
       
    94 								 xmlSecByte* outByte);
       
    95 static int			xmlSecBase64CtxEncode		(xmlSecBase64CtxPtr ctx, 
       
    96                 						 const xmlSecByte* inBuf, 
       
    97 								 xmlSecSize inBufSize, 
       
    98 								 xmlSecSize* inBufResSize,
       
    99                 						 xmlSecByte* outBuf, 
       
   100 								 xmlSecSize outBufSize, 
       
   101 								 xmlSecSize* outBufResSize);
       
   102 static int			xmlSecBase64CtxEncodeFinal	(xmlSecBase64CtxPtr ctx, 
       
   103                 						 xmlSecByte* outBuf, 
       
   104 								 xmlSecSize outBufSize, 
       
   105 								 xmlSecSize* outBufResSize);
       
   106 static int			xmlSecBase64CtxDecode		(xmlSecBase64CtxPtr ctx, 
       
   107                 						 const xmlSecByte* inBuf, 
       
   108 								 xmlSecSize inBufSize, 
       
   109 								 xmlSecSize* inBufResSize,
       
   110                 						 xmlSecByte* outBuf, 
       
   111 								 xmlSecSize outBufSize, 
       
   112 								 xmlSecSize* outBufResSize);
       
   113 static int			xmlSecBase64CtxDecodeIsFinished	(xmlSecBase64CtxPtr ctx);
       
   114 
       
   115 /**
       
   116  * xmlSecBase64CtxCreate:
       
   117  * @encode:		the encode/decode flag (1 - encode, 0 - decode) 
       
   118  * @columns: 		the max line length.
       
   119  *
       
   120  * Allocates and initializes new base64 context.
       
   121  *
       
   122  * Returns a pointer to newly created #xmlSecBase64Ctx structure
       
   123  * or NULL if an error occurs.
       
   124  */
       
   125 EXPORT_C
       
   126 xmlSecBase64CtxPtr	
       
   127 xmlSecBase64CtxCreate(int encode, int columns) {
       
   128     xmlSecBase64CtxPtr ctx;
       
   129     int ret;
       
   130     
       
   131     /*
       
   132      * Allocate a new xmlSecBase64CtxPtr and fill the fields.
       
   133      */
       
   134     ctx = (xmlSecBase64CtxPtr) xmlMalloc(sizeof(xmlSecBase64Ctx));    
       
   135     if (ctx == NULL) {
       
   136 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   137 		    NULL,
       
   138 		    NULL,
       
   139 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   140 		    "sizeof(xmlSecBase64Ctx)=%d", 
       
   141 		    sizeof(xmlSecBase64Ctx));
       
   142 	return(NULL);
       
   143     }
       
   144     
       
   145     ret = xmlSecBase64CtxInitialize(ctx, encode, columns);
       
   146     if(ret < 0) {
       
   147 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   148 		    NULL,
       
   149 		    "xmlSecBase64CtxInitialize",
       
   150 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   151 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   152 	xmlSecBase64CtxDestroy(ctx);
       
   153 	return(NULL);
       
   154     }
       
   155     return(ctx);
       
   156 }
       
   157 
       
   158 /**
       
   159  * xmlSecBase64CtxDestroy:
       
   160  * @ctx: 		the pointer to #xmlSecBase64Ctx structure.
       
   161  * 
       
   162  * Destroys base64 context.
       
   163  */
       
   164 EXPORT_C
       
   165 void
       
   166 xmlSecBase64CtxDestroy(xmlSecBase64CtxPtr ctx) {
       
   167     xmlSecAssert(ctx != NULL);
       
   168     
       
   169     xmlSecBase64CtxFinalize(ctx);
       
   170     xmlFree(ctx);
       
   171 }
       
   172 
       
   173 /**
       
   174  * xmlSecBase64CtxInitialize:
       
   175  * @ctx:		the pointer to #xmlSecBase64Ctx structure,
       
   176  * @encode:		the encode/decode flag (1 - encode, 0 - decode) 
       
   177  * @columns: 		the max line length.
       
   178  *
       
   179  * Initializes new base64 context.
       
   180  *
       
   181  * Returns 0 on success and a negative value otherwise.
       
   182  */
       
   183 EXPORT_C
       
   184 int 
       
   185 xmlSecBase64CtxInitialize(xmlSecBase64CtxPtr ctx, int encode, int columns) {    
       
   186     xmlSecAssert2(ctx != NULL, -1);
       
   187 
       
   188     memset(ctx, 0, sizeof(xmlSecBase64Ctx));
       
   189 
       
   190     ctx->encode     = encode;
       
   191     ctx->columns    = columns;
       
   192     return(0);
       
   193 }
       
   194 
       
   195 /**
       
   196  * xmlSecBase64CtxFinalize:
       
   197  * @ctx:		the pointer to #xmlSecBase64Ctx structure,
       
   198  *
       
   199  * Frees all the resources allocated by @ctx.
       
   200  */
       
   201 EXPORT_C
       
   202 void 
       
   203 xmlSecBase64CtxFinalize(xmlSecBase64CtxPtr ctx) {    
       
   204     xmlSecAssert(ctx != NULL);
       
   205 
       
   206     memset(ctx, 0, sizeof(xmlSecBase64Ctx)); 
       
   207 }	
       
   208 
       
   209 /**
       
   210  * xmlSecBase64CtxUpdate:
       
   211  * @ctx: 		the pointer to #xmlSecBase64Ctx structure
       
   212  * @in:			the input buffer
       
   213  * @inSize: 		the input buffer size
       
   214  * @out: 		the output buffer
       
   215  * @outSize: 		the output buffer size
       
   216  *
       
   217  * Encodes or decodes the next piece of data from input buffer.
       
   218  * 
       
   219  * Returns the number of bytes written to output buffer or 
       
   220  * -1 if an error occurs.
       
   221  */
       
   222 EXPORT_C
       
   223 int
       
   224 xmlSecBase64CtxUpdate(xmlSecBase64CtxPtr ctx,
       
   225 		     const xmlSecByte *in, xmlSecSize inSize, 
       
   226 		     xmlSecByte *out, xmlSecSize outSize) {
       
   227     xmlSecSize inResSize = 0, outResSize = 0;
       
   228     int ret;
       
   229     
       
   230     xmlSecAssert2(ctx != NULL, -1);
       
   231     xmlSecAssert2(in != NULL, -1);
       
   232     xmlSecAssert2(out != NULL, -1);
       
   233 
       
   234     if(ctx->encode != 0) {
       
   235 	ret = xmlSecBase64CtxEncode(ctx, in, inSize, &inResSize, 
       
   236 				    out, outSize, &outResSize);
       
   237 	if((ret < 0) || (inResSize != inSize)) {
       
   238 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   239 			NULL,
       
   240 			"xmlSecBase64CtxEncode",
       
   241 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   242 			XMLSEC_ERRORS_NO_MESSAGE);
       
   243     	    return(-1);
       
   244 	}
       
   245     } else {
       
   246 	ret = xmlSecBase64CtxDecode(ctx, in, inSize, &inResSize, 
       
   247 				    out, outSize, &outResSize);
       
   248 	if((ret < 0) || (inResSize != inSize)) {
       
   249 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   250 			NULL,
       
   251 			"xmlSecBase64CtxDecode",
       
   252 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   253 			XMLSEC_ERRORS_NO_MESSAGE);
       
   254     	    return(-1);
       
   255 	}
       
   256     }
       
   257 
       
   258     return(outResSize);
       
   259 }
       
   260 
       
   261 /**
       
   262  * xmlSecBase64CtxFinal:
       
   263  * @ctx: 		the pointer to #xmlSecBase64Ctx structure
       
   264  * @out: 		the output buffer
       
   265  * @outSize: 		the output buffer size
       
   266  *
       
   267  * Encodes or decodes the last piece of data stored in the context
       
   268  * and finalizes the result.
       
   269  *
       
   270  * Returns the number of bytes written to output buffer or 
       
   271  * -1 if an error occurs.
       
   272  */
       
   273 EXPORT_C
       
   274 int
       
   275 xmlSecBase64CtxFinal(xmlSecBase64CtxPtr ctx, 
       
   276 		    xmlSecByte *out, xmlSecSize outSize) {
       
   277     xmlSecSize outResSize = 0;
       
   278     int ret;
       
   279         
       
   280     xmlSecAssert2(ctx != NULL, -1);
       
   281     xmlSecAssert2(out != NULL, -1);    
       
   282     xmlSecAssert2(outSize > 0, -1);    
       
   283 
       
   284     if(ctx->encode != 0) {    
       
   285 	ret = xmlSecBase64CtxEncodeFinal(ctx, out, outSize, &outResSize);
       
   286         if(ret < 0) {
       
   287 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   288 			NULL,
       
   289 			"xmlSecBase64CtxEncodeFinal",
       
   290 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   291 			"outSize=%d", outSize);
       
   292 	    return(-1);
       
   293 	}
       
   294     } else {
       
   295 	if(!xmlSecBase64CtxDecodeIsFinished(ctx)) {
       
   296 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   297 			NULL,
       
   298 			"xmlSecBase64CtxIsFinished",
       
   299 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   300 			XMLSEC_ERRORS_NO_MESSAGE);
       
   301     	    return(-1);
       
   302 	}	
       
   303     }
       
   304     
       
   305     /* add \0 */
       
   306     if((outResSize + 1) < outSize) {
       
   307 	out[outResSize] = '\0';
       
   308     }
       
   309     return(outResSize);
       
   310 }
       
   311 
       
   312 static xmlSecBase64Status
       
   313 xmlSecBase64CtxEncodeByte(xmlSecBase64CtxPtr ctx, xmlSecByte inByte, xmlSecByte* outByte) {
       
   314     xmlSecAssert2(ctx != NULL, xmlSecBase64StatusFailed);
       
   315     xmlSecAssert2(outByte != NULL, xmlSecBase64StatusFailed);
       
   316 
       
   317     if((ctx->columns > 0) && (ctx->linePos >= ctx->columns)) {
       
   318         (*outByte) = '\n';
       
   319         ctx->linePos = 0;
       
   320         return(xmlSecBase64StatusConsumeAndRepeat);
       
   321     } else if(ctx->inPos == 0) {
       
   322         /* we just started new block */
       
   323 	(*outByte) = base64[xmlSecBase64Encode1(inByte)];
       
   324         ctx->inByte = inByte;
       
   325         ++ctx->linePos;
       
   326         ++ctx->inPos;
       
   327         return(xmlSecBase64StatusConsumeAndNext);
       
   328     } else if(ctx->inPos == 1) {
       
   329 	(*outByte) = base64[xmlSecBase64Encode2(ctx->inByte, inByte)];
       
   330         ctx->inByte = inByte;
       
   331         ++ctx->linePos;
       
   332         ++ctx->inPos;
       
   333         return(xmlSecBase64StatusConsumeAndNext);
       
   334     } else if(ctx->inPos == 2) {
       
   335 	(*outByte) = base64[xmlSecBase64Encode3(ctx->inByte, inByte)];
       
   336         ctx->inByte = inByte;
       
   337         ++ctx->linePos;
       
   338         ++ctx->inPos;
       
   339         return(xmlSecBase64StatusConsumeAndRepeat);
       
   340     } else if(ctx->inPos == 3) {
       
   341 	(*outByte) = base64[xmlSecBase64Encode4(ctx->inByte)];
       
   342         ++ctx->linePos;
       
   343         ctx->inByte = 0;
       
   344         ctx->inPos  = 0;
       
   345         return(xmlSecBase64StatusConsumeAndNext);
       
   346     }
       
   347 
       
   348     xmlSecError(XMLSEC_ERRORS_HERE, 
       
   349 		NULL,
       
   350 		NULL,
       
   351 		XMLSEC_ERRORS_R_INVALID_DATA,
       
   352 		"ctx->inPos=%d", ctx->inPos);
       
   353     return(xmlSecBase64StatusFailed);
       
   354 }
       
   355 
       
   356 static xmlSecBase64Status
       
   357 xmlSecBase64CtxEncodeByteFinal(xmlSecBase64CtxPtr ctx, xmlSecByte* outByte) {
       
   358     xmlSecAssert2(ctx != NULL, xmlSecBase64StatusFailed);
       
   359     xmlSecAssert2(outByte != NULL, xmlSecBase64StatusFailed);
       
   360 
       
   361     if(ctx->inPos == 0) {
       
   362         return(xmlSecBase64StatusDone);
       
   363     } else if((ctx->columns > 0) && (ctx->linePos >= ctx->columns)) {
       
   364         (*outByte) = '\n';
       
   365         ctx->linePos = 0;
       
   366         return(xmlSecBase64StatusConsumeAndRepeat);
       
   367     } else if(ctx->finished == 0) {
       
   368         ctx->finished = 1;
       
   369         return(xmlSecBase64CtxEncodeByte(ctx, 0, outByte));
       
   370     } else if(ctx->inPos < 3) {
       
   371         (*outByte) = '=';
       
   372         ++ctx->inPos;
       
   373         ++ctx->linePos;
       
   374         return(xmlSecBase64StatusConsumeAndRepeat);
       
   375     } else if(ctx->inPos == 3) {
       
   376         (*outByte) = '=';
       
   377         ++ctx->linePos;
       
   378         ctx->inPos = 0;
       
   379         return(xmlSecBase64StatusConsumeAndRepeat);
       
   380     }
       
   381 
       
   382     xmlSecError(XMLSEC_ERRORS_HERE, 
       
   383 		NULL,
       
   384 		NULL,
       
   385 		XMLSEC_ERRORS_R_INVALID_DATA,
       
   386 		"ctx->inPos=%d", ctx->inPos);
       
   387     return(xmlSecBase64StatusFailed);
       
   388 }
       
   389 
       
   390 static xmlSecBase64Status
       
   391 xmlSecBase64CtxDecodeByte(xmlSecBase64CtxPtr ctx, xmlSecByte inByte, xmlSecByte* outByte) {
       
   392     xmlSecAssert2(ctx != NULL, xmlSecBase64StatusFailed);
       
   393     xmlSecAssert2(outByte != NULL, xmlSecBase64StatusFailed);    
       
   394 
       
   395     if((ctx->finished != 0) && (ctx->inPos == 0)) {
       
   396         return(xmlSecBase64StatusDone);
       
   397     } if(inByte == '=') {
       
   398         ctx->finished = 1;
       
   399         if(ctx->inPos < 2) {
       
   400 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   401 			NULL,
       
   402 			NULL,
       
   403 			XMLSEC_ERRORS_R_INVALID_DATA,
       
   404 			"ctx->inPos=%d", ctx->inPos);
       
   405             return(xmlSecBase64StatusFailed);
       
   406         } else if(ctx->inPos == 2) {
       
   407             ++ctx->inPos;
       
   408             return(xmlSecBase64StatusNext);            
       
   409         } else if(ctx->inPos == 3) {
       
   410             ctx->inPos = 0;
       
   411             return(xmlSecBase64StatusNext);
       
   412         } else {
       
   413 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   414 			NULL,
       
   415 			NULL,
       
   416 			XMLSEC_ERRORS_R_INVALID_DATA,
       
   417 			"ctx->inPos=%d", ctx->inPos);
       
   418             return(xmlSecBase64StatusFailed);
       
   419         }
       
   420     } else if(xmlSecIsBase64Space(inByte)) {
       
   421         return(xmlSecBase64StatusNext);
       
   422     } else if(!xmlSecIsBase64Char(inByte) || (ctx->finished != 0)) {
       
   423 	xmlSecError(XMLSEC_ERRORS_HERE, 
       
   424 		    NULL,
       
   425 		    NULL,
       
   426 		    XMLSEC_ERRORS_R_INVALID_DATA,
       
   427 		    "inByte=0x%02x", inByte);
       
   428         return(xmlSecBase64StatusFailed);
       
   429     }
       
   430 
       
   431     /* convert from character to position in base64 array */
       
   432     if((inByte >= 'A') && (inByte <= 'Z')) {
       
   433 	inByte = (inByte - 'A');
       
   434     } else if((inByte >= 'a') && (inByte <= 'z')) {
       
   435 	inByte = 26 + (inByte - 'a');
       
   436     } else if((inByte >= '0') && (inByte <= '9')) {
       
   437 	inByte = 52 + (inByte - '0'); 
       
   438     } else if(inByte == '+') {
       
   439     	inByte = 62;
       
   440     } else if(inByte == '/') {
       
   441 	inByte = 63;
       
   442     }
       
   443         
       
   444     if(ctx->inPos == 0) {
       
   445         ctx->inByte = inByte;
       
   446         ++ctx->inPos;
       
   447         return(xmlSecBase64StatusNext);
       
   448     } else if(ctx->inPos == 1) {
       
   449         (*outByte) = xmlSecBase64Decode1(ctx->inByte, inByte);
       
   450         ctx->inByte = inByte;
       
   451         ++ctx->inPos;
       
   452         return(xmlSecBase64StatusConsumeAndNext);
       
   453     } else if(ctx->inPos == 2) {
       
   454         (*outByte) = xmlSecBase64Decode2(ctx->inByte, inByte);
       
   455         ctx->inByte = inByte;
       
   456         ++ctx->inPos;
       
   457         return(xmlSecBase64StatusConsumeAndNext);
       
   458     } else if(ctx->inPos == 3) {
       
   459         (*outByte) = xmlSecBase64Decode3(ctx->inByte, inByte);
       
   460         ctx->inByte = 0;
       
   461         ctx->inPos = 0;
       
   462         return(xmlSecBase64StatusConsumeAndNext);
       
   463     }
       
   464 
       
   465     xmlSecError(XMLSEC_ERRORS_HERE, 
       
   466 		NULL,
       
   467 		NULL,
       
   468 		XMLSEC_ERRORS_R_INVALID_DATA,
       
   469 		"ctx->inPos=%d", ctx->inPos);
       
   470     return(xmlSecBase64StatusFailed);
       
   471 }
       
   472 
       
   473 
       
   474 static int
       
   475 xmlSecBase64CtxEncode(xmlSecBase64CtxPtr ctx, 
       
   476                      const xmlSecByte* inBuf, xmlSecSize inBufSize, xmlSecSize* inBufResSize,
       
   477                      xmlSecByte* outBuf, xmlSecSize outBufSize, xmlSecSize* outBufResSize) {
       
   478     xmlSecBase64Status status = xmlSecBase64StatusNext;
       
   479     xmlSecSize inPos, outPos;
       
   480     
       
   481     xmlSecAssert2(ctx != NULL, -1);
       
   482     xmlSecAssert2(inBuf != NULL, -1);
       
   483     xmlSecAssert2(inBufResSize != NULL, -1);
       
   484     xmlSecAssert2(outBuf != NULL, -1);
       
   485     xmlSecAssert2(outBufResSize != NULL, -1);
       
   486 
       
   487     /* encode */
       
   488     for(inPos = outPos = 0; (inPos < inBufSize) && (outPos < outBufSize); ) {
       
   489         status = xmlSecBase64CtxEncodeByte(ctx, inBuf[inPos], &(outBuf[outPos]));
       
   490         switch(status) {
       
   491             case xmlSecBase64StatusConsumeAndNext:
       
   492                 ++inPos;
       
   493                 ++outPos;
       
   494                 break;
       
   495             case xmlSecBase64StatusConsumeAndRepeat:
       
   496                 ++outPos;
       
   497                 break;
       
   498             case xmlSecBase64StatusNext:
       
   499             case xmlSecBase64StatusDone:
       
   500             case xmlSecBase64StatusFailed:
       
   501 		xmlSecError(XMLSEC_ERRORS_HERE, 
       
   502 			    NULL,
       
   503 			    "xmlSecBase64CtxEncodeByte",
       
   504 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   505 			    "status=%d", status);
       
   506                 return(-1);
       
   507         }
       
   508     }
       
   509 
       
   510     (*inBufResSize)  = inPos;
       
   511     (*outBufResSize) = outPos;
       
   512 
       
   513     return(0);
       
   514 }
       
   515 
       
   516 static int
       
   517 xmlSecBase64CtxEncodeFinal(xmlSecBase64CtxPtr ctx, 
       
   518                      xmlSecByte* outBuf, xmlSecSize outBufSize, xmlSecSize* outBufResSize) {
       
   519     xmlSecBase64Status status = xmlSecBase64StatusNext;
       
   520     xmlSecSize outPos;
       
   521     
       
   522     xmlSecAssert2(ctx != NULL, -1);
       
   523     xmlSecAssert2(outBuf != NULL, -1);
       
   524     xmlSecAssert2(outBufResSize != NULL, -1);
       
   525 
       
   526     /* encode final bytes */
       
   527     for(outPos = 0; (outPos < outBufSize) && (status != xmlSecBase64StatusDone); ) {
       
   528         status = xmlSecBase64CtxEncodeByteFinal(ctx, &(outBuf[outPos]));
       
   529         switch(status) {
       
   530             case xmlSecBase64StatusConsumeAndNext:
       
   531             case xmlSecBase64StatusConsumeAndRepeat:
       
   532                 ++outPos;
       
   533                 break;
       
   534             case xmlSecBase64StatusDone:
       
   535                 break;
       
   536             case xmlSecBase64StatusNext:
       
   537             case xmlSecBase64StatusFailed:
       
   538 		xmlSecError(XMLSEC_ERRORS_HERE, 
       
   539 			    NULL,
       
   540 			    "xmlSecBase64CtxEncodeByteFinal",
       
   541 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   542 			    "status=%d", status);
       
   543                 return(-1);
       
   544         }
       
   545     }
       
   546 
       
   547     if(status != xmlSecBase64StatusDone) {
       
   548 	xmlSecError(XMLSEC_ERRORS_HERE, 
       
   549 		    NULL,
       
   550 		    NULL,
       
   551 		    XMLSEC_ERRORS_R_INVALID_SIZE,
       
   552 		    "outBufSize=%d", outBufSize);
       
   553         return(-1);
       
   554     }
       
   555     if(outPos < outBufSize) {
       
   556         outBuf[outPos] = '\0'; /* just in case */
       
   557     }
       
   558 
       
   559     (*outBufResSize) = outPos;
       
   560     return(0);
       
   561 }
       
   562 
       
   563 
       
   564 static int
       
   565 xmlSecBase64CtxDecode(xmlSecBase64CtxPtr ctx, 
       
   566                      const xmlSecByte* inBuf, xmlSecSize inBufSize, xmlSecSize* inBufResSize,
       
   567                      xmlSecByte* outBuf, xmlSecSize outBufSize, xmlSecSize* outBufResSize) {
       
   568     xmlSecBase64Status status = xmlSecBase64StatusNext;
       
   569     xmlSecSize inPos, outPos;
       
   570     
       
   571     xmlSecAssert2(ctx != NULL, -1);
       
   572     xmlSecAssert2(inBuf != NULL, -1);
       
   573     xmlSecAssert2(inBufResSize != NULL, -1);
       
   574     xmlSecAssert2(outBuf != NULL, -1);
       
   575     xmlSecAssert2(outBufResSize != NULL, -1);
       
   576 
       
   577     /* decode */
       
   578     for(inPos = outPos = 0; (inPos < inBufSize) && (outPos < outBufSize) && (status != xmlSecBase64StatusDone); ) {
       
   579         status = xmlSecBase64CtxDecodeByte(ctx, inBuf[inPos], &(outBuf[outPos]));
       
   580         switch(status) {
       
   581             case xmlSecBase64StatusConsumeAndNext:
       
   582                 ++inPos;
       
   583                 ++outPos;
       
   584                 break;
       
   585             case xmlSecBase64StatusConsumeAndRepeat:
       
   586                 ++outPos;
       
   587                 break;
       
   588             case xmlSecBase64StatusNext:
       
   589                 ++inPos;
       
   590                 break;
       
   591             case xmlSecBase64StatusDone:
       
   592                 break;
       
   593             case xmlSecBase64StatusFailed:
       
   594 		xmlSecError(XMLSEC_ERRORS_HERE, 
       
   595 			    NULL,
       
   596 			    "xmlSecBase64CtxDecodeByte",
       
   597 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   598 			    "status=%d", status);
       
   599                 return(-1);
       
   600         }
       
   601     }
       
   602 
       
   603     /* skip spaces at the end */
       
   604     while((inPos < inBufSize) && xmlSecIsBase64Space(inBuf[inPos])) {
       
   605         ++inPos;
       
   606     }
       
   607 
       
   608     (*inBufResSize)  = inPos;
       
   609     (*outBufResSize) = outPos;
       
   610 
       
   611     return(0);
       
   612 }
       
   613 
       
   614 static int
       
   615 xmlSecBase64CtxDecodeIsFinished(xmlSecBase64CtxPtr ctx) {
       
   616     xmlSecAssert2(ctx != NULL, -1);
       
   617 
       
   618     return((ctx->inPos == 0) ? 1 : 0);
       
   619 }
       
   620 
       
   621 /**
       
   622  * xmlSecBase64Encode:
       
   623  * @buf: 		the input buffer.
       
   624  * @len: 		the input buffer size.
       
   625  * @columns: 		the output max line length (if 0 then no line breaks
       
   626  *          		would be inserted)
       
   627  *
       
   628  * Encodes the data from input buffer and allocates the string for the result.
       
   629  * The caller is responsible for freeing returned buffer using
       
   630  * xmlFree() function.
       
   631  *
       
   632  * Returns newly allocated string with base64 encoded data 
       
   633  * or NULL if an error occurs.
       
   634  */
       
   635 EXPORT_C
       
   636 xmlChar*
       
   637 xmlSecBase64Encode(const xmlSecByte *buf, xmlSecSize len, int columns) {
       
   638     xmlSecBase64Ctx ctx;
       
   639     xmlChar *ptr;
       
   640     xmlSecSize size;    
       
   641     int size_update, size_final;
       
   642     int ret;
       
   643 
       
   644     xmlSecAssert2(buf != NULL, NULL);
       
   645 
       
   646     ret = xmlSecBase64CtxInitialize(&ctx, 1, columns);
       
   647     if(ret < 0) {
       
   648 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   649 		    NULL,
       
   650 		    "xmlSecBase64CtxInitialize",
       
   651 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   652 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   653 	return(NULL);
       
   654     }
       
   655     
       
   656     /* create result buffer */
       
   657     size = (4 * len) / 3 + 4;
       
   658     if(columns > 0) {
       
   659 	size += (size / columns) + 4;
       
   660     }
       
   661     ptr = (xmlChar*) xmlMalloc(size);
       
   662     if(ptr == NULL) {
       
   663 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   664 		    NULL,
       
   665 		    NULL,
       
   666 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   667 		    "size=%d", size);
       
   668 	xmlSecBase64CtxFinalize(&ctx);
       
   669 	return(NULL);
       
   670     }
       
   671 
       
   672     ret = xmlSecBase64CtxUpdate(&ctx, buf, len, (xmlSecByte*)ptr, size);
       
   673     if(ret < 0) {
       
   674 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   675 		    NULL,
       
   676 		    "xmlSecBase64CtxUpdate",
       
   677 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   678 		    "len=%d", len);
       
   679 	xmlFree(ptr);
       
   680 	xmlSecBase64CtxFinalize(&ctx);
       
   681 	return(NULL);
       
   682     }
       
   683     size_update = ret;
       
   684 
       
   685     ret = xmlSecBase64CtxFinal(&ctx, ((xmlSecByte*)ptr) + size_update, size - size_update);
       
   686     if(ret < 0) {
       
   687 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   688 		    NULL,
       
   689 		    "xmlSecBase64CtxFinal",
       
   690 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   691 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   692 	xmlFree(ptr);
       
   693 	xmlSecBase64CtxFinalize(&ctx);
       
   694 	return(NULL);
       
   695     }
       
   696     size_final = ret;
       
   697     ptr[size_update + size_final] = '\0';
       
   698     
       
   699     xmlSecBase64CtxFinalize(&ctx);
       
   700     return(ptr);
       
   701 }
       
   702 
       
   703 /**
       
   704  * xmlSecBase64Decode:
       
   705  * @str: 		the input buffer with base64 encoded string
       
   706  * @buf: 		the output buffer
       
   707  * @len: 		the output buffer size
       
   708  *
       
   709  * Decodes input base64 encoded string and puts result into
       
   710  * the output buffer.
       
   711  *
       
   712  * Returns the number of bytes written to the output buffer or 
       
   713  * a negative value if an error occurs 
       
   714  */
       
   715 EXPORT_C
       
   716 int
       
   717 xmlSecBase64Decode(const xmlChar* str, xmlSecByte *buf, xmlSecSize len) {
       
   718     xmlSecBase64Ctx ctx;
       
   719     int size_update;
       
   720     int size_final;
       
   721     int ret;
       
   722 
       
   723     xmlSecAssert2(str != NULL, -1);
       
   724     xmlSecAssert2(buf != NULL, -1);
       
   725 
       
   726     ret = xmlSecBase64CtxInitialize(&ctx, 0, 0);
       
   727     if(ret < 0) {
       
   728 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   729 		    NULL,
       
   730 		    "xmlSecBase64CtxInitialize",
       
   731 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   732 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   733 	return(-1);
       
   734     }
       
   735     
       
   736     ret = xmlSecBase64CtxUpdate(&ctx, (const xmlSecByte*)str, xmlStrlen(str), buf, len);
       
   737     if(ret < 0) {
       
   738 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   739 		    NULL,
       
   740 		    "xmlSecBase64CtxUpdate",
       
   741 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   742 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   743 	xmlSecBase64CtxFinalize(&ctx);
       
   744 	return(-1);
       
   745     }
       
   746 
       
   747     size_update = ret;
       
   748     ret = xmlSecBase64CtxFinal(&ctx, buf + size_update, len - size_update);
       
   749     if(ret < 0) {
       
   750 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   751 		    NULL,
       
   752 		    "xmlSecBase64CtxFinal",
       
   753 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   754 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   755 	xmlSecBase64CtxFinalize(&ctx);
       
   756 	return(-1);
       
   757     }
       
   758     size_final = ret;    
       
   759 
       
   760     xmlSecBase64CtxFinalize(&ctx);
       
   761     return(size_update + size_final);
       
   762 }
       
   763 
       
   764 /**************************************************************
       
   765  *
       
   766  * Base64 Transform
       
   767  *
       
   768  * xmlSecBase64Ctx is located after xmlSecTransform
       
   769  * 
       
   770  **************************************************************/
       
   771 #define xmlSecBase64Size \
       
   772 	(sizeof(xmlSecTransform) + sizeof(xmlSecBase64Ctx))
       
   773 #define xmlSecBase64GetCtx(transform) \
       
   774     ((xmlSecTransformCheckSize((transform), xmlSecBase64Size)) ? \
       
   775 	(xmlSecBase64CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
       
   776 	(xmlSecBase64CtxPtr)NULL)
       
   777 
       
   778 static int		xmlSecBase64Initialize		(xmlSecTransformPtr transform);
       
   779 static void		xmlSecBase64Finalize		(xmlSecTransformPtr transform);
       
   780 static int 		xmlSecBase64Execute		(xmlSecTransformPtr transform, 
       
   781 							 int last, 
       
   782 							 xmlSecTransformCtxPtr transformCtx);
       
   783 
       
   784 static xmlSecTransformKlass xmlSecBase64Klass = {
       
   785     /* klass/object sizes */
       
   786     sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
       
   787     xmlSecBase64Size,				/* xmlSecSize objSize */
       
   788 
       
   789     xmlSecNameBase64,				/* const xmlChar* name; */
       
   790     xmlSecHrefBase64,				/* const xmlChar* href; */
       
   791     xmlSecTransformUsageDSigTransform,		/* xmlSecAlgorithmUsage usage; */
       
   792 
       
   793     xmlSecBase64Initialize, 			/* xmlSecTransformInitializeMethod initialize; */
       
   794     xmlSecBase64Finalize,			/* xmlSecTransformFinalizeMethod finalize; */
       
   795     NULL,					/* xmlSecTransformNodeReadMethod readNode; */
       
   796     NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
       
   797     NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
       
   798     NULL,					/* xmlSecTransformSetKeyMethod setKey; */
       
   799     NULL,					/* xmlSecTransformValidateMethod validate; */
       
   800     xmlSecTransformDefaultGetDataType,		/* xmlSecTransformGetDataTypeMethod getDataType; */
       
   801     xmlSecTransformDefaultPushBin,		/* xmlSecTransformPushBinMethod pushBin; */
       
   802     xmlSecTransformDefaultPopBin,		/* xmlSecTransformPopBinMethod popBin; */
       
   803     NULL,					/* xmlSecTransformPushXmlMethod pushXml; */
       
   804     NULL,					/* xmlSecTransformPopXmlMethod popXml; */
       
   805     xmlSecBase64Execute,			/* xmlSecTransformExecuteMethod execute; */
       
   806 
       
   807     NULL,					/* void* reserved0; */
       
   808     NULL,					/* void* reserved1; */
       
   809 };
       
   810 
       
   811 /**
       
   812  * xmlSecTransformBase64GetKlass:
       
   813  *
       
   814  * The Base64 transform klass (http://www.w3.org/TR/xmldsig-core/#sec-Base-64).
       
   815  * The normative specification for base64 decoding transforms is RFC 2045
       
   816  * (http://www.ietf.org/rfc/rfc2045.txt). The base64 Transform element has 
       
   817  * no content. The input is decoded by the algorithms. This transform is 
       
   818  * useful if an application needs to sign the raw data associated with 
       
   819  * the encoded content of an element.
       
   820  *
       
   821  * Returns base64 transform id.
       
   822  */
       
   823 EXPORT_C
       
   824 xmlSecTransformId 
       
   825 xmlSecTransformBase64GetKlass(void) {
       
   826     return(&xmlSecBase64Klass);
       
   827 }
       
   828 
       
   829 /**
       
   830  * xmlSecTransformBase64SetLineSize:
       
   831  * @transform: 		the pointer to BASE64 encode transform.
       
   832  * @lineSize: 		the new max line size.
       
   833  *
       
   834  * Sets the max line size to @lineSize.
       
   835  */
       
   836 EXPORT_C
       
   837 void
       
   838 xmlSecTransformBase64SetLineSize(xmlSecTransformPtr transform, xmlSecSize lineSize) {
       
   839     xmlSecBase64CtxPtr ctx;
       
   840     
       
   841     xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformBase64Id));
       
   842     
       
   843     ctx = xmlSecBase64GetCtx(transform);
       
   844     xmlSecAssert(ctx != NULL);
       
   845     
       
   846     ctx->columns = lineSize;    
       
   847 }
       
   848 
       
   849 static int
       
   850 xmlSecBase64Initialize(xmlSecTransformPtr transform) {
       
   851     xmlSecBase64CtxPtr ctx;
       
   852     int ret;
       
   853     
       
   854     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformBase64Id), -1);
       
   855 
       
   856     ctx = xmlSecBase64GetCtx(transform);
       
   857     xmlSecAssert2(ctx != NULL, -1);
       
   858 
       
   859     transform->operation = xmlSecTransformOperationDecode;
       
   860     ret = xmlSecBase64CtxInitialize(ctx, 0, XMLSEC_BASE64_LINESIZE);
       
   861     if(ret < 0) {
       
   862 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   863 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   864 		    "xmlSecBase64CtxInitialize",
       
   865 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   866 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   867 	return(-1);
       
   868     }
       
   869     
       
   870     return(0);
       
   871 }
       
   872 
       
   873 static void
       
   874 xmlSecBase64Finalize(xmlSecTransformPtr transform) {
       
   875     xmlSecBase64CtxPtr ctx;
       
   876     
       
   877     xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformBase64Id));
       
   878 
       
   879     ctx = xmlSecBase64GetCtx(transform);
       
   880     xmlSecAssert(ctx != NULL);
       
   881     
       
   882     xmlSecBase64CtxFinalize(ctx);
       
   883 }
       
   884 
       
   885 static int 
       
   886 xmlSecBase64Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
       
   887     xmlSecBase64CtxPtr ctx;
       
   888     xmlSecBufferPtr in, out;
       
   889     xmlSecSize inSize, outSize, outLen;
       
   890     int ret;
       
   891 
       
   892     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformBase64Id), -1);
       
   893     xmlSecAssert2((transform->operation == xmlSecTransformOperationEncode) || (transform->operation == xmlSecTransformOperationDecode), -1);
       
   894     xmlSecAssert2(transformCtx != NULL, -1);
       
   895     
       
   896     ctx = xmlSecBase64GetCtx(transform);
       
   897     xmlSecAssert2(ctx != NULL, -1);
       
   898     
       
   899     in = &(transform->inBuf);
       
   900     out = &(transform->outBuf);
       
   901 
       
   902     if(transform->status == xmlSecTransformStatusNone) {
       
   903 	ctx->encode = (transform->operation == xmlSecTransformOperationEncode) ? 1 : 0;
       
   904 	transform->status = xmlSecTransformStatusWorking;
       
   905     }
       
   906 
       
   907     switch(transform->status) {
       
   908 	case xmlSecTransformStatusWorking:
       
   909 	    inSize = xmlSecBufferGetSize(in);
       
   910 	    outSize = xmlSecBufferGetSize(out);
       
   911 	    if(inSize > 0) {
       
   912 		if(ctx->encode != 0) {
       
   913 		    outLen = 4 * inSize / 3 + 8;
       
   914 		    if(ctx->columns > 0) {
       
   915 			outLen += inSize / ctx->columns + 4;
       
   916 		    }
       
   917 		} else {
       
   918 		    outLen = 3 * inSize / 4 + 8;
       
   919 		}
       
   920 		ret = xmlSecBufferSetMaxSize(out, outSize + outLen);
       
   921 		if(ret < 0) {
       
   922 		    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   923 				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   924 				"xmlSecBufferSetMaxSize",
       
   925 				XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   926 				"size=%d", outSize + outLen);
       
   927 		    return(-1);
       
   928 		}
       
   929 
       
   930 		/* encode/decode the next chunk */
       
   931 		ret = xmlSecBase64CtxUpdate(ctx, xmlSecBufferGetData(in), inSize,
       
   932 					    xmlSecBufferGetData(out) + outSize, 
       
   933 					    outLen);
       
   934 		if(ret < 0) {
       
   935 		    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   936 				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   937 				"xmlSecBase64CtxUpdate",
       
   938 				XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   939 				XMLSEC_ERRORS_NO_MESSAGE);
       
   940 		    return(-1);
       
   941 		}
       
   942 		outLen = ret;
       
   943 		
       
   944 		/* set correct size */
       
   945 		ret = xmlSecBufferSetSize(out, outSize + outLen);
       
   946 		if(ret < 0) {
       
   947 		    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   948 				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   949 				"xmlSecBufferSetSize",
       
   950 				XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   951 				"size=%d", outSize + outLen);
       
   952 		    return(-1);
       
   953 		}
       
   954 		
       
   955 		/* remove chunk from input */
       
   956 		ret = xmlSecBufferRemoveHead(in, inSize);
       
   957 		if(ret < 0) {
       
   958 		    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   959 				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   960 				"xmlSecBufferRemoveHead",
       
   961 				XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   962 				"size=%d", inSize);
       
   963 		    return(-1);
       
   964 		}
       
   965 	    }
       
   966 	    
       
   967 	    if(last) {
       
   968 	        outSize = xmlSecBufferGetSize(out);
       
   969 
       
   970 		ret = xmlSecBufferSetMaxSize(out, outSize + 16);
       
   971 		if(ret < 0) {
       
   972 		    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   973 				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   974 				"xmlSecBufferSetMaxSize",
       
   975 				XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   976 				"size=%d", outSize + 16);
       
   977 		    return(-1);
       
   978 		}
       
   979 	
       
   980 		/* add from ctx buffer */
       
   981 		ret = xmlSecBase64CtxFinal(ctx, xmlSecBufferGetData(out) + outSize, 16);
       
   982 		if(ret < 0) {
       
   983 		    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   984 				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   985 				"xmlSecBase64CtxFinal",
       
   986 				XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   987 				XMLSEC_ERRORS_NO_MESSAGE);
       
   988 		    return(-1);
       
   989 		}
       
   990 		outLen = ret;
       
   991 		
       
   992 		/* set correct size */
       
   993 		ret = xmlSecBufferSetSize(out, outSize + outLen);
       
   994 		if(ret < 0) {
       
   995 		    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   996 				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   997 				"xmlSecBufferSetSize",
       
   998 				XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   999 				"size=%d", outSize + outLen);
       
  1000 		    return(-1);
       
  1001 		}
       
  1002 		transform->status = xmlSecTransformStatusFinished;
       
  1003 	    }
       
  1004 	    break;
       
  1005 	case xmlSecTransformStatusFinished:
       
  1006 	    /* the only way we can get here is if there is no input */
       
  1007 	    xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
       
  1008 	    break;
       
  1009 	default:
       
  1010 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
  1011 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1012 			NULL,
       
  1013 			XMLSEC_ERRORS_R_INVALID_STATUS,
       
  1014 			"status=%d", transform->status);
       
  1015 	    return(-1);
       
  1016     }
       
  1017     return(0);
       
  1018 }
       
  1019 
       
  1020