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