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