Line data Source code
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 0 : xmlSecBnCreate(xmlSecSize size) {
69 0 : 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 0 : xmlSecBnDestroy(xmlSecBnPtr bn) {
80 0 : xmlSecBufferDestroy(bn);
81 0 : }
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 0 : xmlSecBnInitialize(xmlSecBnPtr bn, xmlSecSize size) {
95 0 : 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 0 : xmlSecBnFinalize(xmlSecBnPtr bn) {
106 0 : xmlSecBufferFinalize(bn);
107 0 : }
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 0 : xmlSecBnGetData(xmlSecBnPtr bn) {
119 0 : 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 0 : xmlSecBnSetData(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize size) {
134 0 : 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 0 : xmlSecBnGetSize(xmlSecBnPtr bn) {
147 0 : 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 0 : xmlSecBnZero(xmlSecBnPtr bn) {
158 0 : xmlSecBufferEmpty(bn);
159 0 : }
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 0 : 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 0 : xmlSecAssert2(bn != NULL, -1);
181 0 : xmlSecAssert2(str != NULL, -1);
182 0 : xmlSecAssert2(base > 1, -1);
183 0 : xmlSecAssert2(base <= sizeof(xmlSecBnRevLookupTable), -1);
184 :
185 : /* trivial case */
186 0 : len = xmlStrlen(str);
187 0 : if(len == 0) {
188 0 : 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 0 : ret = xmlSecBufferSetMaxSize(bn, xmlSecBufferGetSize(bn) + len / 2 + 1 + 1);
199 0 : if(ret < 0) {
200 0 : xmlSecError(XMLSEC_ERRORS_HERE,
201 : NULL,
202 : "xmlSecBnRevLookupTable",
203 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
204 0 : "size=%d", len / 2 + 1);
205 0 : return (-1);
206 : }
207 :
208 : /* figure out if it is positive or negative number */
209 0 : positive = 1;
210 0 : i = 0;
211 0 : while(i < len) {
212 0 : ch = str[i++];
213 :
214 : /* skip spaces */
215 0 : if(isspace(ch)) {
216 0 : continue;
217 : }
218 :
219 : /* check if it is + or - */
220 0 : if(ch == '+') {
221 0 : positive = 1;
222 0 : break;
223 0 : } else if(ch == '-') {
224 0 : positive = 0;
225 0 : break;
226 : }
227 :
228 : /* otherwise, it must be start of the number */
229 0 : nn = xmlSecBnLookupTable[ch];
230 0 : if((nn >= 0) && ((xmlSecSize)nn < base)) {
231 0 : xmlSecAssert2(i > 0, -1);
232 :
233 : /* no sign, positive by default */
234 0 : positive = 1;
235 0 : --i; /* make sure that we will look at this character in next loop */
236 0 : break;
237 : } else {
238 0 : xmlSecError(XMLSEC_ERRORS_HERE,
239 : NULL,
240 : NULL,
241 : XMLSEC_ERRORS_R_INVALID_DATA,
242 : "char=%c;base=%d",
243 : ch, base);
244 0 : return (-1);
245 : }
246 : }
247 :
248 : /* now parse the number itself */
249 0 : while(i < len) {
250 0 : ch = str[i++];
251 0 : if(isspace(ch)) {
252 0 : continue;
253 : }
254 :
255 : xmlSecAssert2(ch <= sizeof(xmlSecBnLookupTable), -1);
256 0 : nn = xmlSecBnLookupTable[ch];
257 0 : if((nn < 0) || ((xmlSecSize)nn > base)) {
258 0 : xmlSecError(XMLSEC_ERRORS_HERE,
259 : NULL,
260 : NULL,
261 : XMLSEC_ERRORS_R_INVALID_DATA,
262 : "char=%c;base=%d",
263 : ch, base);
264 0 : return (-1);
265 : }
266 :
267 0 : ret = xmlSecBnMul(bn, base);
268 0 : if(ret < 0) {
269 0 : xmlSecError(XMLSEC_ERRORS_HERE,
270 : NULL,
271 : "xmlSecBnMul",
272 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
273 : "base=%d", base);
274 0 : return (-1);
275 : }
276 :
277 0 : ret = xmlSecBnAdd(bn, nn);
278 0 : if(ret < 0) {
279 0 : xmlSecError(XMLSEC_ERRORS_HERE,
280 : NULL,
281 : "xmlSecBnAdd",
282 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
283 : "base=%d", base);
284 0 : return (-1);
285 : }
286 : }
287 :
288 : /* check if we need to add 00 prefix, do this for empty bn too */
289 0 : data = xmlSecBufferGetData(bn);
290 0 : size = xmlSecBufferGetSize(bn);
291 0 : if(((size > 0) && (data[0] > 127)) || (size == 0)) {
292 0 : ch = 0;
293 0 : ret = xmlSecBufferPrepend(bn, &ch, 1);
294 0 : if(ret < 0) {
295 0 : xmlSecError(XMLSEC_ERRORS_HERE,
296 : NULL,
297 : "xmlSecBufferPrepend",
298 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
299 : "base=%d", base);
300 0 : return (-1);
301 : }
302 : }
303 :
304 : /* do 2's compliment and add 1 to represent negative value */
305 0 : if(positive == 0) {
306 0 : data = xmlSecBufferGetData(bn);
307 0 : size = xmlSecBufferGetSize(bn);
308 0 : for(i = 0; i < size; ++i) {
309 0 : data[i] ^= 0xFF;
310 : }
311 :
312 0 : ret = xmlSecBnAdd(bn, 1);
313 0 : if(ret < 0) {
314 0 : xmlSecError(XMLSEC_ERRORS_HERE,
315 : NULL,
316 : "xmlSecBnAdd",
317 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
318 : "base=%d", base);
319 0 : return (-1);
320 : }
321 : }
322 :
323 0 : 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 0 : xmlSecBnToString(xmlSecBnPtr bn, xmlSecSize base) {
338 : xmlSecBn bn2;
339 0 : 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 0 : xmlSecAssert2(bn != NULL, NULL);
348 0 : xmlSecAssert2(base > 1, NULL);
349 0 : xmlSecAssert2(base <= sizeof(xmlSecBnRevLookupTable), NULL);
350 :
351 :
352 : /* copy bn */
353 0 : data = xmlSecBufferGetData(bn);
354 0 : size = xmlSecBufferGetSize(bn);
355 0 : ret = xmlSecBnInitialize(&bn2, size);
356 0 : if(ret < 0) {
357 0 : xmlSecError(XMLSEC_ERRORS_HERE,
358 : NULL,
359 : "xmlSecBnCreate",
360 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
361 : "size=%d", size);
362 0 : return (NULL);
363 : }
364 :
365 0 : ret = xmlSecBnSetData(&bn2, data, size);
366 0 : if(ret < 0) {
367 0 : xmlSecError(XMLSEC_ERRORS_HERE,
368 : NULL,
369 : "xmlSecBnSetData",
370 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
371 : "size=%d", size);
372 0 : xmlSecBnFinalize(&bn2);
373 0 : return (NULL);
374 : }
375 :
376 : /* check if it is a negative number or not */
377 0 : data = xmlSecBufferGetData(&bn2);
378 0 : size = xmlSecBufferGetSize(&bn2);
379 0 : if((size > 0) && (data[0] > 127)) {
380 : /* subtract 1 and do 2's compliment */
381 0 : ret = xmlSecBnAdd(&bn2, -1);
382 0 : if(ret < 0) {
383 0 : xmlSecError(XMLSEC_ERRORS_HERE,
384 : NULL,
385 : "xmlSecBnAdd",
386 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
387 : "size=%d", size);
388 0 : xmlSecBnFinalize(&bn2);
389 0 : return (NULL);
390 : }
391 0 : for(i = 0; i < size; ++i) {
392 0 : data[i] ^= 0xFF;
393 : }
394 :
395 0 : positive = 0;
396 : } else {
397 0 : 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 0 : len = 8 * size + 1 + 1;
406 0 : res = (xmlChar*)xmlMalloc(len + 1);
407 0 : if(res == NULL) {
408 0 : xmlSecError(XMLSEC_ERRORS_HERE,
409 : NULL,
410 : NULL,
411 : XMLSEC_ERRORS_R_MALLOC_FAILED,
412 : "len=%d", len);
413 0 : xmlSecBnFinalize(&bn2);
414 0 : return (NULL);
415 : }
416 0 : memset(res, 0, len + 1);
417 :
418 0 : for(i = 0; (xmlSecBufferGetSize(&bn2) > 0) && (i < len); i++) {
419 0 : if(xmlSecBnDiv(&bn2, base, &nn) < 0) {
420 0 : xmlSecError(XMLSEC_ERRORS_HERE,
421 : NULL,
422 : "xmlSecBnDiv",
423 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
424 : "base=%d", base);
425 0 : xmlFree(res);
426 0 : xmlSecBnFinalize(&bn2);
427 0 : return (NULL);
428 : }
429 0 : xmlSecAssert2((size_t)nn < sizeof(xmlSecBnRevLookupTable), NULL);
430 0 : res[i] = xmlSecBnRevLookupTable[nn];
431 : }
432 0 : xmlSecAssert2(i < len, NULL);
433 :
434 : /* we might have '0' at the beggining, remove it but keep one zero */
435 0 : for(len = i; (len > 1) && (res[len - 1] == '0'); len--);
436 0 : res[len] = '\0';
437 :
438 : /* add "-" for negative numbers */
439 0 : if(positive == 0) {
440 0 : res[len] = '-';
441 0 : res[++len] = '\0';
442 : }
443 :
444 : /* swap the string because we wrote it in reverse order */
445 0 : for(i = 0; i < len / 2; i++) {
446 0 : ch = res[i];
447 0 : res[i] = res[len - i - 1];
448 0 : res[len - i - 1] = ch;
449 : }
450 :
451 0 : xmlSecBnFinalize(&bn2);
452 0 : 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 0 : xmlSecBnFromHexString(xmlSecBnPtr bn, const xmlChar* str) {
466 0 : 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 0 : xmlSecBnToHexString(xmlSecBnPtr bn) {
480 0 : 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 0 : xmlSecBnFromDecString(xmlSecBnPtr bn, const xmlChar* str) {
494 0 : 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 0 : xmlSecBnToDecString(xmlSecBnPtr bn) {
508 0 : 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 0 : xmlSecBnMul(xmlSecBnPtr bn, int multiplier) {
522 : xmlSecByte* data;
523 : int over;
524 : xmlSecSize i;
525 : xmlSecByte ch;
526 : int ret;
527 :
528 0 : xmlSecAssert2(bn != NULL, -1);
529 0 : xmlSecAssert2(multiplier > 0, -1);
530 :
531 0 : if(multiplier == 1) {
532 0 : return(0);
533 : }
534 :
535 0 : data = xmlSecBufferGetData(bn);
536 0 : i = xmlSecBufferGetSize(bn);
537 0 : over = 0;
538 0 : while(i > 0) {
539 0 : xmlSecAssert2(data != NULL, -1);
540 :
541 0 : over = over + multiplier * data[--i];
542 0 : data[i] = over % 256;
543 0 : over = over / 256;
544 : }
545 :
546 0 : while(over > 0) {
547 0 : ch = over % 256;
548 0 : over = over / 256;
549 :
550 0 : ret = xmlSecBufferPrepend(bn, &ch, 1);
551 0 : if(ret < 0) {
552 0 : xmlSecError(XMLSEC_ERRORS_HERE,
553 : NULL,
554 : "xmlSecBufferPrepend",
555 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
556 : "size=1");
557 0 : return (-1);
558 : }
559 : }
560 :
561 0 : 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 0 : xmlSecBnDiv(xmlSecBnPtr bn, int divider, int* mod) {
576 : int over;
577 : xmlSecSize i, size;
578 : xmlSecByte* data;
579 : int ret;
580 :
581 0 : xmlSecAssert2(bn != NULL, -1);
582 0 : xmlSecAssert2(divider > 0, -1);
583 0 : xmlSecAssert2(mod != NULL, -1);
584 :
585 0 : if(divider == 1) {
586 0 : return(0);
587 : }
588 :
589 0 : data = xmlSecBufferGetData(bn);
590 0 : size = xmlSecBufferGetSize(bn);
591 0 : for(over = 0, i = 0; i < size; i++) {
592 0 : xmlSecAssert2(data != NULL, -1);
593 :
594 0 : over = over * 256 + data[i];
595 0 : data[i] = over / divider;
596 0 : over = over % divider;
597 : }
598 0 : (*mod) = over;
599 :
600 : /* remove leading zeros */
601 0 : for(i = 0; i < size; i++) {
602 0 : xmlSecAssert2(data != NULL, -1);
603 :
604 0 : if(data[i] != 0) {
605 0 : break;
606 : }
607 : }
608 0 : if(i > 0) {
609 0 : ret = xmlSecBufferRemoveHead(bn, i);
610 0 : if(ret < 0) {
611 0 : xmlSecError(XMLSEC_ERRORS_HERE,
612 : NULL,
613 : "xmlSecBufferRemoveHead",
614 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
615 : "size=%d", i);
616 0 : return (-1);
617 : }
618 : }
619 0 : 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 0 : xmlSecBnAdd(xmlSecBnPtr bn, int delta) {
633 : int over, tmp;
634 : xmlSecByte* data;
635 : xmlSecSize i;
636 : xmlSecByte ch;
637 : int ret;
638 :
639 0 : xmlSecAssert2(bn != NULL, -1);
640 :
641 0 : if(delta == 0) {
642 0 : return(0);
643 : }
644 :
645 0 : data = xmlSecBufferGetData(bn);
646 0 : if(delta > 0) {
647 0 : for(over = delta, i = xmlSecBufferGetSize(bn); (i > 0) && (over > 0) ;) {
648 0 : xmlSecAssert2(data != NULL, -1);
649 :
650 0 : tmp = data[--i];
651 0 : over += tmp;
652 0 : data[i] = over % 256;
653 0 : over = over / 256;
654 : }
655 :
656 0 : while(over > 0) {
657 0 : ch = over % 256;
658 0 : over = over / 256;
659 :
660 0 : ret = xmlSecBufferPrepend(bn, &ch, 1);
661 0 : if(ret < 0) {
662 0 : xmlSecError(XMLSEC_ERRORS_HERE,
663 : NULL,
664 : "xmlSecBufferPrepend",
665 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
666 : "size=1");
667 0 : return (-1);
668 : }
669 : }
670 : } else {
671 0 : for(over = -delta, i = xmlSecBufferGetSize(bn); (i > 0) && (over > 0);) {
672 0 : xmlSecAssert2(data != NULL, -1);
673 :
674 0 : tmp = data[--i];
675 0 : if(tmp < over) {
676 0 : data[i] = 0;
677 0 : over = (over - tmp) / 256;
678 : } else {
679 0 : data[i] = tmp - over;
680 0 : over = 0;
681 : }
682 : }
683 : }
684 0 : 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 0 : xmlSecBnReverse(xmlSecBnPtr bn) {
697 : xmlSecByte* data;
698 : xmlSecSize i, j, size;
699 : xmlSecByte ch;
700 :
701 0 : xmlSecAssert2(bn != NULL, -1);
702 :
703 0 : data = xmlSecBufferGetData(bn);
704 0 : size = xmlSecBufferGetSize(bn);
705 0 : for(i = 0, j = size - 1; i < size / 2; ++i, --j) {
706 0 : xmlSecAssert2(data != NULL, -1);
707 :
708 0 : ch = data[i];
709 0 : data[i] = data[j];
710 0 : data[j] = ch;
711 : }
712 :
713 0 : 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 0 : xmlSecBnCompare(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize dataSize) {
729 : xmlSecByte* bnData;
730 : xmlSecSize bnSize;
731 :
732 0 : xmlSecAssert2(bn != NULL, -1);
733 :
734 0 : bnData = xmlSecBnGetData(bn);
735 0 : bnSize = xmlSecBnGetSize(bn);
736 :
737 : /* skip zeros in the beggining */
738 0 : while((dataSize > 0) && (data != 0) && (data[0] == 0)) {
739 0 : ++data;
740 0 : --dataSize;
741 : }
742 0 : while((bnSize > 0) && (bnData != 0) && (bnData[0] == 0)) {
743 0 : ++bnData;
744 0 : --bnSize;
745 : }
746 :
747 0 : if(((bnData == NULL) || (bnSize == 0)) && ((data == NULL) || (dataSize == 0))) {
748 0 : return(0);
749 0 : } else if((bnData == NULL) || (bnSize == 0)) {
750 0 : return(-1);
751 0 : } else if((data == NULL) || (dataSize == 0)) {
752 0 : return(1);
753 0 : } else if(bnSize < dataSize) {
754 0 : return(-1);
755 0 : } else if(bnSize > dataSize) {
756 0 : return(-1);
757 : }
758 :
759 0 : xmlSecAssert2(bnData != NULL, -1);
760 0 : xmlSecAssert2(data != NULL, -1);
761 0 : xmlSecAssert2(bnSize == dataSize, -1);
762 :
763 0 : 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 0 : xmlSecBnCompareReverse(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize dataSize) {
779 : xmlSecByte* bnData;
780 : xmlSecSize bnSize;
781 : xmlSecSize i, j;
782 :
783 0 : xmlSecAssert2(bn != NULL, -1);
784 :
785 0 : bnData = xmlSecBnGetData(bn);
786 0 : bnSize = xmlSecBnGetSize(bn);
787 :
788 : /* skip zeros in the beggining */
789 0 : while((dataSize > 0) && (data != 0) && (data[dataSize - 1] == 0)) {
790 0 : --dataSize;
791 : }
792 0 : while((bnSize > 0) && (bnData != 0) && (bnData[0] == 0)) {
793 0 : ++bnData;
794 0 : --bnSize;
795 : }
796 :
797 0 : if(((bnData == NULL) || (bnSize == 0)) && ((data == NULL) || (dataSize == 0))) {
798 0 : return(0);
799 0 : } else if((bnData == NULL) || (bnSize == 0)) {
800 0 : return(-1);
801 0 : } else if((data == NULL) || (dataSize == 0)) {
802 0 : return(1);
803 0 : } else if(bnSize < dataSize) {
804 0 : return(-1);
805 0 : } else if(bnSize > dataSize) {
806 0 : return(-1);
807 : }
808 :
809 0 : xmlSecAssert2(bnData != NULL, -1);
810 0 : xmlSecAssert2(data != NULL, -1);
811 0 : xmlSecAssert2(bnSize == dataSize, -1);
812 0 : for(i = 0, j = dataSize - 1; i < dataSize; ++i, --j) {
813 0 : if(bnData[i] < data[j]) {
814 0 : return(-1);
815 0 : } else if(data[j] < bnData[i]) {
816 0 : return(1);
817 : }
818 : }
819 :
820 0 : 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 0 : xmlSecBnGetNodeValue(xmlSecBnPtr bn, xmlNodePtr cur, xmlSecBnFormat format, int reverse) {
836 : xmlChar* content;
837 : int ret;
838 :
839 0 : xmlSecAssert2(bn != NULL, -1);
840 0 : xmlSecAssert2(cur != NULL, -1);
841 :
842 0 : switch(format) {
843 : case xmlSecBnBase64:
844 0 : ret = xmlSecBufferBase64NodeContentRead(bn, cur);
845 0 : if(ret < 0) {
846 0 : xmlSecError(XMLSEC_ERRORS_HERE,
847 : NULL,
848 : "xmlSecBufferBase64NodeContentRead",
849 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
850 : XMLSEC_ERRORS_NO_MESSAGE);
851 0 : return(-1);
852 : }
853 0 : break;
854 : case xmlSecBnHex:
855 0 : content = xmlNodeGetContent(cur);
856 0 : if(content == NULL) {
857 0 : xmlSecError(XMLSEC_ERRORS_HERE,
858 : NULL,
859 : "xmlNodeGetContent",
860 : XMLSEC_ERRORS_R_XML_FAILED,
861 : XMLSEC_ERRORS_NO_MESSAGE);
862 0 : return(-1);
863 : }
864 0 : ret = xmlSecBnFromHexString(bn, content);
865 0 : if(ret < 0) {
866 0 : xmlSecError(XMLSEC_ERRORS_HERE,
867 : NULL,
868 : "xmlSecBnFromHexString",
869 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
870 : XMLSEC_ERRORS_NO_MESSAGE);
871 0 : xmlFree(content);
872 0 : return(-1);
873 : }
874 0 : xmlFree(content);
875 0 : break;
876 : case xmlSecBnDec:
877 0 : content = xmlNodeGetContent(cur);
878 0 : if(content == NULL) {
879 0 : xmlSecError(XMLSEC_ERRORS_HERE,
880 : NULL,
881 : "xmlNodeGetContent",
882 : XMLSEC_ERRORS_R_XML_FAILED,
883 : XMLSEC_ERRORS_NO_MESSAGE);
884 0 : return(-1);
885 : }
886 0 : ret = xmlSecBnFromDecString(bn, content);
887 0 : if(ret < 0) {
888 0 : xmlSecError(XMLSEC_ERRORS_HERE,
889 : NULL,
890 : "xmlSecBnFromDecString",
891 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
892 : XMLSEC_ERRORS_NO_MESSAGE);
893 0 : xmlFree(content);
894 0 : return(-1);
895 : }
896 0 : xmlFree(content);
897 0 : break;
898 : }
899 :
900 0 : if(reverse != 0) {
901 0 : ret = xmlSecBnReverse(bn);
902 0 : if(ret < 0) {
903 0 : xmlSecError(XMLSEC_ERRORS_HERE,
904 : NULL,
905 : "xmlSecBnReverse",
906 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
907 : XMLSEC_ERRORS_NO_MESSAGE);
908 0 : return(-1);
909 : }
910 : }
911 0 : 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 0 : xmlSecBnSetNodeValue(xmlSecBnPtr bn, xmlNodePtr cur, xmlSecBnFormat format, int reverse, int addLineBreaks) {
928 : xmlChar* content;
929 : int ret;
930 :
931 0 : xmlSecAssert2(bn != NULL, -1);
932 0 : xmlSecAssert2(cur != NULL, -1);
933 :
934 0 : if(reverse != 0) {
935 0 : ret = xmlSecBnReverse(bn);
936 0 : if(ret < 0) {
937 0 : xmlSecError(XMLSEC_ERRORS_HERE,
938 : NULL,
939 : "xmlSecBnReverse",
940 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
941 : XMLSEC_ERRORS_NO_MESSAGE);
942 0 : return(-1);
943 : }
944 : }
945 :
946 0 : if(addLineBreaks) {
947 0 : xmlNodeAddContent(cur, xmlSecStringCR);
948 : }
949 :
950 0 : switch(format) {
951 : case xmlSecBnBase64:
952 0 : ret = xmlSecBufferBase64NodeContentWrite(bn, cur, xmlSecBase64GetDefaultLineSize());
953 0 : if(ret < 0) {
954 0 : xmlSecError(XMLSEC_ERRORS_HERE,
955 : NULL,
956 : "xmlSecBufferBase64NodeContentWrite",
957 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
958 : XMLSEC_ERRORS_NO_MESSAGE);
959 0 : return(-1);
960 : }
961 0 : break;
962 : case xmlSecBnHex:
963 0 : content = xmlSecBnToHexString(bn);
964 0 : if(content == NULL) {
965 0 : xmlSecError(XMLSEC_ERRORS_HERE,
966 : NULL,
967 : "xmlSecBnToHexString",
968 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
969 : XMLSEC_ERRORS_NO_MESSAGE);
970 0 : xmlFree(content);
971 0 : return(-1);
972 : }
973 0 : xmlNodeSetContent(cur, content);
974 0 : xmlFree(content);
975 0 : break;
976 : case xmlSecBnDec:
977 0 : content = xmlSecBnToDecString(bn);
978 0 : if(content == NULL) {
979 0 : xmlSecError(XMLSEC_ERRORS_HERE,
980 : NULL,
981 : "xmlSecBnToDecString",
982 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
983 : XMLSEC_ERRORS_NO_MESSAGE);
984 0 : xmlFree(content);
985 0 : return(-1);
986 : }
987 0 : xmlNodeSetContent(cur, content);
988 0 : xmlFree(content);
989 0 : break;
990 : }
991 :
992 0 : if(addLineBreaks) {
993 0 : xmlNodeAddContent(cur, xmlSecStringCR);
994 : }
995 :
996 0 : 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 0 : xmlSecBnBlobSetNodeValue(const xmlSecByte* data, xmlSecSize dataSize,
1016 : xmlNodePtr cur, xmlSecBnFormat format, int reverse,
1017 : int addLineBreaks) {
1018 : xmlSecBn bn;
1019 : int ret;
1020 :
1021 0 : xmlSecAssert2(data != NULL, -1);
1022 0 : xmlSecAssert2(cur != NULL, -1);
1023 :
1024 0 : ret = xmlSecBnInitialize(&bn, dataSize);
1025 0 : if(ret < 0) {
1026 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1027 : NULL,
1028 : "xmlSecBnInitialize",
1029 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1030 : XMLSEC_ERRORS_NO_MESSAGE);
1031 0 : return(-1);
1032 : }
1033 :
1034 0 : ret = xmlSecBnSetData(&bn, data, dataSize);
1035 0 : if(ret < 0) {
1036 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1037 : NULL,
1038 : "xmlSecBnSetData",
1039 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1040 : XMLSEC_ERRORS_NO_MESSAGE);
1041 0 : xmlSecBnFinalize(&bn);
1042 0 : return(-1);
1043 : }
1044 :
1045 0 : ret = xmlSecBnSetNodeValue(&bn, cur, format, reverse, addLineBreaks);
1046 0 : if(ret < 0) {
1047 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1048 : NULL,
1049 : "xmlSecBnSetNodeValue",
1050 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1051 : XMLSEC_ERRORS_NO_MESSAGE);
1052 0 : xmlSecBnFinalize(&bn);
1053 0 : return(-1);
1054 : }
1055 :
1056 0 : xmlSecBnFinalize(&bn);
1057 0 : return(0);
1058 : }
1059 :
1060 :
|