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