diff options
Diffstat (limited to 'docs/api/src/chapters/new-crypto.sgml')
-rw-r--r-- | docs/api/src/chapters/new-crypto.sgml | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/docs/api/src/chapters/new-crypto.sgml b/docs/api/src/chapters/new-crypto.sgml new file mode 100644 index 00000000..35cbd145 --- /dev/null +++ b/docs/api/src/chapters/new-crypto.sgml @@ -0,0 +1,462 @@ +<chapter id="xmlsec-notes-new-crypto"> + <title>Adding support for new cryptographic library.</title> + <sect1 id="xmlsec-notes-new-crypto-overview"> + <title>Overview.</title> + <para>XML Security Library can support practicaly any cryptographic + library. Currently, it has "out-of-the-box" support for OpenSSL, + MSCrypto, NSS, GnuTLS and GCrypt. If your favorite library is not supported yet then + you can write necessary code yourself. If you and your company + (university, ...) are willing to share the results of your work I would + be happy to add support for new libraries to the main XML Security + Library distribution.</para> + <para> + The XML Security Library + <link linkend="xmlsec-notes-structure">separates</link> + the cryptographic library (engine) + specific code in an "xmlsec-<crypto>" library (where "<crypto>" is + "openssl", "mscrypt", "gnutls", "gcrypt", "nss", etc.) which includes following items: + <itemizedlist> + <listitem><para> + xmlSecCryptoApp* functions. + </para></listitem> + <listitem><para> + Cryptographic transforms and keys data implementation. + </para></listitem> + <listitem><para> + Keys store support (X509, PGP, etc.). + </para></listitem> + </itemizedlist> + In this chapter, we will discuss + a task of creating "xmlsec-mycrypto" library that provides support + for your favorite "MyCrypto" cryptographic library. + </para> + </sect1> + <sect1 id="xmlsec-notes-new-crypto-skeleton"> + <title>Creating a framework from the skeleton.</title> + <para> + The XML Security Library contains a "skeleton" for creating new + "xmlsec-<crypto>" libraries. In order to create "xmlsec-mycrypto" + library framework, do the following (this example assumes that you + are using *nix system, adjust the commands if you are using something else): + <itemizedlist> + <listitem><para> + Copy src/skeleton and include/xmlsec/skeleton folders to src/mycrypto and + include/xmlsec/mycrypto folders: + <example> + <title>Coping skeleton folders:</title> + <programlisting><![CDATA[ +cp -r src/skeleton src/mycrypto +cp -r include/xmlsec/skeleton include/xmlsec/mycrypto + ]]></programlisting> + </example> + </para></listitem> + <listitem><para> + Replace "skeleton" with "mycrypto" in the copied files (note that there + are different possible cases here): + <example> + <title>Replacing "skeleton" with "mycrypto".</title> + <programlisting><![CDATA[ +for i in `ls include/xmlsec/mycrypto/* src/mycrypto/*`; do + echo Processing $i ..; + sed 's/skeleton/mycrypto/g' $i | \ + sed 's/SKELETON/MYCRYPTO/g' | \ + sed 's/Skeleton/MyCrypto/g' > $i.tmp; + mv $i.tmp $i; +done + ]]></programlisting> + </example> + </para></listitem> + <listitem><para> + Add "xmlsec-mycrypto" library to the "include/xmlsec/crypto.h" file: + <example> + <title>Modifying include/xmlsec/crypto.h file.</title> + <programlisting><![CDATA[ +... +#ifdef XMLSEC_CRYPTO_MYCRYPTO +#include <xmlsec/mycrypto/app.h> +#include <xmlsec/mycrypto/crypto.h> +#include <xmlsec/mycrypto/symbols.h> +#else /* XMLSEC_CRYPTO_MYCRYPTO */ +... +#endif /* XMLSEC_CRYPTO_MYCRYPTO */ +... + ]]></programlisting> + </example> + </para></listitem> + <listitem><para> + Add "xmlsec-crypto" library to the configure.in file (for *nix systems; + for Windows you need to modify win32/confgure.js and win32/Makefile.msvc + files, see win32/README.txt for details): + <example> + <title>Modifying configure.in file.</title> + <programlisting><![CDATA[ +dnl ========================================================================== +dnl See if we can find MyCrypto +dnl ========================================================================== +XMLSEC_MYCRYPTO_DEFINES="" +MYCRYPTO_CONFIG="mycrypto-config" # TODO +XMLSEC_NO_MYCRYPTO="1" +MYCRYPTO_MIN_VERSION="0.0.0" # TODO +MYCRYPTO_VERSION="" +MYCRYPTO_PREFIX="" +MYCRYPTO_CFLAGS="" +MYCRYPTO_LIBS="" +MYCRYPTO_LDADDS="" +AC_MSG_CHECKING(for mycrypto libraries >= $MYCRYPTO_MIN_VERSION) +AC_ARG_WITH(mycrypto, [ --with-mycrypto=[PFX] mycrypto location]) +if test "$with_mycrypto" = "no" ; then + XMLSEC_CRYPTO_DISABLED_LIST="$XMLSEC_CRYPTO_DISABLED_LIST mycrypto" + AC_MSG_RESULT(no) +else + if test "$with_mycrypto" != "" ; then + MYCRYPTO_PREFIX=$with_mycrypto + MYCRYPTO_CONFIG=$MYCRYPTO_PREFIX/bin/$MYCRYPTO_CONFIG + fi + if ! $MYCRYPTO_CONFIG --version > /dev/null 2>&1 ; then + if test "$with_mycrypto" != "" ; then + AC_MSG_ERROR(Unable to find mycrypto at '$with_mycrypto') + fi + else + vers=`$MYCRYPTO_CONFIG --version | awk -F. '{ printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'` + minvers=`echo $MYCRYPTO_MIN_VERSION | awk -F. '{ printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'` + if test "$vers" -ge "$minvers" ; then + MYCRYPTO_LIBS="`$MYCRYPTO_CONFIG --libs`" + MYCRYPTO_CFLAGS="`$MYCRYPTO_CONFIG --cflags`" + MYCRYPTO_VERSION="`$MYCRYPTO_CONFIG --version`" + XMLSEC_NO_MYCRYPTO="0" + else + AC_MSG_ERROR(You need at least mycrypto $MYCRYPTO_MIN_VERSION for this version of $PACKAGE) + fi + fi + + dnl update crypt libraries list + if test "z$XMLSEC_NO_MYCRYPTO" = "z0" ; then + dnl first crypto library is default one + if test "z$XMLSEC_CRYPTO" = "z" ; then + XMLSEC_CRYPTO="mycrypto" + XMLSEC_CRYPTO_LIB="xmlsec1-mycrypto" + XMLSEC_CRYPTO_CFLAGS="$MYCRYPTO_CFLAGS -DXMLSEC_CRYPTO_MYCRYPTO=1" + XMLSEC_CRYPTO_LIBS="$MYCRYPTO_LIBS" + XMLSEC_CRYPTO_LDADDS="$MYCRYPTO_LDADDS" + fi + XMLSEC_CRYPTO_LIST="$XMLSEC_CRYPTO_LIST mycrypto" + AC_MSG_RESULT(yes ('$MYCRYPTO_VERSION')) + else + XMLSEC_CRYPTO_DISABLED_LIST="$XMLSEC_CRYPTO_DISABLED_LIST mycrypto" + AC_MSG_RESULT(no) + fi +fi +AC_SUBST(XMLSEC_NO_MYCRYPTO) +AC_SUBST(MYCRYPTO_MIN_VERSION) +AC_SUBST(MYCRYPTO_VERSION) +AC_SUBST(MYCRYPTO_CONFIG) +AC_SUBST(MYCRYPTO_PREFIX) +AC_SUBST(MYCRYPTO_CFLAGS) +AC_SUBST(MYCRYPTO_LIBS) +AC_SUBST(MYCRYPTO_LDADDS) +AC_SUBST(XMLSEC_MYCRYPTO_DEFINES) + +... +AC_OUTPUT([ +... +include/xmlsec/mycrypto/Makefile +src/mycrypto/Makefile +... +]) + ]]></programlisting> + </example> + </para></listitem> + <listitem><para>Modify "xmlsec.spec.in" file to create "xmlsec-mycrypto" + RPM (if necessary). + </para></listitem> + </itemizedlist> + + By now you should be able to sucessfuly compile XML Security Library + with MyCrypto library (we disable all other libraries to make sure + that xmlsec command line utility is linked against xmlsec-mycrypto + library): + <example> + <title>Compiling the results.</title> + <programlisting><![CDATA[ +./autogen.sh --without-openssl --without-nss --without-gnutls --without-gcrypt \ + --with-mycrypto=$HOME --disable-tmpl-tests +make + ]]></programlisting> + </example> + </para> + </sect1> + <sect1 id="xmlsec-notes-new-crypto-functions"> + <title>xmlSecCryptoApp* functions.</title> + <para> + The XML Security Library allows application to load multiple + "xmlsec-<crypto> libraries. To prevent symbol conflicts, + all "xmlsec-mycrypto" library names MUST start with "xmlSecMyCrypto". + However, in some applications (for example, the xmlsec command line + utility) that can use any crypto library, would prefer to + use a generic function names where possible. + The "include/xmlsec/crypto.h" and "include/xmlsec/mycrypto/symbols.h" + include files do the magic by mapping "xmlSecMyCrypto*" to + "xmlSecCrypto*" names using "XMLSEC_CRYPTO_*" defines. + </para> + <para> + In order to build xmlsec command line utility, the + "xmlsec-<crypto>" library must implement several functions. + The stubs for all these functions are provided in the "skeleton" + we've created. While these functions are not required to be + implemented by "xmlsec-<crypto>" library, you should consider + doing so (if possible) to simplify testing (thru xmlsec command line + utility) and application development. + </para> + <para> + In adition to xmlSecCryptoApp* functions, the xmlsec-<crypto> + library MUST implement following xmlSecCrypto* functions: + <table> + <title>xmlSecCrypto* functions.</title> + <tgroup cols="2"><tbody> + <row><entry>xmlSecCryptoInit()</entry> + <entry>Initializes xmlsec-<crypto> library: registers cryptographic + transforms implemented by the library, keys, etc. + Please note, that the application might want to intialize + the cryprographic library by itself. The default cryprographic + library initialization (for example, used by xmlsec utility) + is implemented in xmlSecCryptoAppInit() function. + </entry></row> + <row><entry>xmlSecCryptoShutdown()</entry> + <entry>Shuts down xmlsec-<crypto> library. + Please note, that the application might want to shutdown + the cryprographic library by itself. The default cryprographic + library shutdown (for example, used by xmlsec utility) + is implemented in xmlSecCryptoAppShutdown() function. + </entry></row> + <row><entry>xmlSecCryptoKeysMngrInit()</entry> + <entry>Adds keys stores implemented by the xmlsec-<crypto> library + to the keys manager object. + </entry></row> + </tbody></tgroup></table> + </para> + </sect1> + <sect1 id="xmlsec-notes-new-crypto-klasses"> + <title>Klasses and objects.</title> + <para>The XML Security Library is written in C but it uses some OOP techniques: + the objects in the library have "klasses" and there is "klasses" inheritance. + (see <link linkend="xmlsec-signature-klasses">signature</link> and + <link linkend="xmlsec-encryption-klasses">encryption</link> klasses + diagrams). The "klass" is different from C++ "class" (btw, this is + one of the reasons why it is spelled differently). The idea of "klasses" + used in XML Security Library are close to one in the GLIB/GTK/GNOME + and many other C projects. If you ever seen an OOP code written in C + you should find everything familiar. + </para> + <para>XML Security Library "klass" includes three main parts: + <itemizedlist> + <listitem><para>"Klass" declaration structure that defines "klass" interfaces + and global constant data (for example, the human-readable name of + the "klass"). + <example> + <title>Base transform "klass" and its child XPath transform "klass" structure.</title> + <programlisting><![CDATA[ +struct _xmlSecTransformKlass { + /* data */ + size_t klassSize; + size_t objSize; + const xmlChar* name; + const xmlChar* href; + xmlSecTransformUsage usage; + + /* methods */ + xmlSecTransformInitializeMethod initialize; + xmlSecTransformFinalizeMethod finalize; + + xmlSecTransformNodeReadMethod readNode; + xmlSecTransformNodeWriteMethod writeNode; + + ... +}; + +... + +static xmlSecTransformKlass xmlSecTransformXPathKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* size_t klassSize */ + xmlSecXPathTransformSize, /* size_t objSize */ + + xmlSecNameXPath, /* const xmlChar* name; */ + xmlSecXPathNs, /* const xmlChar* href; */ + xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */ + + xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecTransformXPathNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + + ... +}; + ]]></programlisting> + </example> + </para></listitem> + + <listitem><para>"Klass" id which is simply a pointer to the "klass" + declaration strucutre. "Klass" id is used to bind "klass" objects + to the "klass" declaration and to pass "klass" strucutre to functions. + <example> + <title>Base transform "klass" id declaration and its child XPath transform "klass" id implementation.</title> + <programlisting><![CDATA[ +typedef const struct _xmlSecTransformKlass xmlSecTransformKlass, *xmlSecTransformId; + +... + +#define xmlSecTransformXPathId xmlSecTransformXPathGetKlass() + +... + +xmlSecTransformId +xmlSecTransformXPathGetKlass(void) { + return(&xmlSecTransformXPathKlass); +} + ]]></programlisting> + </example> + </para></listitem> + + <listitem><para>"Klass" object structure that contains object specific + data. The child object specific data are placed after the parent "klass" + object data. + <example> + <title>Base transform object strucutre and its child XPath transform object.</title> + <programlisting><![CDATA[ +struct _xmlSecTransform { + xmlSecTransformId id; + xmlSecTransformOperation operation; + xmlSecTransformStatus status; + xmlNodePtr hereNode; + + /* transforms chain */ + xmlSecTransformPtr next; + xmlSecTransformPtr prev; + + ... +}; + +... + +/****************************************************************************** + * + * XPath/XPointer transforms + * + * xmlSecPtrList with XPath expressions is located after xmlSecTransform structure + * + *****************************************************************************/ +#define xmlSecXPathTransformSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecPtrList)) +#define xmlSecXPathTransformGetDataList(transform) \ + ((xmlSecTransformCheckSize((transform), xmlSecXPathTransformSize)) ? \ + (xmlSecPtrListPtr)(((unsigned char*)(transform)) + sizeof(xmlSecTransform)) : \ + (xmlSecPtrListPtr)NULL) + ]]></programlisting> + </example> + </para></listitem> + </itemizedlist> + </para> + </sect1> + <sect1 id="xmlsec-notes-new-crypto-transforms"> + <title>Cryptographic transforms.</title> + <para>The cryptographic transforms (digests, signatures and encryption) + implementation is the main goal of "xmlsec-<crypto>" library. + Most of the cryptographic <link linkend="xmlsec-notes-transforms">transforms</link> + use default <structfield>pushBin</structfield> and <structfield>popBin</structfield> + methods and provide custom <link linkend="xmlSecTransformExecuteMethod">execute</link> method. + The binary transform <link linkend="xmlSecTransformExecuteMethod">execute</link> method + processes data from the input buffer + <structfield>inBuf</structfield> and pushes results to + <structfield>outBuf</structfield>. The transform should try to + consume and remove data from <structfield>inBuf</structfield> buffer + as soon as the data became available. However, it might happen + that current data size in the input buffer is not enough (for example, + RSA-PKCS1 algorithm requires that all the data are available in + one buffer). In this case, transform might keep the data in the + input buffer till the next call to + <link linkend="xmlSecTransformExecuteMethod">execute</link> + method. The "last" parameter of the + <link linkend="xmlSecTransformExecuteMethod">execute</link> + indicates that transform MUST process all the data in the input buffer + and return as much as possible in the output buffer. The + <link linkend="xmlSecTransformExecuteMethod">execute</link> method + might be called multiple times with non-zero "last" parameter until + the transforms returns nothing + in the output buffer. In addition, the transform implementation is + responsible for managing the transform <structfield>status</structfield> + variable. + <table> + <title>Typical transform status managing.</title> + <tgroup cols="2"><tbody> + <row><entry>xmlSecTransformStatusNone</entry> + <entry>Transform initializes itself (for example, cipher transform + generates or reads IV) and sets <structfield>status</structfield> + variable to xmlSecTransformStatusWorking.</entry></row> + <row><entry>xmlSecTransformStatusWorking</entry> + <entry>Transform process the next (if "last" parameter is zero) or + last block of data (if "last" parameter is non-zero). + When transform returns all the data, it sets the + <structfield>status</structfield> variable to + xmlSecTransformStatusFinished.</entry></row> + <row><entry>xmlSecTransformStatusFinished</entry> + <entry>Transform returns no data to indicate that it finished + processing.</entry></row> + </tbody></tgroup></table> + </para> + <para>In adition to <link linkend="xmlSecTransformExecuteMethod">execute</link> + methods, signature, hmac or digest transforms + MUST implement <link linkend="xmlSecTransformVerifyMethod">verify</link> method. + The <link linkend="xmlSecTransformVerifyMethod">verify</link> method is called + after transform execution is finished. The + <link linkend="xmlSecTransformVerifyMethod">verify</link> method implementation + must set the "status" member to <link linkend="xmlSecTransformStatusOk">xmlSecTransformStatusOk</link> + if signature, hmac or digest is successfuly verified or to + <link linkend="xmlSecTransformStatusFail">xmlSecTransformStatusFail</link> + otherwise. + </para> + <para>The transforms that require a key (signature or encryption + transforms, for example) MUST imlpement + <link linkend="xmlSecTransformSetKeyRequirementsMethod">setKeyReq</link> + (prepares the <link linkend="xmlSecKeyReq">key requirements</link> + for key search) and + <link linkend="xmlSecTransformSetKeyMethod">setKey</link> + (sets the key in the transform) methods. + </para> + </sect1> + <sect1 id="xmlsec-notes-new-crypto-keys"> + <title>Keys data and keys data stores.</title> + <para> + There are two key data types: key value data (for example, AES, DES, DSA, + HMAC or RSA key data) and others (for example, key name, X509 or PGP data). + The key data implementation should implement at least one of + <link linkend="xmlSecKeyDataXmlReadMethod">xmlRead</link> + or <link linkend="xmlSecKeyDataBinReadMethod">binRead</link> methods. + </para> + <para>TODO</para> + </sect1> + <sect1 id="xmlsec-notes-new-crypto-simple-keys-mngr"> + <title>Default keys manager.</title> + <para>Any "xmlsec-<crypto>" library implementation must provide + a default keys store. The XML Security Library has a built-in flat + list based <link linkend="xmlSecSimpleKeysStoreId">simple keys + store</link> which could be used if cryptographic library does not + have one itself. + </para> + </sect1> + <sect1 id="xmlsec-notes-new-crypto-sharing-results"> + <title>Sharing the results.</title> + <para>If you implemented support for new cryptographic library + (or extended an existing one) and both you and your company/university/... + are willing to share the code I would be glad to add your work + to XML Security Library. Many people will thank you for this + and will use your library. Of course, you'll get all the credits + for your work. + </para> + <para>The best way to submit your enchancements is to send a pull request + through <ulink URL="https://github.com/lsh123/xmlsec">GitHub</ulink>. + I will try to review and merge your pool request as soon as possible. + </para> + </sect1> +</chapter> + + |