xmlsecurityengine/xmlsec/src/xmlsec_bn.c
changeset 0 e35f40988205
child 12 d10d750052f0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlsec/src/xmlsec_bn.c	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,1087 @@
+/** 
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Big Numbers.
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ * 
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyright (C) 2003 Cordys R&D BV, All rights reserved.
+ * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
+ */
+#include "xmlsec_globals.h" 
+ 
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+ 
+#include <libxml2_tree.h>
+#include <libxml2_globals.h>
+
+#include "xmlsec_xmlsec.h"
+#include "xmlsec_xmltree.h"
+#include "xmlsec_base64.h"
+#include "xmlsec_bn.h"
+#include "xmlsec_errors.h"
+
+/* table for converting hex digits back to bytes */
+static const int xmlSecBnLookupTable[] =
+{
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static const char xmlSecBnRevLookupTable[] = 
+{ 
+    '0', '1', '2', '3', '4', '5', '6', '7', 
+    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
+};
+
+/*****************************************************************************
+ *
+ * xmlSecBn
+ *
+ ****************************************************************************/
+/**
+ * xmlSecBnCreate:
+ * @size:	the initial allocated BN size.
+ *
+ * Creates a new BN object. Caller is responsible for destroying it
+ * by calling @xmlSecBnDestroy function.
+ *
+ * Returns the newly BN or a NULL if an error occurs.
+ */
+EXPORT_C
+xmlSecBnPtr 
+xmlSecBnCreate(xmlSecSize size) {
+    return(xmlSecBufferCreate(size));
+}
+
+/**
+ * xmlSecBnDestroy:
+ * @bn:		the pointer to BN.
+ *
+ * Destroys @bn object created with @xmlSecBnCreate function.
+ */
+EXPORT_C
+void 
+xmlSecBnDestroy(xmlSecBnPtr bn) {
+    xmlSecBufferDestroy(bn);
+}
+
+/**
+ * xmlSecBnInitialize:
+ * @bn:		the pointer to BN.
+ * @size:	the initial allocated BN size.
+ *
+ * Initializes a BN object. Caller is responsible for destroying it
+ * by calling @xmlSecBnFinalize function.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnInitialize(xmlSecBnPtr bn, xmlSecSize size) {
+    return(xmlSecBufferInitialize(bn, size));
+}
+
+/**
+ * xmlSecBnFinalize:
+ * @bn:		the pointer to BN.
+ *
+ * Destroys @bn object created with @xmlSecBnInitialize function.
+ */
+EXPORT_C
+void 
+xmlSecBnFinalize(xmlSecBnPtr bn) {
+    xmlSecBufferFinalize(bn);
+}
+
+/**
+ * xmlSecBnGetData:
+ * @bn:		the pointer to BN.
+ *
+ * Gets pointer to the binary @bn representation.
+ * 
+ * Returns pointer to binary BN data or NULL if an error occurs.
+ */
+EXPORT_C
+xmlSecByte* 
+xmlSecBnGetData(xmlSecBnPtr bn) {
+    return(xmlSecBufferGetData(bn));
+}
+
+/**
+ * xmlSecBnSetData:
+ * @bn:		the pointer to BN.
+ * @data:	the pointer to new BN binary data.
+ * @size:	the size of new BN data.
+ *
+ * Sets the value of @bn to @data.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnSetData(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize size) {
+    return(xmlSecBufferSetData(bn, data, size));
+}
+
+/**
+ * xmlSecBnGetSize:
+ * @bn:		the pointer to BN.
+ *
+ * Gets the size of binary data in @bn.
+ *
+ * Returns the size of binary data.
+ */
+EXPORT_C
+xmlSecSize 
+xmlSecBnGetSize(xmlSecBnPtr bn) {
+    return(xmlSecBufferGetSize(bn));
+}
+
+/**
+ * xmlSecBnZero:
+ * @bn:		the pointer to BN.
+ *
+ * Sets the value of @bn to zero.
+ */
+EXPORT_C
+void 
+xmlSecBnZero(xmlSecBnPtr bn) {
+    xmlSecBufferEmpty(bn);
+}
+
+/**
+ * xmlSecBnFromString:
+ * @bn:		the pointer to BN.
+ * @str:	the string with BN.
+ * @base:	the base for @str.
+ *
+ * Reads @bn from string @str assuming it has base @base.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnFromString(xmlSecBnPtr bn, const xmlChar* str, xmlSecSize base) {
+    xmlSecSize i, len, size;
+    xmlSecByte ch;
+    xmlSecByte* data;
+    int positive;
+    int nn;
+    int ret;
+
+    xmlSecAssert2(bn != NULL, -1);
+    xmlSecAssert2(str != NULL, -1);
+    xmlSecAssert2(base > 1, -1);
+    xmlSecAssert2(base <= sizeof(xmlSecBnRevLookupTable), -1);
+
+    /* trivial case */
+    len = xmlStrlen(str);
+    if(len == 0) {
+        return(0);
+    }
+    
+    /* The result size could not exceed the input string length
+     * because each char fits inside a byte in all cases :)
+     * In truth, it would be likely less than 1/2 input string length
+     * because each byte is represented by 2 chars. If needed, 
+     * buffer size would be increased by Mul/Add functions.
+     * Finally, we can add one byte for 00 or 10 prefix.
+     */
+    ret = xmlSecBufferSetMaxSize(bn, xmlSecBufferGetSize(bn) + len / 2 + 1 + 1);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecBnRevLookupTable",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "size=%d", len / 2 + 1);
+        return (-1);
+    }
+
+    /* figure out if it is positive or negative number */
+    positive = 1;
+    i = 0;
+    while(i < len) {
+        ch = str[i++];
+
+        /* skip spaces */
+        if(isspace(ch)) {
+	        continue;
+        } 
+        
+        /* check if it is + or - */
+        if(ch == '+') {
+            positive = 1;
+            break;
+        } else if(ch == '-') {
+            positive = 0;
+            break;
+        }
+
+        /* otherwise, it must be start of the number */
+        nn = xmlSecBnLookupTable[ch];
+        if((nn >= 0) && ((xmlSecSize)nn < base)) {
+            xmlSecAssert2(i > 0, -1);
+
+            /* no sign, positive by default */
+            positive = 1;
+            --i; /* make sure that we will look at this character in next loop */
+            break;
+        } else {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        NULL,
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        "char=%c;base=%d", 
+		        ch, base);
+    	        return (-1);
+        }
+    }
+
+    /* now parse the number itself */
+    while(i < len) {
+        ch = str[i++];
+        if(isspace(ch)) {
+	        continue;
+        }
+
+        xmlSecAssert2(ch <= sizeof(xmlSecBnLookupTable), -1);
+        nn = xmlSecBnLookupTable[ch];
+        if((nn < 0) || ((xmlSecSize)nn > base)) {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        NULL,
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        "char=%c;base=%d", 
+		        ch, base);
+    	        return (-1);
+        }
+
+        ret = xmlSecBnMul(bn, base);
+        if(ret < 0) {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecBnMul",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "base=%d", base);
+	        return (-1);
+        }
+
+        ret = xmlSecBnAdd(bn, nn);
+        if(ret < 0) {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecBnAdd",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "base=%d", base);
+	        return (-1);
+}	
+    }
+
+    /* check if we need to add 00 prefix, do this for empty bn too */
+    data = xmlSecBufferGetData(bn);
+    size = xmlSecBufferGetSize(bn);
+    if(((size > 0) && (data[0] > 127)) || (size == 0))  {
+        ch = 0;
+        ret = xmlSecBufferPrepend(bn, &ch, 1);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                NULL,
+                "xmlSecBufferPrepend",
+                XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                "base=%d", base);
+            return (-1);
+        }
+    }
+
+    /* do 2's compliment and add 1 to represent negative value */
+    if(positive == 0) {
+        data = xmlSecBufferGetData(bn);
+        size = xmlSecBufferGetSize(bn);
+        for(i = 0; i < size; ++i) {
+            data[i] ^= 0xFF;
+        }
+        
+        ret = xmlSecBnAdd(bn, 1);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                NULL,
+                "xmlSecBnAdd",
+                XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                "base=%d", base);
+            return (-1);
+        }
+    }
+
+    return(0);
+}
+
+/**
+ * xmlSecBnToString:
+ * @bn:		the pointer to BN.
+ * @base:	the base for returned string.
+ *
+ * Writes @bn to string with base @base. Caller is responsible for 
+ * freeing returned string with @xmlFree.
+ *
+ * Returns the string represenataion if BN or a NULL if an error occurs.
+ */
+EXPORT_C
+xmlChar* 
+xmlSecBnToString(xmlSecBnPtr bn, xmlSecSize base) {
+    xmlSecBn bn2;
+    int positive = 1;
+    xmlChar* res;
+    xmlSecSize i, len, size;
+    xmlSecByte* data;
+    int ret;
+    int nn;
+    xmlChar ch;
+
+    xmlSecAssert2(bn != NULL, NULL);
+    xmlSecAssert2(base > 1, NULL);
+    xmlSecAssert2(base <= sizeof(xmlSecBnRevLookupTable), NULL);
+
+
+    /* copy bn */
+    data = xmlSecBufferGetData(bn);
+    size = xmlSecBufferGetSize(bn);
+    ret = xmlSecBnInitialize(&bn2, size);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+            NULL,
+            "xmlSecBnCreate",
+            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+            "size=%d", size);
+        return (NULL);
+    }
+    
+    ret = xmlSecBnSetData(&bn2, data, size);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+            NULL,
+            "xmlSecBnSetData",
+            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+            "size=%d", size);
+        xmlSecBnFinalize(&bn2);
+        return (NULL);
+    }
+
+    /* check if it is a negative number or not */
+    data = xmlSecBufferGetData(&bn2);
+    size = xmlSecBufferGetSize(&bn2);
+    if((size > 0) && (data[0] > 127)) {
+        /* subtract 1 and do 2's compliment */
+        ret = xmlSecBnAdd(&bn2, -1);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecBnAdd",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "size=%d", size);
+            xmlSecBnFinalize(&bn2);
+            return (NULL);
+        }
+        for(i = 0; i < size; ++i) {
+            data[i] ^= 0xFF;
+        }
+
+        positive = 0;
+    } else {
+        positive = 1;
+    }
+
+    /* Result string len is
+     *	    len = log base (256) * <bn size>
+     * Since the smallest base == 2 then we can get away with 
+     *	    len = 8 * <bn size>
+     */
+    len = 8 * size + 1 + 1;
+    res = (xmlChar*)xmlMalloc(len + 1);
+    if(res == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+		            NULL,
+		            NULL,
+		            XMLSEC_ERRORS_R_MALLOC_FAILED,
+		            "len=%d", len);
+        xmlSecBnFinalize(&bn2);
+        return (NULL);
+    }
+    memset(res, 0, len + 1);
+
+    for(i = 0; (xmlSecBufferGetSize(&bn2) > 0) && (i < len); i++) {
+        if(xmlSecBnDiv(&bn2, base, &nn) < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecBnDiv",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "base=%d", base);
+            xmlFree(res);
+            xmlSecBnFinalize(&bn2);
+            return (NULL);
+        }
+        xmlSecAssert2((size_t)nn < sizeof(xmlSecBnRevLookupTable), NULL);
+        res[i] = xmlSecBnRevLookupTable[nn];
+    }
+    xmlSecAssert2(i < len, NULL);
+
+    /* we might have '0' at the beggining, remove it but keep one zero */
+    for(len = i; (len > 1) && (res[len - 1] == '0'); len--)
+        {
+        };
+    res[len] = '\0';
+
+    /* add "-" for negative numbers */
+    if(positive == 0) {
+        res[len] = '-';
+        res[++len] = '\0';
+    }
+
+    /* swap the string because we wrote it in reverse order */
+    for(i = 0; i < len / 2; i++) {
+        ch = res[i];
+        res[i] = res[len - i - 1];
+        res[len - i - 1] = ch;
+    }
+
+    xmlSecBnFinalize(&bn2);
+    return(res);
+}
+
+/**
+ * xmlSecBnFromHexString:
+ * @bn:		the pointer to BN.
+ * @str:	the string with BN.
+ *
+ * Reads @bn from hex string @str.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnFromHexString(xmlSecBnPtr bn, const xmlChar* str) {
+    return(xmlSecBnFromString(bn, str, 16));
+}
+
+/**
+ * xmlSecBnToHexString:
+ * @bn:		the pointer to BN.
+ *
+ * Writes @bn to hex string. Caller is responsible for 
+ * freeing returned string with @xmlFree.
+ *
+ * Returns the string represenataion if BN or a NULL if an error occurs.
+ */
+EXPORT_C
+xmlChar* 
+xmlSecBnToHexString(xmlSecBnPtr bn) {
+    return(xmlSecBnToString(bn, 16));
+}
+
+/**
+ * xmlSecBnFromDecString:
+ * @bn:		the pointer to BN.
+ * @str:	the string with BN.
+ *
+ * Reads @bn from decimal string @str.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnFromDecString(xmlSecBnPtr bn, const xmlChar* str) {
+    return(xmlSecBnFromString(bn, str, 10));
+}
+
+/**
+ * xmlSecBnToDecString:
+ * @bn:		the pointer to BN.
+ *
+ * Writes @bn to decimal string. Caller is responsible for 
+ * freeing returned string with @xmlFree.
+ *
+ * Returns the string represenataion if BN or a NULL if an error occurs.
+ */
+EXPORT_C
+xmlChar* 
+xmlSecBnToDecString(xmlSecBnPtr bn) {
+    return(xmlSecBnToString(bn, 10));
+}
+
+/**
+ * xmlSecBnMul:
+ * @bn:			the pointer to BN.
+ * @multiplier:		the multiplier.
+ *
+ * Multiplies @bn with @multiplier.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnMul(xmlSecBnPtr bn, int multiplier) {
+    xmlSecByte* data;
+    int over;
+    xmlSecSize i;
+    xmlSecByte ch;
+    int ret;
+
+    xmlSecAssert2(bn != NULL, -1);
+    xmlSecAssert2(multiplier > 0, -1);
+
+    if(multiplier == 1) {
+	return(0);
+    }
+
+    data = xmlSecBufferGetData(bn);
+    i = xmlSecBufferGetSize(bn);
+    over = 0; 
+    while(i > 0) {
+	xmlSecAssert2(data != NULL, -1);
+
+	over	= over + multiplier * data[--i];
+	data[i]	= over % 256;
+	over	= over / 256;
+    }
+    
+    while(over > 0) {
+	ch	= over % 256;
+	over	= over / 256;
+	
+	ret = xmlSecBufferPrepend(bn, &ch, 1);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBufferPrepend",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"size=1");
+	    return (-1);
+	}
+    }
+    
+    return(0);
+}
+
+/**
+ * xmlSecBnDiv:
+ * @bn:		the pointer to BN.
+ * @divider:	the divider
+ * @mod:	the pointer for modulus result.
+ *
+ * Divides @bn by @divider and places modulus into @mod.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnDiv(xmlSecBnPtr bn, int divider, int* mod) {
+    int over;
+    xmlSecSize i, size;
+    xmlSecByte* data;
+    int ret;
+
+    xmlSecAssert2(bn != NULL, -1);
+    xmlSecAssert2(divider > 0, -1);
+    xmlSecAssert2(mod != NULL, -1);
+
+    if(divider == 1) {
+	return(0);
+    }
+
+    data = xmlSecBufferGetData(bn);
+    size = xmlSecBufferGetSize(bn);
+    for(over = 0, i = 0; i < size; i++) {
+	xmlSecAssert2(data != NULL, -1);
+
+	over	= over * 256 + data[i];
+	data[i]	= over / divider;
+	over	= over % divider;
+    }
+    (*mod) = over;
+    
+    /* remove leading zeros */
+    for(i = 0; i < size; i++) {
+	xmlSecAssert2(data != NULL, -1);
+
+	if(data[i] != 0) {
+	    break;
+	}
+    }
+    if(i > 0) {
+	ret = xmlSecBufferRemoveHead(bn, i);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBufferRemoveHead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"size=%d", i);
+	    return (-1);
+	}
+    }
+    return(0);
+}
+
+/**
+ * xmlSecBnAdd:
+ * @bn:		the pointer to BN.
+ * @delta:	the delta.
+ *
+ * Adds @delta to @bn.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnAdd(xmlSecBnPtr bn, int delta) {
+    int over, tmp;
+    xmlSecByte* data;
+    xmlSecSize i;
+    xmlSecByte ch;
+    int ret;
+
+    xmlSecAssert2(bn != NULL, -1);
+
+    if(delta == 0) {
+    	return(0);
+    }
+
+    data = xmlSecBufferGetData(bn);
+    if(delta > 0) {
+        for(over = delta, i = xmlSecBufferGetSize(bn); (i > 0) && (over > 0) ;) {
+	        xmlSecAssert2(data != NULL, -1);
+	
+            tmp     = data[--i];
+        	over   += tmp;
+	        data[i]	= over % 256;
+	        over	= over / 256;
+        }
+    
+        while(over > 0) {
+	        ch	= over % 256;
+	        over	= over / 256;
+	
+        	ret = xmlSecBufferPrepend(bn, &ch, 1);
+	        if(ret < 0) {
+	            xmlSecError(XMLSEC_ERRORS_HERE,
+			        NULL,
+			        "xmlSecBufferPrepend",
+			        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			        "size=1");
+	            return (-1);
+	        }
+        }
+    } else {
+        for(over = -delta, i = xmlSecBufferGetSize(bn); (i > 0) && (over > 0);) {
+	        xmlSecAssert2(data != NULL, -1);
+	
+            tmp     = data[--i];
+            if(tmp < over) {
+                data[i]	= 0;
+                over = (over - tmp) / 256;
+            } else {
+                data[i] = tmp - over;
+                over = 0;
+            }
+        }
+    }
+    return(0);
+}
+
+/**
+ * xmlSecBnReverse:
+ * @bn:		the pointer to BN.
+ *
+ * Reverses bytes order in @bn.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnReverse(xmlSecBnPtr bn) {
+    xmlSecByte* data;
+    xmlSecSize i, j, size;
+    xmlSecByte ch;
+
+    xmlSecAssert2(bn != NULL, -1);
+
+    data = xmlSecBufferGetData(bn);
+    size = xmlSecBufferGetSize(bn);
+    for(i = 0, j = size - 1; i < size / 2; ++i, --j) {
+	xmlSecAssert2(data != NULL, -1);
+
+	ch	 = data[i];
+	data[i]	 = data[j];
+	data[j]  = ch;
+    }    
+
+    return(0);
+}
+
+/**
+ * xmlSecBnCompare:
+ * @bn:		the pointer to BN.
+ * @data:	the data to compare BN to.
+ * @dataSize:	the @data size.
+ *
+ * Compares the @bn with @data.
+ *
+ * Returns 0 if data is equal, negative value if @bn is less or positive value if @bn
+ * is greater than @data.
+ */
+EXPORT_C
+int 
+xmlSecBnCompare(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize dataSize) {
+    xmlSecByte* bnData;
+    xmlSecSize bnSize;
+
+    xmlSecAssert2(bn != NULL, -1);
+
+    bnData = xmlSecBnGetData(bn);
+    bnSize = xmlSecBnGetSize(bn);
+
+    /* skip zeros in the beggining */
+    while((dataSize > 0) && (data != 0) && (data[0] == 0)) {
+	++data;
+	--dataSize;
+    }
+    while((bnSize > 0) && (bnData != 0) && (bnData[0] == 0)) {
+	++bnData;
+	--bnSize;
+    }
+
+    if(((bnData == NULL) || (bnSize == 0)) && ((data == NULL) || (dataSize == 0))) {
+	return(0);
+    } else if((bnData == NULL) || (bnSize == 0)) {
+	return(-1);
+    } else if((data == NULL) || (dataSize == 0)) {
+	return(1);
+    } else if(bnSize < dataSize) {
+	return(-1);
+    } else if(bnSize > dataSize) {
+	return(-1);
+    } 
+
+    xmlSecAssert2(bnData != NULL, -1);
+    xmlSecAssert2(data != NULL, -1);
+    xmlSecAssert2(bnSize == dataSize, -1);
+
+    return(memcmp(bnData, data, dataSize));
+}
+
+/**
+ * xmlSecBnCompareReverse:
+ * @bn:		the pointer to BN.
+ * @data:	the data to compare BN to.
+ * @dataSize:	the @data size.
+ *
+ * Compares the @bn with reverse @data.
+ *
+ * Returns 0 if data is equal, negative value if @bn is less or positive value if @bn
+ * is greater than @data.
+ */
+EXPORT_C
+int 
+xmlSecBnCompareReverse(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize dataSize) {
+    xmlSecByte* bnData;
+    xmlSecSize bnSize;
+    xmlSecSize i, j;
+
+    xmlSecAssert2(bn != NULL, -1);
+
+    bnData = xmlSecBnGetData(bn);
+    bnSize = xmlSecBnGetSize(bn);
+
+    /* skip zeros in the beggining */
+    while((dataSize > 0) && (data != 0) && (data[dataSize - 1] == 0)) {
+	--dataSize;
+    }
+    while((bnSize > 0) && (bnData != 0) && (bnData[0] == 0)) {
+	++bnData;
+	--bnSize;
+    }
+
+    if(((bnData == NULL) || (bnSize == 0)) && ((data == NULL) || (dataSize == 0))) {
+	return(0);
+    } else if((bnData == NULL) || (bnSize == 0)) {
+	return(-1);
+    } else if((data == NULL) || (dataSize == 0)) {
+	return(1);
+    } else if(bnSize < dataSize) {
+	return(-1);
+    } else if(bnSize > dataSize) {
+	return(-1);
+    } 
+
+    xmlSecAssert2(bnData != NULL, -1);
+    xmlSecAssert2(data != NULL, -1);
+    xmlSecAssert2(bnSize == dataSize, -1);
+    for(i = 0, j = dataSize - 1; i < dataSize; ++i, --j) {
+	if(bnData[i] < data[j]) {
+	    return(-1);
+	} else if(data[j] < bnData[i]) {
+	    return(1);
+	}
+    }
+
+    return(0);
+}
+
+/**
+ * xmlSecBnGetNodeValue:
+ * @bn:		the pointer to BN.
+ * @cur:	the poitner to an XML node.
+ * @format:	the BN format.
+ * @reverse:	if set then reverse read buffer after reading.
+ *
+ * Converts the node content from @format to @bn.
+ *
+ * Returns 0 on success and a negative values if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecBnGetNodeValue(xmlSecBnPtr bn, xmlNodePtr cur, xmlSecBnFormat format, int reverse) {
+    xmlChar* content;
+    int ret;
+
+    xmlSecAssert2(bn != NULL, -1);
+    xmlSecAssert2(cur != NULL, -1);
+
+    switch(format) {
+    case xmlSecBnBase64:
+	ret = xmlSecBufferBase64NodeContentRead(bn, cur);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBufferBase64NodeContentRead",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	break;
+    case xmlSecBnHex:
+	content = xmlNodeGetContent(cur);
+	if(content == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlNodeGetContent",
+	    		XMLSEC_ERRORS_R_XML_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	ret = xmlSecBnFromHexString(bn, content);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBnFromHexString",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlFree(content);
+	    return(-1);
+	}
+	xmlFree(content);
+	break;
+    case xmlSecBnDec:
+	content = xmlNodeGetContent(cur);
+	if(content == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlNodeGetContent",
+	    		XMLSEC_ERRORS_R_XML_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	ret = xmlSecBnFromDecString(bn, content);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBnFromDecString",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlFree(content);
+	    return(-1);
+	}
+	xmlFree(content);
+	break;
+    }
+
+    if(reverse != 0) {
+    	ret = xmlSecBnReverse(bn);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBnReverse",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    }
+    return(0);
+}
+
+/**
+ * xmlSecBnSetNodeValue:
+ * @bn:			the pointer to BN.
+ * @cur:		the poitner to an XML node.
+ * @format:		the BN format.
+ * @reverse:		the flag that indicates whether to reverse the buffer before writing.
+ * @addLineBreaks:  	the flag; it is equal to 1 then linebreaks will be added before and after new buffer content.
+ *
+ * Converts the @bn and sets it to node content.
+ *
+ * Returns 0 on success and a negative values if an error occurs.
+ */
+EXPORT_C
+int  
+xmlSecBnSetNodeValue(xmlSecBnPtr bn, xmlNodePtr cur, xmlSecBnFormat format, int reverse, int addLineBreaks) {
+    xmlChar* content;
+    int ret;
+
+    xmlSecAssert2(bn != NULL, -1);
+    xmlSecAssert2(cur != NULL, -1);
+
+    if(reverse != 0) {
+    	ret = xmlSecBnReverse(bn);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBnReverse",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    }
+
+    if(addLineBreaks) {
+	xmlNodeAddContent(cur, xmlSecStringCR);
+    }
+
+    switch(format) {
+    case xmlSecBnBase64:
+	ret = xmlSecBufferBase64NodeContentWrite(bn, cur, XMLSEC_BASE64_LINESIZE);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBufferBase64NodeContentWrite",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	break;
+    case xmlSecBnHex:
+	content = xmlSecBnToHexString(bn);
+	if(content == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBnToHexString",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlFree(content);
+	    return(-1);
+	}
+	xmlNodeSetContent(cur, content);
+	xmlFree(content);
+	break;
+    case xmlSecBnDec:
+	content = xmlSecBnToDecString(bn);
+	if(content == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecBnToDecString",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlFree(content);
+	    return(-1);
+	}
+	xmlNodeSetContent(cur, content);
+	xmlFree(content);
+	break;
+    }
+
+    if(addLineBreaks) {
+	xmlNodeAddContent(cur, xmlSecStringCR);
+    }
+
+    return(0);
+}
+
+/**
+ * xmlSecBnBlobSetNodeValue:
+ * @data:	the pointer to BN blob.
+ * @dataSize:	the size of BN blob.
+ * @cur:	the poitner to an XML node.
+ * @format:	the BN format.
+ * @reverse:	the flag that indicates whether to reverse the buffer before writing.
+ * @addLineBreaks:  if the flag is equal to 1 then 
+ *		linebreaks will be added before and after
+ *		new buffer content.
+ *
+ * Converts the @blob and sets it to node content.
+ *
+ * Returns 0 on success and a negative values if an error occurs.
+ */
+EXPORT_C
+int  
+xmlSecBnBlobSetNodeValue(const xmlSecByte* data, xmlSecSize dataSize, 
+			 xmlNodePtr cur, xmlSecBnFormat format, int reverse,
+			 int addLineBreaks) {
+    xmlSecBn bn;
+    int ret;
+
+    xmlSecAssert2(data != NULL, -1);
+    xmlSecAssert2(cur != NULL, -1);
+
+    ret = xmlSecBnInitialize(&bn, dataSize);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBnInitialize",
+	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    ret = xmlSecBnSetData(&bn, data, dataSize);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBnSetData",
+	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecBnFinalize(&bn);
+	return(-1);
+    }
+
+    ret = xmlSecBnSetNodeValue(&bn, cur, format, reverse, addLineBreaks);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBnSetNodeValue",
+	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecBnFinalize(&bn);
+	return(-1);
+    }
+
+    xmlSecBnFinalize(&bn);
+    return(0);
+}
+
+