Git init
[external/xmlsec1.git] / src / bn.c
1 /** 
2  * XML Security Library (http://www.aleksey.com/xmlsec).
3  *
4  * Big Numbers.
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  * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
11  */
12 #include "globals.h"
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17  
18 #include <libxml/tree.h>
19
20 #include <xmlsec/xmlsec.h>
21 #include <xmlsec/xmltree.h>
22 #include <xmlsec/base64.h>
23 #include <xmlsec/bn.h>
24 #include <xmlsec/errors.h>
25
26 /* table for converting hex digits back to bytes */
27 static const int xmlSecBnLookupTable[] =
28 {
29     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
33     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
37     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
38     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
39     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
40     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
41     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
42     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
43     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
44     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
45 };
46
47 static const char xmlSecBnRevLookupTable[] = 
48
49     '0', '1', '2', '3', '4', '5', '6', '7', 
50     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
51 };
52
53 /*****************************************************************************
54  *
55  * xmlSecBn
56  *
57  ****************************************************************************/
58 /**
59  * xmlSecBnCreate:
60  * @size:       the initial allocated BN size.
61  *
62  * Creates a new BN object. Caller is responsible for destroying it
63  * by calling @xmlSecBnDestroy function.
64  *
65  * Returns: the newly BN or a NULL if an error occurs.
66  */
67 xmlSecBnPtr 
68 xmlSecBnCreate(xmlSecSize size) {
69     return(xmlSecBufferCreate(size));
70 }
71
72 /**
73  * xmlSecBnDestroy:
74  * @bn:         the pointer to BN.
75  *
76  * Destroys @bn object created with @xmlSecBnCreate function.
77  */
78 void 
79 xmlSecBnDestroy(xmlSecBnPtr bn) {
80     xmlSecBufferDestroy(bn);
81 }
82
83 /**
84  * xmlSecBnInitialize:
85  * @bn:         the pointer to BN.
86  * @size:       the initial allocated BN size.
87  *
88  * Initializes a BN object. Caller is responsible for destroying it
89  * by calling @xmlSecBnFinalize function.
90  *
91  * Returns: 0 on success or a negative value if an error occurs.
92  */
93 int 
94 xmlSecBnInitialize(xmlSecBnPtr bn, xmlSecSize size) {
95     return(xmlSecBufferInitialize(bn, size));
96 }
97
98 /**
99  * xmlSecBnFinalize:
100  * @bn:         the pointer to BN.
101  *
102  * Destroys @bn object created with @xmlSecBnInitialize function.
103  */
104 void 
105 xmlSecBnFinalize(xmlSecBnPtr bn) {
106     xmlSecBufferFinalize(bn);
107 }
108
109 /**
110  * xmlSecBnGetData:
111  * @bn:         the pointer to BN.
112  *
113  * Gets pointer to the binary @bn representation.
114  * 
115  * Returns: pointer to binary BN data or NULL if an error occurs.
116  */
117 xmlSecByte* 
118 xmlSecBnGetData(xmlSecBnPtr bn) {
119     return(xmlSecBufferGetData(bn));
120 }
121
122 /**
123  * xmlSecBnSetData:
124  * @bn:         the pointer to BN.
125  * @data:       the pointer to new BN binary data.
126  * @size:       the size of new BN data.
127  *
128  * Sets the value of @bn to @data.
129  *
130  * Returns: 0 on success or a negative value if an error occurs.
131  */
132 int 
133 xmlSecBnSetData(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize size) {
134     return(xmlSecBufferSetData(bn, data, size));
135 }
136
137 /**
138  * xmlSecBnGetSize:
139  * @bn:         the pointer to BN.
140  *
141  * Gets the size of binary data in @bn.
142  *
143  * Returns: the size of binary data.
144  */
145 xmlSecSize 
146 xmlSecBnGetSize(xmlSecBnPtr bn) {
147     return(xmlSecBufferGetSize(bn));
148 }
149
150 /**
151  * xmlSecBnZero:
152  * @bn:         the pointer to BN.
153  *
154  * Sets the value of @bn to zero.
155  */
156 void 
157 xmlSecBnZero(xmlSecBnPtr bn) {
158     xmlSecBufferEmpty(bn);
159 }
160
161 /**
162  * xmlSecBnFromString:
163  * @bn:         the pointer to BN.
164  * @str:        the string with BN.
165  * @base:       the base for @str.
166  *
167  * Reads @bn from string @str assuming it has base @base.
168  *
169  * Returns: 0 on success or a negative value if an error occurs.
170  */
171 int 
172 xmlSecBnFromString(xmlSecBnPtr bn, const xmlChar* str, xmlSecSize base) {
173     xmlSecSize i, len, size;
174     xmlSecByte ch;
175     xmlSecByte* data;
176     int positive;
177     int nn;
178     int ret;
179
180     xmlSecAssert2(bn != NULL, -1);
181     xmlSecAssert2(str != NULL, -1);
182     xmlSecAssert2(base > 1, -1);
183     xmlSecAssert2(base <= sizeof(xmlSecBnRevLookupTable), -1);
184
185     /* trivial case */
186     len = xmlStrlen(str);
187     if(len == 0) {
188         return(0);
189     }
190     
191     /* The result size could not exceed the input string length
192      * because each char fits inside a byte in all cases :)
193      * In truth, it would be likely less than 1/2 input string length
194      * because each byte is represented by 2 chars. If needed, 
195      * buffer size would be increased by Mul/Add functions.
196      * Finally, we can add one byte for 00 or 10 prefix.
197      */
198     ret = xmlSecBufferSetMaxSize(bn, xmlSecBufferGetSize(bn) + len / 2 + 1 + 1);
199     if(ret < 0) {
200         xmlSecError(XMLSEC_ERRORS_HERE,
201                         NULL,
202                         "xmlSecBnRevLookupTable",
203                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
204                         "size=%d", len / 2 + 1);
205         return (-1);
206     }
207
208     /* figure out if it is positive or negative number */
209     positive = 1;
210     i = 0;
211     while(i < len) {
212         ch = str[i++];
213
214         /* skip spaces */
215         if(isspace(ch)) {
216                 continue;
217         } 
218         
219         /* check if it is + or - */
220         if(ch == '+') {
221             positive = 1;
222             break;
223         } else if(ch == '-') {
224             positive = 0;
225             break;
226         }
227
228         /* otherwise, it must be start of the number */
229         nn = xmlSecBnLookupTable[ch];
230         if((nn >= 0) && ((xmlSecSize)nn < base)) {
231             xmlSecAssert2(i > 0, -1);
232
233             /* no sign, positive by default */
234             positive = 1;
235             --i; /* make sure that we will look at this character in next loop */
236             break;
237         } else {
238                 xmlSecError(XMLSEC_ERRORS_HERE,
239                         NULL,
240                         NULL,
241                         XMLSEC_ERRORS_R_INVALID_DATA,
242                         "char=%c;base=%d", 
243                         ch, base);
244                 return (-1);
245         }
246     }
247
248     /* now parse the number itself */
249     while(i < len) {
250         ch = str[i++];
251         if(isspace(ch)) {
252                 continue;
253         }
254
255         xmlSecAssert2(ch <= sizeof(xmlSecBnLookupTable), -1);
256         nn = xmlSecBnLookupTable[ch];
257         if((nn < 0) || ((xmlSecSize)nn > base)) {
258                 xmlSecError(XMLSEC_ERRORS_HERE,
259                         NULL,
260                         NULL,
261                         XMLSEC_ERRORS_R_INVALID_DATA,
262                         "char=%c;base=%d", 
263                         ch, base);
264                 return (-1);
265         }
266
267         ret = xmlSecBnMul(bn, base);
268         if(ret < 0) {
269                 xmlSecError(XMLSEC_ERRORS_HERE,
270                         NULL,
271                         "xmlSecBnMul",
272                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
273                         "base=%d", base);
274                 return (-1);
275         }
276
277         ret = xmlSecBnAdd(bn, nn);
278         if(ret < 0) {
279                 xmlSecError(XMLSEC_ERRORS_HERE,
280                         NULL,
281                         "xmlSecBnAdd",
282                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
283                         "base=%d", base);
284                 return (-1);
285 }       
286     }
287
288     /* check if we need to add 00 prefix, do this for empty bn too */
289     data = xmlSecBufferGetData(bn);
290     size = xmlSecBufferGetSize(bn);
291     if(((size > 0) && (data[0] > 127)) || (size == 0))  {
292         ch = 0;
293         ret = xmlSecBufferPrepend(bn, &ch, 1);
294         if(ret < 0) {
295             xmlSecError(XMLSEC_ERRORS_HERE,
296                 NULL,
297                 "xmlSecBufferPrepend",
298                 XMLSEC_ERRORS_R_XMLSEC_FAILED,
299                 "base=%d", base);
300             return (-1);
301         }
302     }
303
304     /* do 2's compliment and add 1 to represent negative value */
305     if(positive == 0) {
306         data = xmlSecBufferGetData(bn);
307         size = xmlSecBufferGetSize(bn);
308         for(i = 0; i < size; ++i) {
309             data[i] ^= 0xFF;
310         }
311         
312         ret = xmlSecBnAdd(bn, 1);
313         if(ret < 0) {
314             xmlSecError(XMLSEC_ERRORS_HERE,
315                 NULL,
316                 "xmlSecBnAdd",
317                 XMLSEC_ERRORS_R_XMLSEC_FAILED,
318                 "base=%d", base);
319             return (-1);
320         }
321     }
322
323     return(0);
324 }
325
326 /**
327  * xmlSecBnToString:
328  * @bn:         the pointer to BN.
329  * @base:       the base for returned string.
330  *
331  * Writes @bn to string with base @base. Caller is responsible for 
332  * freeing returned string with @xmlFree.
333  *
334  * Returns: the string represenataion if BN or a NULL if an error occurs.
335  */
336 xmlChar* 
337 xmlSecBnToString(xmlSecBnPtr bn, xmlSecSize base) {
338     xmlSecBn bn2;
339     int positive = 1;
340     xmlChar* res;
341     xmlSecSize i, len, size;
342     xmlSecByte* data;
343     int ret;
344     int nn;
345     xmlChar ch;
346
347     xmlSecAssert2(bn != NULL, NULL);
348     xmlSecAssert2(base > 1, NULL);
349     xmlSecAssert2(base <= sizeof(xmlSecBnRevLookupTable), NULL);
350
351
352     /* copy bn */
353     data = xmlSecBufferGetData(bn);
354     size = xmlSecBufferGetSize(bn);
355     ret = xmlSecBnInitialize(&bn2, size);
356     if(ret < 0) {
357         xmlSecError(XMLSEC_ERRORS_HERE,
358             NULL,
359             "xmlSecBnCreate",
360             XMLSEC_ERRORS_R_XMLSEC_FAILED,
361             "size=%d", size);
362         return (NULL);
363     }
364     
365     ret = xmlSecBnSetData(&bn2, data, size);
366     if(ret < 0) {
367         xmlSecError(XMLSEC_ERRORS_HERE,
368             NULL,
369             "xmlSecBnSetData",
370             XMLSEC_ERRORS_R_XMLSEC_FAILED,
371             "size=%d", size);
372         xmlSecBnFinalize(&bn2);
373         return (NULL);
374     }
375
376     /* check if it is a negative number or not */
377     data = xmlSecBufferGetData(&bn2);
378     size = xmlSecBufferGetSize(&bn2);
379     if((size > 0) && (data[0] > 127)) {
380         /* subtract 1 and do 2's compliment */
381         ret = xmlSecBnAdd(&bn2, -1);
382         if(ret < 0) {
383             xmlSecError(XMLSEC_ERRORS_HERE,
384                         NULL,
385                         "xmlSecBnAdd",
386                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
387                         "size=%d", size);
388             xmlSecBnFinalize(&bn2);
389             return (NULL);
390         }
391         for(i = 0; i < size; ++i) {
392             data[i] ^= 0xFF;
393         }
394
395         positive = 0;
396     } else {
397         positive = 1;
398     }
399
400     /* Result string len is
401      *      len = log base (256) * <bn size>
402      * Since the smallest base == 2 then we can get away with 
403      *      len = 8 * <bn size>
404      */
405     len = 8 * size + 1 + 1;
406     res = (xmlChar*)xmlMalloc(len + 1);
407     if(res == NULL) {
408         xmlSecError(XMLSEC_ERRORS_HERE,
409                             NULL,
410                             NULL,
411                             XMLSEC_ERRORS_R_MALLOC_FAILED,
412                             "len=%d", len);
413         xmlSecBnFinalize(&bn2);
414         return (NULL);
415     }
416     memset(res, 0, len + 1);
417
418     for(i = 0; (xmlSecBufferGetSize(&bn2) > 0) && (i < len); i++) {
419         if(xmlSecBnDiv(&bn2, base, &nn) < 0) {
420             xmlSecError(XMLSEC_ERRORS_HERE,
421                         NULL,
422                         "xmlSecBnDiv",
423                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
424                         "base=%d", base);
425             xmlFree(res);
426             xmlSecBnFinalize(&bn2);
427             return (NULL);
428         }
429         xmlSecAssert2((size_t)nn < sizeof(xmlSecBnRevLookupTable), NULL);
430         res[i] = xmlSecBnRevLookupTable[nn];
431     }
432     xmlSecAssert2(i < len, NULL);
433
434     /* we might have '0' at the beggining, remove it but keep one zero */
435     for(len = i; (len > 1) && (res[len - 1] == '0'); len--);
436     res[len] = '\0';
437
438     /* add "-" for negative numbers */
439     if(positive == 0) {
440         res[len] = '-';
441         res[++len] = '\0';
442     }
443
444     /* swap the string because we wrote it in reverse order */
445     for(i = 0; i < len / 2; i++) {
446         ch = res[i];
447         res[i] = res[len - i - 1];
448         res[len - i - 1] = ch;
449     }
450
451     xmlSecBnFinalize(&bn2);
452     return(res);
453 }
454
455 /**
456  * xmlSecBnFromHexString:
457  * @bn:         the pointer to BN.
458  * @str:        the string with BN.
459  *
460  * Reads @bn from hex string @str.
461  *
462  * Returns: 0 on success or a negative value if an error occurs.
463  */
464 int 
465 xmlSecBnFromHexString(xmlSecBnPtr bn, const xmlChar* str) {
466     return(xmlSecBnFromString(bn, str, 16));
467 }
468
469 /**
470  * xmlSecBnToHexString:
471  * @bn:         the pointer to BN.
472  *
473  * Writes @bn to hex string. Caller is responsible for 
474  * freeing returned string with @xmlFree.
475  *
476  * Returns: the string represenataion if BN or a NULL if an error occurs.
477  */
478 xmlChar* 
479 xmlSecBnToHexString(xmlSecBnPtr bn) {
480     return(xmlSecBnToString(bn, 16));
481 }
482
483 /**
484  * xmlSecBnFromDecString:
485  * @bn:         the pointer to BN.
486  * @str:        the string with BN.
487  *
488  * Reads @bn from decimal string @str.
489  *
490  * Returns: 0 on success or a negative value if an error occurs.
491  */
492 int 
493 xmlSecBnFromDecString(xmlSecBnPtr bn, const xmlChar* str) {
494     return(xmlSecBnFromString(bn, str, 10));
495 }
496
497 /**
498  * xmlSecBnToDecString:
499  * @bn:         the pointer to BN.
500  *
501  * Writes @bn to decimal string. Caller is responsible for 
502  * freeing returned string with @xmlFree.
503  *
504  * Returns: the string represenataion if BN or a NULL if an error occurs.
505  */
506 xmlChar* 
507 xmlSecBnToDecString(xmlSecBnPtr bn) {
508     return(xmlSecBnToString(bn, 10));
509 }
510
511 /**
512  * xmlSecBnMul:
513  * @bn:                 the pointer to BN.
514  * @multiplier:         the multiplier.
515  *
516  * Multiplies @bn with @multiplier.
517  *
518  * Returns: 0 on success or a negative value if an error occurs.
519  */
520 int 
521 xmlSecBnMul(xmlSecBnPtr bn, int multiplier) {
522     xmlSecByte* data;
523     int over;
524     xmlSecSize i;
525     xmlSecByte ch;
526     int ret;
527
528     xmlSecAssert2(bn != NULL, -1);
529     xmlSecAssert2(multiplier > 0, -1);
530
531     if(multiplier == 1) {
532         return(0);
533     }
534
535     data = xmlSecBufferGetData(bn);
536     i = xmlSecBufferGetSize(bn);
537     over = 0; 
538     while(i > 0) {
539         xmlSecAssert2(data != NULL, -1);
540
541         over    = over + multiplier * data[--i];
542         data[i] = over % 256;
543         over    = over / 256;
544     }
545     
546     while(over > 0) {
547         ch      = over % 256;
548         over    = over / 256;
549         
550         ret = xmlSecBufferPrepend(bn, &ch, 1);
551         if(ret < 0) {
552             xmlSecError(XMLSEC_ERRORS_HERE,
553                         NULL,
554                         "xmlSecBufferPrepend",
555                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
556                         "size=1");
557             return (-1);
558         }
559     }
560     
561     return(0);
562 }
563
564 /**
565  * xmlSecBnDiv:
566  * @bn:         the pointer to BN.
567  * @divider:    the divider
568  * @mod:        the pointer for modulus result.
569  *
570  * Divides @bn by @divider and places modulus into @mod.
571  *
572  * Returns: 0 on success or a negative value if an error occurs.
573  */
574 int 
575 xmlSecBnDiv(xmlSecBnPtr bn, int divider, int* mod) {
576     int over;
577     xmlSecSize i, size;
578     xmlSecByte* data;
579     int ret;
580
581     xmlSecAssert2(bn != NULL, -1);
582     xmlSecAssert2(divider > 0, -1);
583     xmlSecAssert2(mod != NULL, -1);
584
585     if(divider == 1) {
586         return(0);
587     }
588
589     data = xmlSecBufferGetData(bn);
590     size = xmlSecBufferGetSize(bn);
591     for(over = 0, i = 0; i < size; i++) {
592         xmlSecAssert2(data != NULL, -1);
593
594         over    = over * 256 + data[i];
595         data[i] = over / divider;
596         over    = over % divider;
597     }
598     (*mod) = over;
599     
600     /* remove leading zeros */
601     for(i = 0; i < size; i++) {
602         xmlSecAssert2(data != NULL, -1);
603
604         if(data[i] != 0) {
605             break;
606         }
607     }
608     if(i > 0) {
609         ret = xmlSecBufferRemoveHead(bn, i);
610         if(ret < 0) {
611             xmlSecError(XMLSEC_ERRORS_HERE,
612                         NULL,
613                         "xmlSecBufferRemoveHead",
614                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
615                         "size=%d", i);
616             return (-1);
617         }
618     }
619     return(0);
620 }
621
622 /**
623  * xmlSecBnAdd:
624  * @bn:         the pointer to BN.
625  * @delta:      the delta.
626  *
627  * Adds @delta to @bn.
628  *
629  * Returns: 0 on success or a negative value if an error occurs.
630  */
631 int 
632 xmlSecBnAdd(xmlSecBnPtr bn, int delta) {
633     int over, tmp;
634     xmlSecByte* data;
635     xmlSecSize i;
636     xmlSecByte ch;
637     int ret;
638
639     xmlSecAssert2(bn != NULL, -1);
640
641     if(delta == 0) {
642         return(0);
643     }
644
645     data = xmlSecBufferGetData(bn);
646     if(delta > 0) {
647         for(over = delta, i = xmlSecBufferGetSize(bn); (i > 0) && (over > 0) ;) {
648                 xmlSecAssert2(data != NULL, -1);
649         
650             tmp     = data[--i];
651                 over   += tmp;
652                 data[i] = over % 256;
653                 over    = over / 256;
654         }
655     
656         while(over > 0) {
657                 ch      = over % 256;
658                 over    = over / 256;
659         
660                 ret = xmlSecBufferPrepend(bn, &ch, 1);
661                 if(ret < 0) {
662                     xmlSecError(XMLSEC_ERRORS_HERE,
663                                 NULL,
664                                 "xmlSecBufferPrepend",
665                                 XMLSEC_ERRORS_R_XMLSEC_FAILED,
666                                 "size=1");
667                     return (-1);
668                 }
669         }
670     } else {
671         for(over = -delta, i = xmlSecBufferGetSize(bn); (i > 0) && (over > 0);) {
672                 xmlSecAssert2(data != NULL, -1);
673         
674             tmp     = data[--i];
675             if(tmp < over) {
676                 data[i] = 0;
677                 over = (over - tmp) / 256;
678             } else {
679                 data[i] = tmp - over;
680                 over = 0;
681             }
682         }
683     }
684     return(0);
685 }
686
687 /**
688  * xmlSecBnReverse:
689  * @bn:         the pointer to BN.
690  *
691  * Reverses bytes order in @bn.
692  *
693  * Returns: 0 on success or a negative value if an error occurs.
694  */
695 int 
696 xmlSecBnReverse(xmlSecBnPtr bn) {
697     xmlSecByte* data;
698     xmlSecSize i, j, size;
699     xmlSecByte ch;
700
701     xmlSecAssert2(bn != NULL, -1);
702
703     data = xmlSecBufferGetData(bn);
704     size = xmlSecBufferGetSize(bn);
705     for(i = 0, j = size - 1; i < size / 2; ++i, --j) {
706         xmlSecAssert2(data != NULL, -1);
707
708         ch       = data[i];
709         data[i]  = data[j];
710         data[j]  = ch;
711     }    
712
713     return(0);
714 }
715
716 /**
717  * xmlSecBnCompare:
718  * @bn:         the pointer to BN.
719  * @data:       the data to compare BN to.
720  * @dataSize:   the @data size.
721  *
722  * Compares the @bn with @data.
723  *
724  * Returns: 0 if data is equal, negative value if @bn is less or positive value if @bn
725  * is greater than @data.
726  */
727 int 
728 xmlSecBnCompare(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize dataSize) {
729     xmlSecByte* bnData;
730     xmlSecSize bnSize;
731
732     xmlSecAssert2(bn != NULL, -1);
733
734     bnData = xmlSecBnGetData(bn);
735     bnSize = xmlSecBnGetSize(bn);
736
737     /* skip zeros in the beggining */
738     while((dataSize > 0) && (data != 0) && (data[0] == 0)) {
739         ++data;
740         --dataSize;
741     }
742     while((bnSize > 0) && (bnData != 0) && (bnData[0] == 0)) {
743         ++bnData;
744         --bnSize;
745     }
746
747     if(((bnData == NULL) || (bnSize == 0)) && ((data == NULL) || (dataSize == 0))) {
748         return(0);
749     } else if((bnData == NULL) || (bnSize == 0)) {
750         return(-1);
751     } else if((data == NULL) || (dataSize == 0)) {
752         return(1);
753     } else if(bnSize < dataSize) {
754         return(-1);
755     } else if(bnSize > dataSize) {
756         return(-1);
757     } 
758
759     xmlSecAssert2(bnData != NULL, -1);
760     xmlSecAssert2(data != NULL, -1);
761     xmlSecAssert2(bnSize == dataSize, -1);
762
763     return(memcmp(bnData, data, dataSize));
764 }
765
766 /**
767  * xmlSecBnCompareReverse:
768  * @bn:         the pointer to BN.
769  * @data:       the data to compare BN to.
770  * @dataSize:   the @data size.
771  *
772  * Compares the @bn with reverse @data.
773  *
774  * Returns: 0 if data is equal, negative value if @bn is less or positive value if @bn
775  * is greater than @data.
776  */
777 int 
778 xmlSecBnCompareReverse(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize dataSize) {
779     xmlSecByte* bnData;
780     xmlSecSize bnSize;
781     xmlSecSize i, j;
782
783     xmlSecAssert2(bn != NULL, -1);
784
785     bnData = xmlSecBnGetData(bn);
786     bnSize = xmlSecBnGetSize(bn);
787
788     /* skip zeros in the beggining */
789     while((dataSize > 0) && (data != 0) && (data[dataSize - 1] == 0)) {
790         --dataSize;
791     }
792     while((bnSize > 0) && (bnData != 0) && (bnData[0] == 0)) {
793         ++bnData;
794         --bnSize;
795     }
796
797     if(((bnData == NULL) || (bnSize == 0)) && ((data == NULL) || (dataSize == 0))) {
798         return(0);
799     } else if((bnData == NULL) || (bnSize == 0)) {
800         return(-1);
801     } else if((data == NULL) || (dataSize == 0)) {
802         return(1);
803     } else if(bnSize < dataSize) {
804         return(-1);
805     } else if(bnSize > dataSize) {
806         return(-1);
807     } 
808
809     xmlSecAssert2(bnData != NULL, -1);
810     xmlSecAssert2(data != NULL, -1);
811     xmlSecAssert2(bnSize == dataSize, -1);
812     for(i = 0, j = dataSize - 1; i < dataSize; ++i, --j) {
813         if(bnData[i] < data[j]) {
814             return(-1);
815         } else if(data[j] < bnData[i]) {
816             return(1);
817         }
818     }
819
820     return(0);
821 }
822
823 /**
824  * xmlSecBnGetNodeValue:
825  * @bn:         the pointer to BN.
826  * @cur:        the poitner to an XML node.
827  * @format:     the BN format.
828  * @reverse:    if set then reverse read buffer after reading.
829  *
830  * Converts the node content from @format to @bn.
831  *
832  * Returns: 0 on success and a negative values if an error occurs.
833  */
834 int 
835 xmlSecBnGetNodeValue(xmlSecBnPtr bn, xmlNodePtr cur, xmlSecBnFormat format, int reverse) {
836     xmlChar* content;
837     int ret;
838
839     xmlSecAssert2(bn != NULL, -1);
840     xmlSecAssert2(cur != NULL, -1);
841
842     switch(format) {
843     case xmlSecBnBase64:
844         ret = xmlSecBufferBase64NodeContentRead(bn, cur);
845         if(ret < 0) {
846             xmlSecError(XMLSEC_ERRORS_HERE,
847                         NULL,
848                         "xmlSecBufferBase64NodeContentRead",
849                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
850                         XMLSEC_ERRORS_NO_MESSAGE);
851             return(-1);
852         }
853         break;
854     case xmlSecBnHex:
855         content = xmlNodeGetContent(cur);
856         if(content == NULL) {
857             xmlSecError(XMLSEC_ERRORS_HERE,
858                         NULL,
859                         "xmlNodeGetContent",
860                         XMLSEC_ERRORS_R_XML_FAILED,
861                         XMLSEC_ERRORS_NO_MESSAGE);
862             return(-1);
863         }
864         ret = xmlSecBnFromHexString(bn, content);
865         if(ret < 0) {
866             xmlSecError(XMLSEC_ERRORS_HERE,
867                         NULL,
868                         "xmlSecBnFromHexString",
869                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
870                         XMLSEC_ERRORS_NO_MESSAGE);
871             xmlFree(content);
872             return(-1);
873         }
874         xmlFree(content);
875         break;
876     case xmlSecBnDec:
877         content = xmlNodeGetContent(cur);
878         if(content == NULL) {
879             xmlSecError(XMLSEC_ERRORS_HERE,
880                         NULL,
881                         "xmlNodeGetContent",
882                         XMLSEC_ERRORS_R_XML_FAILED,
883                         XMLSEC_ERRORS_NO_MESSAGE);
884             return(-1);
885         }
886         ret = xmlSecBnFromDecString(bn, content);
887         if(ret < 0) {
888             xmlSecError(XMLSEC_ERRORS_HERE,
889                         NULL,
890                         "xmlSecBnFromDecString",
891                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
892                         XMLSEC_ERRORS_NO_MESSAGE);
893             xmlFree(content);
894             return(-1);
895         }
896         xmlFree(content);
897         break;
898     }
899
900     if(reverse != 0) {
901         ret = xmlSecBnReverse(bn);
902         if(ret < 0) {
903             xmlSecError(XMLSEC_ERRORS_HERE,
904                         NULL,
905                         "xmlSecBnReverse",
906                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
907                         XMLSEC_ERRORS_NO_MESSAGE);
908             return(-1);
909         }
910     }
911     return(0);
912 }
913
914 /**
915  * xmlSecBnSetNodeValue:
916  * @bn:                 the pointer to BN.
917  * @cur:                the poitner to an XML node.
918  * @format:             the BN format.
919  * @reverse:            the flag that indicates whether to reverse the buffer before writing.
920  * @addLineBreaks:      the flag; it is equal to 1 then linebreaks will be added before and after new buffer content.
921  *
922  * Converts the @bn and sets it to node content.
923  *
924  * Returns: 0 on success and a negative values if an error occurs.
925  */
926 int  
927 xmlSecBnSetNodeValue(xmlSecBnPtr bn, xmlNodePtr cur, xmlSecBnFormat format, int reverse, int addLineBreaks) {
928     xmlChar* content;
929     int ret;
930
931     xmlSecAssert2(bn != NULL, -1);
932     xmlSecAssert2(cur != NULL, -1);
933
934     if(reverse != 0) {
935         ret = xmlSecBnReverse(bn);
936         if(ret < 0) {
937             xmlSecError(XMLSEC_ERRORS_HERE,
938                         NULL,
939                         "xmlSecBnReverse",
940                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
941                         XMLSEC_ERRORS_NO_MESSAGE);
942             return(-1);
943         }
944     }
945
946     if(addLineBreaks) {
947         xmlNodeAddContent(cur, xmlSecStringCR);
948     }
949
950     switch(format) {
951     case xmlSecBnBase64:
952         ret = xmlSecBufferBase64NodeContentWrite(bn, cur, xmlSecBase64GetDefaultLineSize());
953         if(ret < 0) {
954             xmlSecError(XMLSEC_ERRORS_HERE,
955                         NULL,
956                         "xmlSecBufferBase64NodeContentWrite",
957                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
958                         XMLSEC_ERRORS_NO_MESSAGE);
959             return(-1);
960         }
961         break;
962     case xmlSecBnHex:
963         content = xmlSecBnToHexString(bn);
964         if(content == NULL) {
965             xmlSecError(XMLSEC_ERRORS_HERE,
966                         NULL,
967                         "xmlSecBnToHexString",
968                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
969                         XMLSEC_ERRORS_NO_MESSAGE);
970             xmlFree(content);
971             return(-1);
972         }
973         xmlNodeSetContent(cur, content);
974         xmlFree(content);
975         break;
976     case xmlSecBnDec:
977         content = xmlSecBnToDecString(bn);
978         if(content == NULL) {
979             xmlSecError(XMLSEC_ERRORS_HERE,
980                         NULL,
981                         "xmlSecBnToDecString",
982                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
983                         XMLSEC_ERRORS_NO_MESSAGE);
984             xmlFree(content);
985             return(-1);
986         }
987         xmlNodeSetContent(cur, content);
988         xmlFree(content);
989         break;
990     }
991
992     if(addLineBreaks) {
993         xmlNodeAddContent(cur, xmlSecStringCR);
994     }
995
996     return(0);
997 }
998
999 /**
1000  * xmlSecBnBlobSetNodeValue:
1001  * @data:       the pointer to BN blob.
1002  * @dataSize:   the size of BN blob.
1003  * @cur:        the poitner to an XML node.
1004  * @format:     the BN format.
1005  * @reverse:    the flag that indicates whether to reverse the buffer before writing.
1006  * @addLineBreaks:  if the flag is equal to 1 then 
1007  *              linebreaks will be added before and after
1008  *              new buffer content.
1009  *
1010  * Converts the @blob and sets it to node content.
1011  *
1012  * Returns: 0 on success and a negative values if an error occurs.
1013  */
1014 int  
1015 xmlSecBnBlobSetNodeValue(const xmlSecByte* data, xmlSecSize dataSize, 
1016                          xmlNodePtr cur, xmlSecBnFormat format, int reverse,
1017                          int addLineBreaks) {
1018     xmlSecBn bn;
1019     int ret;
1020
1021     xmlSecAssert2(data != NULL, -1);
1022     xmlSecAssert2(cur != NULL, -1);
1023
1024     ret = xmlSecBnInitialize(&bn, dataSize);
1025     if(ret < 0) {
1026         xmlSecError(XMLSEC_ERRORS_HERE,
1027                     NULL,
1028                     "xmlSecBnInitialize",
1029                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1030                     XMLSEC_ERRORS_NO_MESSAGE);
1031         return(-1);
1032     }
1033
1034     ret = xmlSecBnSetData(&bn, data, dataSize);
1035     if(ret < 0) {
1036         xmlSecError(XMLSEC_ERRORS_HERE,
1037                     NULL,
1038                     "xmlSecBnSetData",
1039                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1040                     XMLSEC_ERRORS_NO_MESSAGE);
1041         xmlSecBnFinalize(&bn);
1042         return(-1);
1043     }
1044
1045     ret = xmlSecBnSetNodeValue(&bn, cur, format, reverse, addLineBreaks);
1046     if(ret < 0) {
1047         xmlSecError(XMLSEC_ERRORS_HERE,
1048                     NULL,
1049                     "xmlSecBnSetNodeValue",
1050                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1051                     XMLSEC_ERRORS_NO_MESSAGE);
1052         xmlSecBnFinalize(&bn);
1053         return(-1);
1054     }
1055
1056     xmlSecBnFinalize(&bn);
1057     return(0);
1058 }
1059
1060