diff options
Diffstat (limited to 'docs/api/src')
-rw-r--r-- | docs/api/src/chapters/compiling-and-linking.sgml | 252 | ||||
-rw-r--r-- | docs/api/src/chapters/creating-templates.sgml | 325 | ||||
-rw-r--r-- | docs/api/src/chapters/examples.sgml | 102 | ||||
-rw-r--r-- | docs/api/src/chapters/init-and-shutdown.sgml | 104 | ||||
-rw-r--r-- | docs/api/src/chapters/new-crypto.sgml | 462 | ||||
-rw-r--r-- | docs/api/src/chapters/sign-and-encrypt.sgml | 286 | ||||
-rw-r--r-- | docs/api/src/chapters/using-contexts.sgml | 138 | ||||
-rw-r--r-- | docs/api/src/chapters/using-keys.sgml | 26 | ||||
-rw-r--r-- | docs/api/src/chapters/using-keysmngr.sgml | 592 | ||||
-rw-r--r-- | docs/api/src/chapters/using-transforms.sgml | 67 | ||||
-rw-r--r-- | docs/api/src/chapters/using-x509-certs.sgml | 197 | ||||
-rw-r--r-- | docs/api/src/chapters/verify-and-decrypt.sgml | 265 | ||||
-rw-r--r-- | docs/api/src/xmlsec.sgml | 307 |
13 files changed, 3123 insertions, 0 deletions
diff --git a/docs/api/src/chapters/compiling-and-linking.sgml b/docs/api/src/chapters/compiling-and-linking.sgml new file mode 100644 index 00000000..f184c6a4 --- /dev/null +++ b/docs/api/src/chapters/compiling-and-linking.sgml @@ -0,0 +1,252 @@ +<chapter id="xmlsec-notes-compiling"> + <title>Building the application with XML Security Library.</title> + <sect1 id="xmlsec-notes-compiling-overview"> + <title>Overview.</title> + <para>Compiling and linking application with XML Security + Library requires specifying correct compilation flags, library files + and paths to include and library files. As we discussed before, + XML Security Library consist of the core xmlsec library and several + xmlsec-crypto libraries. Application has a choice of selecting crypto + library at link time or dynamicaly loading it at run time. Please note, + that loading crypto engines dynamicaly may introduce security problems + on some platforms. + </para> + </sect1> + <sect1 id="xmlsec-notes-include-files" > + <title>Include files.</title> + <para>In order to use XML Security Library an application should include + one or more of the following files: + <itemizedlist> + <listitem> + <para><link linkend="XMLSEC-XMLSEC">xmlsec/xmlsec.h</link> - + XML Security Library initialization and shutdown functions; + </para> + </listitem> + <listitem> + <para><link linkend="XMLSEC-XMLDSIG">xmlsec/xmldsig.h</link> - + XML Digital Signature functions;</para> + </listitem> + <listitem> + <para><link linkend="XMLSEC-XMLENC">xmlsec/xmlenc.h</link> - + XML Encryption functions;</para> + </listitem> + <listitem> + <para><link linkend="XMLSEC-XMLTREE">xmlsec/xmltree.h</link> - + helper functions for XML documents manipulation; + </para> + </listitem> + <listitem> + <para><link linkend="XMLSEC-TEMPLATES">xmlsec/templates.h</link> - + helper functions for dynamic XML Digital Signature and + XML Encryption templates creation; + </para> + </listitem> + <listitem> + <para><link linkend="XMLSEC-CRYPTO">xmlsec/crypto.h</link> - + automatic XML Security Crypto Library selection. + </para> + </listitem> + </itemizedlist> + </para> + <para>If necessary, the application should also include LibXML, + LibXSLT and crypto library header files. + </para> + <para> + <example> + <title>Example includes file section.</title> + <programlisting><![CDATA[ +#include <libxml/tree.h> +#include <libxml/xmlmemory.h> +#include <libxml/parser.h> + +#ifndef XMLSEC_NO_XSLT +#include <libxslt/xslt.h> +#endif /* XMLSEC_NO_XSLT */ + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/xmldsig.h> +#include <xmlsec/xmlenc.h> +#include <xmlsec/templates.h> +#include <xmlsec/crypto.h> + ]]></programlisting> + </example> + </para> + </sect1> + <sect1 id="xmlsec-notes-compiling-unix" > + <title>Compiling and linking on Unix.</title> + <para>There are several ways to get necessary compilation + and linking information on Unix and application can use + any of these methods to do crypto engine selection either + at linking or run time. + + <itemizedlist> + <listitem><para>PKG_CHECK_MODULES() macro + <example> + <title>Using PKG_CHECK_MODULES() macro in a configure.in file + to select crypto engine (openssl) at linking time.</title> + <programlisting><![CDATA[ +dnl +dnl Check for xmlsec and friends +dnl +PKG_CHECK_MODULES(XMLSEC, xmlsec1-openssl >= 1.0.0 xml2 libxslt,,exit) +CFLAGS="$CFLAGS $XMLSEC_CFLAGS" +CPPFLAGS="$CPPFLAGS $XMLSEC_CFLAGS" +LDFLAGS="$LDFLAGS $XMLSEC_LIBS" + ]]></programlisting> + </example> + + <example> + <title>Using PKG_CHECK_MODULES() macro in a configure.in file + to enable dynamical loading of xmlsec-crypto library.</title> + <programlisting><![CDATA[ +dnl +dnl Check for xmlsec and friends +dnl +PKG_CHECK_MODULES(XMLSEC, xmlsec1 >= 1.0.0 xml2 libxslt,,exit) +CFLAGS="$CFLAGS $XMLSEC_CFLAGS" +CPPFLAGS="$CPPFLAGS $XMLSEC_CFLAGS" +LDFLAGS="$LDFLAGS $XMLSEC_LIBS" + ]]></programlisting> + </example> + + </para></listitem> + + + <listitem><para>pkg-config script + <example> + <title>Using pkg-config script in a Makefile + to select crypto engine (nss) at linking time.</title> + <programlisting><![CDATA[ +PROGRAM = test +PROGRAM_FILES = test.c + +CFLAGS += -g $(shell pkg-config --cflags xmlsec1-nss) +LDFLAGS += -g +LIBS += $(shell pkg-config --libs xmlsec1-nss) + +all: $(PROGRAM) + +%: %.c + $(cc) $(PROGRAM_FILES) $(CFLAGS) $(LDFLAGS) -o $(PROGRAM) $(LIBS) + +clean: + @rm -rf $(PROGRAM) + ]]></programlisting> + </example> + + + <example> + <title>Using pkg-config script in a Makefile + to enable dynamical loading of xmlsec-crypto library.</title> + <programlisting><![CDATA[ +PROGRAM = test +PROGRAM_FILES = test.c + +CFLAGS += -g $(shell pkg-config --cflags xmlsec1) +LDFLAGS += -g +LIBS += $(shell pkg-config --libs xmlsec1) + +all: $(PROGRAM) + +%: %.c + $(cc) $(PROGRAM_FILES) $(CFLAGS) $(LDFLAGS) -o $(PROGRAM) $(LIBS) + +clean: + @rm -rf $(PROGRAM) + ]]></programlisting> + </example> + + </para></listitem> + <listitem><para>xmlsec1-config script + <example> + <title>Using xmlsec1-config script in a Makefile + to select crypto engine (e.g. gnutls) at linking time.</title> + <programlisting><![CDATA[ +PROGRAM = test +PROGRAM_FILES = test.c + +CFLAGS += -g $(shell xmlsec1-config --crypto gnutls --cflags) +LDFLAGS += -g +LIBS += $(shell xmlsec1-config --crypto gnutls --libs) + +all: $(PROGRAM) + +%: %.c + $(cc) $(PROGRAM_FILES) $(CFLAGS) $(LDFLAGS) -o $(PROGRAM) $(LIBS) + +clean: + @rm -rf $(PROGRAM) + ]]></programlisting> + </example> + + <example> + <title>Using xmlsec1-config script in a Makefile + to enable dynamical loading of xmlsec-crypto library.</title> + <programlisting><![CDATA[ +PROGRAM = test +PROGRAM_FILES = test.c + +CFLAGS += -g $(shell xmlsec1-config --cflags) +LDFLAGS += -g +LIBS += $(shell xmlsec1-config --libs) + +all: $(PROGRAM) + +%: %.c + $(cc) $(PROGRAM_FILES) $(CFLAGS) $(LDFLAGS) -o $(PROGRAM) $(LIBS) + +clean: + @rm -rf $(PROGRAM) + ]]></programlisting> + </example> + </para></listitem> + </itemizedlist> + </para> + </sect1> + <sect1 id="xmlsec-notes-compiling-windows" > + <title>Compiling and linking on Windows.</title> + <para>On Windows there is no such simple and elegant solution. + Please check <filename>README</filename> file in <filename>win32</filename> + folder of the library package for latest instructions. + However, there are few general things, that you need to remember: + <itemizedlist> + <listitem><para> + <emphasis>All libraries linked to your application must be compiled + with the same Microsoft Runtime Libraries.</emphasis> + </para></listitem> + <listitem><para> + <emphasis>Static linking with XML Security Library requires + additional global defines:</emphasis> + <informalexample><programlisting> +#define LIBXML_STATIC +#define LIBXSLT_STATIC +#define XMLSEC_STATIC + </programlisting></informalexample> + </para></listitem> + <listitem><para> + If you do not want to dynamicaly load xmlsec-crypto library + and prefer to select crypto engine at linking then you should + link your application with xmlsec and at least one of + xmlsec-crypto libraries. + </para></listitem> + <listitem><para> + In order to enable dynamic loading for xmlsec-crypto library + you should add additional global define: + <informalexample><programlisting> +#define XMLSEC_CRYPTO_DYNAMIC_LOADING + </programlisting></informalexample> + </para></listitem> + </itemizedlist> + </para> + </sect1> + <sect1 id="xmlsec-notes-compiling-others"> + <title>Compiling and linking on other systems.</title> + <para>Well, nothing is impossible, it's only software (you managed to + compile the library itself, do you?). + I'll be happy to include in this manual your expirience with + compiling and linking applications with XML Security Library + on other platforms (if you would like to share it). + </para> + </sect1> +</chapter> diff --git a/docs/api/src/chapters/creating-templates.sgml b/docs/api/src/chapters/creating-templates.sgml new file mode 100644 index 00000000..4d6088f3 --- /dev/null +++ b/docs/api/src/chapters/creating-templates.sgml @@ -0,0 +1,325 @@ +<chapter id="xmlsec-notes-templates"> + <title>Creating dynamic templates.</title> + <sect1 id="xmlsec-notes-templates-overview"> + <title>Overview.</title> + <para>The XML Security Library uses templates to describe + how and what data should be signed or encrypted. The template + is a regular XML file. You can create templates in advance + using your favorite XML files editor, load them from a file + and use for creating signature or encrypting data. You can + also create templates dynamicaly. The XML Security Library + provides helper functions to quickly create dynamic templates + inside your application.</para> + </sect1> + <sect1 id="xmlsec-notes-dynamic-signature-templates"> + <title>Creating dynamic signature templates.</title> + <para>The signature template has structure similar + to the XML Digital Signature structure as it is described in + <ulink URL="http://www.w3.org/TR/xmldsig-core">specification</ulink>. + The only difference is that some nodes (for example, + <dsig:DigestValue/> or <SignatureValue/>) + are empty. The XML Security Library sets the content of these + nodes after doing necessary calculations. + </para> + <figure> + <title>XML Digital Signature structure</title> + <programlisting> +<dsig:Signature ID?> + <dsig:SignedInfo> + <dsig:CanonicalizationMethod Algorithm /> + <dsig:SignatureMethod Algorithm /> + (<dsig:Reference URI? > + (<dsig:Transforms> + (<dsig:Transform Algorithm />)+ + </dsig:Transforms>)? + <dsig:DigestMethod Algorithm > + <dsig:DigestValue> + </dsig:Reference>)+ + </dsig:SignedInfo> + <dsig:SignatureValue> + (<dsig:KeyInfo> + <dsig:KeyName>? + <dsig:KeyValue>? + <dsig:RetrievalMethod>? + <dsig:X509Data>? + <dsig:PGPData>? + <enc:EncryptedKey>? + <enc:AgreementMethod>? + <dsig:KeyName>? + <dsig:RetrievalMethod>? + <*>? + </dsig:KeyInfo>)? + (<dsig:Object ID?>)* +</dsig:Signature> + </programlisting> + </figure> + <para> + <example> + <title>Creating dynamic signature template.</title> + <programlisting><![CDATA[ +/** + * sign_file: + * @xml_file: the XML file name. + * @key_file: the PEM private key file name. + * + * Signs the #xml_file using private key from #key_file and dynamicaly + * created enveloped signature template. + * + * Returns 0 on success or a negative value if an error occurs. + */ +int +sign_file(const char* xml_file, const char* key_file) { + xmlDocPtr doc = NULL; + xmlNodePtr signNode = NULL; + xmlNodePtr refNode = NULL; + xmlNodePtr keyInfoNode = NULL; + xmlSecDSigCtxPtr dsigCtx = NULL; + int res = -1; + + assert(xml_file); + assert(key_file); + + /* load doc file */ + doc = xmlParseFile(xml_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file); + goto done; + } + + /* create signature template for RSA-SHA1 enveloped signature */ + signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId, + xmlSecTransformRsaSha1Id, NULL); + if(signNode == NULL) { + fprintf(stderr, "Error: failed to create signature template\n"); + goto done; + } + + /* add <dsig:Signature/> node to the doc */ + xmlAddChild(xmlDocGetRootElement(doc), signNode); + + /* add reference */ + refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id, + NULL, NULL, NULL); + if(refNode == NULL) { + fprintf(stderr, "Error: failed to add reference to signature template\n"); + goto done; + } + + /* add enveloped transform */ + if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) { + fprintf(stderr, "Error: failed to add enveloped transform to reference\n"); + goto done; + } + + /* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed document */ + keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL); + if(keyInfoNode == NULL) { + fprintf(stderr, "Error: failed to add key info\n"); + goto done; + } + + if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) { + fprintf(stderr, "Error: failed to add key name\n"); + goto done; + } + + /* create signature context, we don't need keys manager in this example */ + dsigCtx = xmlSecDSigCtxCreate(NULL); + if(dsigCtx == NULL) { + fprintf(stderr,"Error: failed to create signature context\n"); + goto done; + } + + /* load private key, assuming that there is not password */ + dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL); + if(dsigCtx->signKey == NULL) { + fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file); + goto done; + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); + goto done; + } + + /* sign the template */ + if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) { + fprintf(stderr,"Error: signature failed\n"); + goto done; + } + + /* print signed document to stdout */ + xmlDocDump(stdout, doc); + + /* success */ + res = 0; + +done: + /* cleanup */ + if(dsigCtx != NULL) { + xmlSecDSigCtxDestroy(dsigCtx); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-sign2">Full program listing</link></simpara> + </example> + </para> + </sect1> + + <sect1 id="xmlsec-notes-dynamic-encryption-templates"> + <title>Creating dynamic encryption templates.</title> + <para>The encryption template has structure similar + to the XML Encryption structure as it is described in + <ulink URL="http://www.w3.org/TR/xmlenc-core">specification</ulink>. + The only difference is that some nodes (for example, + <enc:CipherValue/>) + are empty. The XML Security Library sets the content of these + nodes after doing necessary calculations. + </para> + <figure> + <title>XML Encryption structure</title> + <programlisting> +<enc:EncryptedData Id? Type? MimeType? Encoding?> + <enc:EncryptionMethod Algorithm />? + (<dsig:KeyInfo> + <dsig:KeyName>? + <dsig:KeyValue>? + <dsig:RetrievalMethod>? + <dsig:X509Data>? + <dsig:PGPData>? + <enc:EncryptedKey>? + <enc:AgreementMethod>? + <dsig:KeyName>? + <dsig:RetrievalMethod>? + <*>? + </dsig:KeyInfo>)? + <enc:CipherData> + <enc:CipherValue>? + <enc:CipherReference URI?>? + </enc:CipherData> + <enc:EncryptionProperties>? +</enc:EncryptedData> + </programlisting> + </figure> + <para> + <example> + <title>Creating dynamic encrytion template.</title> + <programlisting><![CDATA[ +/** + * encrypt_file: + * @xml_file: the encryption template file name. + * @key_file: the Triple DES key file. + * + * Encrypts #xml_file using a dynamicaly created template and DES key from + * #key_file. + * + * Returns 0 on success or a negative value if an error occurs. + */ +int +encrypt_file(const char* xml_file, const char* key_file) { + xmlDocPtr doc = NULL; + xmlNodePtr encDataNode = NULL; + xmlNodePtr keyInfoNode = NULL; + xmlSecEncCtxPtr encCtx = NULL; + int res = -1; + + assert(xml_file); + assert(key_file); + + /* load template */ + doc = xmlParseFile(xml_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file); + goto done; + } + + /* create encryption template to encrypt XML file and replace + * its content with encryption result */ + encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformDes3CbcId, + NULL, xmlSecTypeEncElement, NULL, NULL); + if(encDataNode == NULL) { + fprintf(stderr, "Error: failed to create encryption template\n"); + goto done; + } + + /* we want to put encrypted data in the <enc:CipherValue/> node */ + if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL) { + fprintf(stderr, "Error: failed to add CipherValue node\n"); + goto done; + } + + /* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed document */ + keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL); + if(keyInfoNode == NULL) { + fprintf(stderr, "Error: failed to add key info\n"); + goto done; + } + + if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) { + fprintf(stderr, "Error: failed to add key name\n"); + goto done; + } + + /* create encryption context, we don't need keys manager in this example */ + encCtx = xmlSecEncCtxCreate(NULL); + if(encCtx == NULL) { + fprintf(stderr,"Error: failed to create encryption context\n"); + goto done; + } + + /* load DES key, assuming that there is not password */ + encCtx->encKey = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, key_file); + if(encCtx->encKey == NULL) { + fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", key_file); + goto done; + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(encCtx->encKey, key_file) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); + goto done; + } + + /* encrypt the data */ + if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0) { + fprintf(stderr,"Error: encryption failed\n"); + goto done; + } + + /* we template is inserted in the doc */ + encDataNode = NULL; + + /* print encrypted data with document to stdout */ + xmlDocDump(stdout, doc); + + /* success */ + res = 0; + +done: + + /* cleanup */ + if(encCtx != NULL) { + xmlSecEncCtxDestroy(encCtx); + } + + if(encDataNode != NULL) { + xmlFreeNode(encDataNode); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-encrypt2">Full program listing</link></simpara> + </example> + </para> + </sect1> +</chapter> diff --git a/docs/api/src/chapters/examples.sgml b/docs/api/src/chapters/examples.sgml new file mode 100644 index 00000000..05d972d4 --- /dev/null +++ b/docs/api/src/chapters/examples.sgml @@ -0,0 +1,102 @@ +<chapter id="xmlsec-examples"> + <title>Examples.</title> + <sect1 id="xmlsec-examples-overview" > + <title>XML Security Library Examples.</title> + <para>This section contains several examples of using XML Security Library + to sign, veiryf, encrypt or decrypt XML documents.</para> + </sect1> + + <sect1 id="xmlsec-examples-sign-template-file"> + <title>Signing a template file.</title> + + &xmlsec-example-sign1; + &xmlsec-example-sign1-tmpl; + &xmlsec-example-sign1-res; + </sect1> + + <sect1 id="xmlsec-examples-sign-dynamimc-template"> + <title>Signing a dynamicaly created template.</title> + + &xmlsec-example-sign2; + &xmlsec-example-sign2-doc; + &xmlsec-example-sign2-res; + </sect1> + + <sect1 id="xmlsec-examples-sign-x509"> + <title>Signing with X509 certificate.</title> + + &xmlsec-example-sign3; + &xmlsec-example-sign3-doc; + &xmlsec-example-sign3-res; + </sect1> + + <sect1 id="xmlsec-verify-with-key"> + <title>Verifying a signature with a single key.</title> + + &xmlsec-example-verify1; + </sect1> + + <sect1 id="xmlsec-verify-with-keys-mngr"> + <title>Verifying a signature with keys manager.</title> + + &xmlsec-example-verify2; + </sect1> + + <sect1 id="xmlsec-verify-with-x509"> + <title>Verifying a signature with X509 certificates.</title> + + &xmlsec-example-verify3; + </sect1> + + <sect1 id="xmlsec-verify-with-restrictions"> + <title>Verifying a signature with additional restrictions.</title> + + &xmlsec-example-verify4; + &xmlsec-example-verify4-tmpl; + &xmlsec-example-verify4-res; + &xmlsec-example-verify4-bad-tmpl; + &xmlsec-example-verify4-bad-res; + </sect1> + + <sect1 id="xmlsec-encrypt-template-file"> + <title>Encrypting data with a template file.</title> + + &xmlsec-example-encrypt1; + &xmlsec-example-encrypt1-tmpl; + &xmlsec-example-encrypt1-res; + </sect1> + + <sect1 id="xmlsec-encrypt-dynamic-template"> + <title>Encrypting data with a dynamicaly created template.</title> + + &xmlsec-example-encrypt2; + &xmlsec-example-encrypt2-doc; + &xmlsec-example-encrypt2-res; + </sect1> + + <sect1 id="xmlsec-encrypt-with-session-key"> + <title>Encrypting data with a session key.</title> + + &xmlsec-example-encrypt3; + &xmlsec-example-encrypt3-doc; + &xmlsec-example-encrypt3-res; + </sect1> + + <sect1 id="xmlsec-decrypt-with-signle-key"> + <title>Decrypting data with a single key.</title> + + &xmlsec-example-decrypt1; + </sect1> + + <sect1 id="xmlsec-decrypt-with-keys-mngr"> + <title>Decrypting data with keys manager.</title> + + &xmlsec-example-decrypt2; + </sect1> + + <sect1 id="xmlsec-custom-keys-manager"> + <title>Writing a custom keys manager.</title> + + &xmlsec-example-decrypt3; + </sect1> +</chapter> diff --git a/docs/api/src/chapters/init-and-shutdown.sgml b/docs/api/src/chapters/init-and-shutdown.sgml new file mode 100644 index 00000000..f4c060c1 --- /dev/null +++ b/docs/api/src/chapters/init-and-shutdown.sgml @@ -0,0 +1,104 @@ +<chapter id="xmlsec-notes-init-shutdown"> + <title>Initialization and shutdown.</title> + <para>XML Security Library initialization/shutdown + process includes initialization and shutdown of the + dependent libraries: + <itemizedlist> + <listitem><para>libxml library;</para></listitem> + <listitem><para>libxslt library;</para></listitem> + <listitem><para>crypto library (OpenSSL, GnuTLS, GCrypt, NSS, ...);</para></listitem> + <listitem><para>xmlsec library + (<link linkend="xmlSecInit">xmlSecInit</link> + and <link linkend="xmlSecShutdown">xmlSecShutdown</link> + functions); + </para></listitem> + <listitem><para>xmlsec-crypto library + (<link linkend="xmlSecCryptoDLLoadLibrary">xmlSecCryptoDLLoadLibrary</link> + to load xmlsec-crypto library dynamicaly if needed, + <link linkend="xmlSecCryptoInit">xmlSecCryptoInit</link> + and <link linkend="xmlSecCryptoShutdown">xmlSecCryptoShutdown</link> + functions); + </para></listitem> + </itemizedlist> + xmlsec-crypto library also provides a convinient functions + <link linkend="xmlSecAppCryptoInit">xmlSecAppCryptoInit</link> + and <link linkend="xmlSecAppCryptoShutdown">xmlSecAppCryptoShutdown</link> + to initialize the crypto library itself but application can do it + by itself. + </para> + <para> + <example> + <title>Initializing application.</title> + <programlisting><![CDATA[ + /* Init libxml and libxslt libraries */ + xmlInitParser(); + LIBXML_TEST_VERSION + xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + xmlSubstituteEntitiesDefault(1); +#ifndef XMLSEC_NO_XSLT + xmlIndentTreeOutput = 1; +#endif /* XMLSEC_NO_XSLT */ + + /* Init xmlsec library */ + if(xmlSecInit() < 0) { + fprintf(stderr, "Error: xmlsec initialization failed.\n"); + return(-1); + } + + /* Check loaded library version */ + if(xmlSecCheckVersion() != 1) { + fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n"); + return(-1); + } + + /* Load default crypto engine if we are supporting dynamic + * loading for xmlsec-crypto libraries. Use the crypto library + * name ("openssl", "nss", etc.) to load corresponding + * xmlsec-crypto library. + */ +#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING + if(xmlSecCryptoDLLoadLibrary(NULL) < 0) { + fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n" + "that you have it installed and check shared libraries path\n" + "(LD_LIBRARY_PATH) envornment variable.\n"); + return(-1); + } +#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */ + + /* Init crypto library */ + if(xmlSecCryptoAppInit(NULL) < 0) { + fprintf(stderr, "Error: crypto initialization failed.\n"); + return(-1); + } + + /* Init xmlsec-crypto library */ + if(xmlSecCryptoInit() < 0) { + fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n"); + return(-1); + } + ]]></programlisting> + </example> + </para> + + <para> + <example> + <title>Shutting down application.</title> + <programlisting><![CDATA[ + /* Shutdown xmlsec-crypto library */ + xmlSecCryptoShutdown(); + + /* Shutdown crypto library */ + xmlSecCryptoAppShutdown(); + + /* Shutdown xmlsec library */ + xmlSecShutdown(); + + /* Shutdown libxslt/libxml */ +#ifndef XMLSEC_NO_XSLT + xsltCleanupGlobals(); +#endif /* XMLSEC_NO_XSLT */ + xmlCleanupParser(); + ]]></programlisting> + </example> + </para> +</chapter> 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> + + diff --git a/docs/api/src/chapters/sign-and-encrypt.sgml b/docs/api/src/chapters/sign-and-encrypt.sgml new file mode 100644 index 00000000..72b969b6 --- /dev/null +++ b/docs/api/src/chapters/sign-and-encrypt.sgml @@ -0,0 +1,286 @@ +<chapter id="xmlsec-notes-sign-encrypt"> + <title>Signing and encrypting documents.</title> + <sect1 id="xmlsec-notes-sign-encrypt-overview"> + <title>Overview.</title> + <para>XML Security Library performs signature or encryption by processing + input xml or binary data and a template that specifies a signature or + encryption skeleton: the transforms, algorithms, the key selection + process. A template has the same structure as the desired result but + some of the nodes are empty. XML Security Library gets the key for + signature/encryption from keys managers using the information from + the template, does necessary computations and puts the results in + the template. Signature or encryption context controls the whole + process and stores the required temporary data. + <figure> + <title>The signature or encryption processing model.</title> + <graphic fileref="images/sign-enc-model.png" align="center"></graphic> + </figure> + </para> + </sect1> + + <sect1 id="xmlsec-notes-sign" > + <title>Signing a document.</title> + <para>The typical signature process includes following steps: + <itemizedlist> + <listitem><para> + Prepare data for signature. + </para></listitem> + <listitem><para> + Create or load signature template and select start + <ulink URL="http://www.w3.org/TR/xmldsig-core/#sec-Signature"><dsig:Signature/></ulink> + node. + </para></listitem> + <listitem><para> + Create signature context <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> + using <link linkend="xmlSecDSigCtxCreate">xmlSecDSigCtxCreate</link> or + <link linkend="xmlSecDSigCtxInitialize">xmlSecDSigCtxInitialize</link> + functions. + </para></listitem> + <listitem><para> + Load signature key in <link linkend="xmlSecKeysMngr">keys manager</link> + or generate a session key and set it in the signature context + (<structfield>signKey</structfield> member of + <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> structure). + </para></listitem> + <listitem><para> + Sign data by calling <link linkend="xmlSecDSigCtxSign">xmlSecDSigCtxSign</link> + function. + </para></listitem> + <listitem><para> + Check returned value and consume signed data. + </para></listitem> + <listitem><para> + Destroy signature context <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> + using <link linkend="xmlSecDSigCtxDestroy">xmlSecDSigCtxDestroy</link> or + <link linkend="xmlSecDSigCtxFinalize">xmlSecDSigCtxFinalize</link> + functions. + </para></listitem> + </itemizedlist> + </para> + <para> + <example> + <title>Signing a template.</title> + <programlisting><![CDATA[ +/** + * sign_file: + * @tmpl_file: the signature template file name. + * @key_file: the PEM private key file name. + * + * Signs the #tmpl_file using private key from #key_file. + * + * Returns 0 on success or a negative value if an error occurs. + */ +int +sign_file(const char* tmpl_file, const char* key_file) { + xmlDocPtr doc = NULL; + xmlNodePtr node = NULL; + xmlSecDSigCtxPtr dsigCtx = NULL; + int res = -1; + + assert(tmpl_file); + assert(key_file); + + /* load template */ + doc = xmlParseFile(tmpl_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file); + goto done; + } + + /* find start node */ + node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs); + if(node == NULL) { + fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file); + goto done; + } + + /* create signature context, we don't need keys manager in this example */ + dsigCtx = xmlSecDSigCtxCreate(NULL); + if(dsigCtx == NULL) { + fprintf(stderr,"Error: failed to create signature context\n"); + goto done; + } + + /* load private key, assuming that there is not password */ + dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL); + if(dsigCtx->signKey == NULL) { + fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file); + goto done; + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); + goto done; + } + + /* sign the template */ + if(xmlSecDSigCtxSign(dsigCtx, node) < 0) { + fprintf(stderr,"Error: signature failed\n"); + goto done; + } + + /* print signed document to stdout */ + xmlDocDump(stdout, doc); + + /* success */ + res = 0; + +done: + /* cleanup */ + if(dsigCtx != NULL) { + xmlSecDSigCtxDestroy(dsigCtx); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-sign1">Full program listing</link></simpara> + <simpara><link linkend="xmlsec-example-sign1-tmpl">Simple signature template file</link></simpara> + </example> + </para> + </sect1> + + <sect1 id="xmlsec-notes-encrypt"> + <title>Encrypting data.</title> + <para>The typical encryption process includes following steps: + <itemizedlist> + <listitem><para> + Prepare data for encryption. + </para></listitem> + <listitem><para> + Create or load encryption template and select start + <enc:EncryptedData/> node. + </para></listitem> + <listitem><para> + Create encryption context <link linkend="xmlSecEncCtx">xmlSecEncCtx</link> + using <link linkend="xmlSecEncCtxCreate">xmlSecEncCtxCreate</link> or + <link linkend="xmlSecEncCtxInitialize">xmlSecEncCtxInitialize</link> + functions. + </para></listitem> + <listitem><para> + Load encryption key in <link linkend="xmlSecKeysMngr">keys manager</link> + or generate a session key and set it in the encryption context + (<structfield>encKey</structfield> member of + <link linkend="xmlSecEncCtx">xmlSecEncCtx</link> structure). + </para></listitem> + <listitem><para> + Encrypt data by calling one of the following functions: + <itemizedlist> + <listitem><para> + <link linkend="xmlSecEncCtxBinaryEncrypt">xmlSecEncCtxBinaryEncrypt</link> + </para></listitem> + <listitem><para> + <link linkend="xmlSecEncCtxXmlEncrypt">xmlSecEncCtxXmlEncrypt</link> + </para></listitem> + <listitem><para> + <link linkend="xmlSecEncCtxUriEncrypt">xmlSecEncCtxUriEncrypt</link> + </para></listitem> + </itemizedlist> + </para></listitem> + <listitem><para> + Check returned value and if necessary consume encrypted data. + </para></listitem> + <listitem><para> + Destroy encryption context <link linkend="xmlSecEncCtx">xmlSecEncCtx</link> + using <link linkend="xmlSecEncCtxDestroy">xmlSecEncCtxDestroy</link> or + <link linkend="xmlSecEncCtxFinalize">xmlSecEncCtxFinalize</link> + functions. + </para></listitem> + </itemizedlist> + </para> + <para> + <example> + <title>Encrypting binary data with a template.</title> + <programlisting><![CDATA[ +/** + * encrypt_file: + * @tmpl_file: the encryption template file name. + * @key_file: the Triple DES key file. + * @data: the binary data to encrypt. + * @dataSize: the binary data size. + * + * Encrypts binary #data using template from #tmpl_file and DES key from + * #key_file. + * + * Returns 0 on success or a negative value if an error occurs. + */ +int +encrypt_file(const char* tmpl_file, const char* key_file, const unsigned char* data, size_t dataSize) { + xmlDocPtr doc = NULL; + xmlNodePtr node = NULL; + xmlSecEncCtxPtr encCtx = NULL; + int res = -1; + + assert(tmpl_file); + assert(key_file); + assert(data); + + /* load template */ + doc = xmlParseFile(tmpl_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file); + goto done; + } + + /* find start node */ + node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs); + if(node == NULL) { + fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file); + goto done; + } + + /* create encryption context, we don't need keys manager in this example */ + encCtx = xmlSecEncCtxCreate(NULL); + if(encCtx == NULL) { + fprintf(stderr,"Error: failed to create encryption context\n"); + goto done; + } + + /* load DES key */ + encCtx->encKey = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, key_file); + if(encCtx->encKey == NULL) { + fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", key_file); + goto done; + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(encCtx->encKey, key_file) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); + goto done; + } + + /* encrypt the data */ + if(xmlSecEncCtxBinaryEncrypt(encCtx, node, data, dataSize) < 0) { + fprintf(stderr,"Error: encryption failed\n"); + goto done; + } + + /* print encrypted data with document to stdout */ + xmlDocDump(stdout, doc); + + /* success */ + res = 0; + +done: + /* cleanup */ + if(encCtx != NULL) { + xmlSecEncCtxDestroy(encCtx); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-encrypt1">Full program listing</link></simpara> + <simpara><link linkend="xmlsec-example-encrypt1-tmpl">Simple encryption template file</link></simpara> + </example> + </para> + </sect1> +</chapter> + diff --git a/docs/api/src/chapters/using-contexts.sgml b/docs/api/src/chapters/using-contexts.sgml new file mode 100644 index 00000000..48a336d9 --- /dev/null +++ b/docs/api/src/chapters/using-contexts.sgml @@ -0,0 +1,138 @@ +<chapter id="xmlsec-notes-contexts"> + <title>Using context objects.</title> + <para>The great flexibility of XML Digital Signature and XML Encryption + specification is one of the most interesting and in the same time, + most dangerouse feature for an application developer. + For example, XPath and XSLT transform can make it very difficult + to find out what exactly was signed by just looking at the + transforms and the input data. Many protocols based on + XML Digital Signature and XML Encryption restrict allowed + key data types, allowed transforms or possible input data. + For example, signature in a simple SAML Response should have only + one <dsig:Reference/> element with an empty or NULL + URI attribute and only one enveloped transform. + XML Security Library uses "context" objects to let application + enable or disable particular features, return the result + data and the information collected during the processing. + Also all the context objects defined in XML Security library have + a special <structfield>userData</structfield> member which could + be used by application to pass application specific data around. + XML Security Library never use this field. + The application creates a new + <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> + or <link linkend="xmlSecEncCtx">xmlSecEncCtx</link> object for each + operation, sets necessary options and consumes result returned + in the context after signature, verification, encryption or decryption. + </para> + <para> + <example> + <title>SAML signature validation.</title> + <programlisting><![CDATA[ +/** + * verify_file: + * @mngr: the pointer to keys manager. + * @xml_file: the signed XML file name. + * + * Verifies XML signature in #xml_file. + * + * Returns 0 on success or a negative value if an error occurs. + */ +int +verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file) { + xmlDocPtr doc = NULL; + xmlNodePtr node = NULL; + xmlSecDSigCtxPtr dsigCtx = NULL; + int res = -1; + + assert(mngr); + assert(xml_file); + + /* load file */ + doc = xmlParseFile(xml_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file); + goto done; + } + + /* find start node */ + node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs); + if(node == NULL) { + fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file); + goto done; + } + + /* create signature context */ + dsigCtx = xmlSecDSigCtxCreate(mngr); + if(dsigCtx == NULL) { + fprintf(stderr,"Error: failed to create signature context\n"); + goto done; + } + + /* limit the Reference URI attributes to empty or NULL */ + dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeEmpty; + + /* limit allowed transforms for signature and reference processing */ + if((xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformInclC14NId) < 0) || + (xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformExclC14NId) < 0) || + (xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformSha1Id) < 0) || + (xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformRsaSha1Id) < 0)) { + + fprintf(stderr,"Error: failed to limit allowed signature transforms\n"); + goto done; + } + if((xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformInclC14NId) < 0) || + (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformExclC14NId) < 0) || + (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformSha1Id) < 0) || + (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformEnvelopedId) < 0)) { + + fprintf(stderr,"Error: failed to limit allowed reference transforms\n"); + goto done; + } + + /* in addition, limit possible key data to valid X509 certificates only */ + if(xmlSecPtrListAdd(&(dsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecKeyDataX509Id) < 0) { + fprintf(stderr,"Error: failed to limit allowed key data\n"); + goto done; + } + + /* Verify signature */ + if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) { + fprintf(stderr,"Error: signature verify\n"); + goto done; + } + + /* check that we have only one Reference */ + if((dsigCtx->status == xmlSecDSigStatusSucceeded) && + (xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) != 1)) { + + fprintf(stderr,"Error: only one reference is allowed\n"); + goto done; + } + + /* print verification result to stdout */ + if(dsigCtx->status == xmlSecDSigStatusSucceeded) { + fprintf(stdout, "Signature is OK\n"); + } else { + fprintf(stdout, "Signature is INVALID\n"); + } + + /* success */ + res = 0; + +done: + /* cleanup */ + if(dsigCtx != NULL) { + xmlSecDSigCtxDestroy(dsigCtx); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} + + ]]></programlisting> + </example> + </para> +</chapter> + diff --git a/docs/api/src/chapters/using-keys.sgml b/docs/api/src/chapters/using-keys.sgml new file mode 100644 index 00000000..c2c90f50 --- /dev/null +++ b/docs/api/src/chapters/using-keys.sgml @@ -0,0 +1,26 @@ +<chapter id="xmlsec-notes-keys"> + <title>Keys.</title> + <para>A key in XML Security Library is a representation of the + <ulink URL="http://www.w3.org/TR/xmldsig-core/#sec-KeyInfo"><dsig:KeyInfo/></ulink> + element and consist of several key data objects. + The "value" key data usually contains raw key material (or handlers to + key material) required to execute particular crypto transform. Other + key data objects may contain any additional information about the key. + All the key data objects in the key are associated with the same key + material. For example, if a DSA key material has both an X509 + certificate and a PGP data associated with it then such a key can + have a DSA key "value" and two key data objects for X509 certificate + and PGP key data. + </para> + <figure> + <title>The key structure.</title> + <graphic fileref="images/key.png" align="center"></graphic> + </figure> + <para>XML Security Library has several "invisible" key data classes. + These classes never show up in the keys data list of a key but are used for + <ulink URL="http://www.w3.org/TR/xmldsig-core/#sec-KeyInfo"><dsig:KeyInfo/></ulink> + children processing (<ulink URL="http://www.w3.org/TR/xmldsig-core/#sec-KeyName"><dsig:KeyName/></ulink>, + <enc:EncryptedKey/>, ...). As with transforms, application might + add any new key data objects or replace the default ones. + </para> +</chapter> diff --git a/docs/api/src/chapters/using-keysmngr.sgml b/docs/api/src/chapters/using-keysmngr.sgml new file mode 100644 index 00000000..1c25b3da --- /dev/null +++ b/docs/api/src/chapters/using-keysmngr.sgml @@ -0,0 +1,592 @@ +<chapter id="xmlsec-notes-keysmngr"> + <title>Keys manager.</title> + <sect1 id="xmlsec-notes-keysmngr-overview"> + <title>Overview.</title> + <para>Processing some of the key data objects require additional + information which is global across the application (or in the + particular area of the application). For example, X509 certificates + processing require a common list of trusted certificates to be + available. XML Security Library keeps all the common information + for key data processing in a a collection of key data stores called + "keys manager". + </para> + <figure> + <title>The keys manager structure.</title> + <graphic fileref="images/keysmngr.png" align="center"></graphic> + </figure> + <para>Keys manager has a special "keys store" which lists the keys + known to the application. This "keys store" is used by XML Security + Library to lookup keys by name, type and crypto algorithm (for example, + during + <ulink URL="http://www.w3.org/TR/xmldsig-core/#sec-KeyName"><dsig:KeyName/></ulink> + processing). The XML Security Library + provides default simple "flat list" based implementation of a default keys + store. The application can replace it with any other keys store + (for example, based on an SQL database). + </para> + <para>Keys manager is the only object in XML Security Library which + is supposed to be shared by many different operations. Usually keys + manager is initialized once at the application startup and later is + used by XML Security library routines in "read-only" mode. If + application or crypto function need to modify any of the key data + stores inside keys manager then proper synchronization must be + implemented. In the same time, application can create a new keys + manager each time it needs to perform XML signature, verification, + encryption or decryption. + </para> + </sect1> + + <sect1 id="xmlsec-notes-simple-keys-store"> + <title>Simple keys store.</title> + <para> + XML Security Library has a built-in simple keys store + implemented using a keys list. You can use it in your application + if you have a small number of keys. However, this might be not a + best option from performance point of view if you have a lot of keys. + In this case, you probably should implement your own keys store + using an SQL database or some other keys storage. + </para> + <para> + <example> + <title>Initializing keys manager and loading keys from PEM files.</title> + <programlisting><![CDATA[ +/** + * load_keys: + * @files: the list of filenames. + * @files_size: the number of filenames in #files. + * + * Creates default keys manager and load PEM keys from #files in it. + * The caller is responsible for destroing returned keys manager using + * @xmlSecKeysMngrDestroy. + * + * Returns the pointer to newly created keys manager or NULL if an error + * occurs. + */ +xmlSecKeysMngrPtr +load_keys(char** files, int files_size) { + xmlSecKeysMngrPtr mngr; + xmlSecKeyPtr key; + int i; + + assert(files); + assert(files_size > 0); + + /* create and initialize keys manager, we use a default list based + * keys manager, implement your own xmlSecKeysStore klass if you need + * something more sophisticated + */ + mngr = xmlSecKeysMngrCreate(); + if(mngr == NULL) { + fprintf(stderr, "Error: failed to create keys manager.\n"); + return(NULL); + } + if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) { + fprintf(stderr, "Error: failed to initialize keys manager.\n"); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + for(i = 0; i < files_size; ++i) { + assert(files[i]); + + /* load key */ + key = xmlSecCryptoAppKeyLoad(files[i], xmlSecKeyDataFormatPem, NULL, NULL, NULL); + if(key == NULL) { + fprintf(stderr,"Error: failed to load pem key from \"%s\"\n", files[i]); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(key, BAD_CAST files[i]) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", files[i]); + xmlSecKeyDestroy(key); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* add key to keys manager, from now on keys manager is responsible + * for destroying key + */ + if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) { + fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", files[i]); + xmlSecKeyDestroy(key); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + } + + return(mngr); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-verify2">Full program listing</link></simpara> + </example> + </para> + </sect1> + + <sect1 id="xmlsec-notes-keys-manager-sign-enc"> + <title>Using keys manager for signatures/encryption.</title> + <para>Instead of specifiying signature or encryption key in the + corresponding context object (<structfield>signKey</structfield> + member of <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> + structure or <structfield>encKey</structfield> member of + <link linkend="xmlSecEncCtx">xmlSecEncCtx</link> structure), + the application can use keys manager to select the + signature or encryption key. This is especialy useful + when you are encrypting or signing something with a session key + which is by itself should be encrypted. The key for the + session key encryption in the + <ulink URL="http://www.w3.org/TR/xmlenc-core/#sec-EncryptedKey"><EncryptedKey/></ulink> + node could be selected using + <ulink URL="http://www.w3.org/TR/xmldsig-core/#sec-KeyName"><dsig:KeyName/></ulink> + node in the template. + </para> + <para> + <example> + <title>Encrypting file using a session key and a permanent key from keys manager.</title> + <programlisting><![CDATA[ +/** + * load_rsa_keys: + * @key_file: the key filename. + * + * Creates default keys manager and load RSA key from #key_file in it. + * The caller is responsible for destroing returned keys manager using + * @xmlSecKeysMngrDestroy. + * + * Returns the pointer to newly created keys manager or NULL if an error + * occurs. + */ +xmlSecKeysMngrPtr +load_rsa_keys(char* key_file) { + xmlSecKeysMngrPtr mngr; + xmlSecKeyPtr key; + + assert(key_file); + + /* create and initialize keys manager, we use a default list based + * keys manager, implement your own xmlSecKeysStore klass if you need + * something more sophisticated + */ + mngr = xmlSecKeysMngrCreate(); + if(mngr == NULL) { + fprintf(stderr, "Error: failed to create keys manager.\n"); + return(NULL); + } + if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) { + fprintf(stderr, "Error: failed to initialize keys manager.\n"); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* load private RSA key */ + key = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL); + if(key == NULL) { + fprintf(stderr,"Error: failed to load rsa key from file \"%s\"\n", key_file); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(key, BAD_CAST key_file) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); + xmlSecKeyDestroy(key); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* add key to keys manager, from now on keys manager is responsible + * for destroying key + */ + if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) { + fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", key_file); + xmlSecKeyDestroy(key); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + return(mngr); +} + +/** + * encrypt_file: + * @mngr: the pointer to keys manager. + * @xml_file: the encryption template file name. + * @key_name: the RSA key name. + * + * Encrypts #xml_file using a dynamicaly created template, a session DES key + * and an RSA key from keys manager. + * + * Returns 0 on success or a negative value if an error occurs. + */ +int +encrypt_file(xmlSecKeysMngrPtr mngr, const char* xml_file, const char* key_name) { + xmlDocPtr doc = NULL; + xmlNodePtr encDataNode = NULL; + xmlNodePtr keyInfoNode = NULL; + xmlNodePtr encKeyNode = NULL; + xmlNodePtr keyInfoNode2 = NULL; + xmlSecEncCtxPtr encCtx = NULL; + int res = -1; + + assert(mngr); + assert(xml_file); + assert(key_name); + + /* load template */ + doc = xmlParseFile(xml_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file); + goto done; + } + + /* create encryption template to encrypt XML file and replace + * its content with encryption result */ + encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformDes3CbcId, + NULL, xmlSecTypeEncElement, NULL, NULL); + if(encDataNode == NULL) { + fprintf(stderr, "Error: failed to create encryption template\n"); + goto done; + } + + /* we want to put encrypted data in the <enc:CipherValue/> node */ + if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL) { + fprintf(stderr, "Error: failed to add CipherValue node\n"); + goto done; + } + + /* add <dsig:KeyInfo/> */ + keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL); + if(keyInfoNode == NULL) { + fprintf(stderr, "Error: failed to add key info\n"); + goto done; + } + + /* add <enc:EncryptedKey/> to store the encrypted session key */ + encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode, + xmlSecTransformRsaOaepId, + NULL, NULL, NULL); + if(encKeyNode == NULL) { + fprintf(stderr, "Error: failed to add key info\n"); + goto done; + } + + /* we want to put encrypted key in the <enc:CipherValue/> node */ + if(xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL) { + fprintf(stderr, "Error: failed to add CipherValue node\n"); + goto done; + } + + /* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/> */ + keyInfoNode2 = xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, NULL); + if(keyInfoNode2 == NULL) { + fprintf(stderr, "Error: failed to add key info\n"); + goto done; + } + + /* set key name so we can lookup key when needed */ + if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode2, key_name) == NULL) { + fprintf(stderr, "Error: failed to add key name\n"); + goto done; + } + + /* create encryption context */ + encCtx = xmlSecEncCtxCreate(mngr); + if(encCtx == NULL) { + fprintf(stderr,"Error: failed to create encryption context\n"); + goto done; + } + + /* generate a Triple DES key */ + encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataDesId, 192, xmlSecKeyDataTypeSession); + if(encCtx->encKey == NULL) { + fprintf(stderr,"Error: failed to generate session des key\n"); + goto done; + } + + /* encrypt the data */ + if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0) { + fprintf(stderr,"Error: encryption failed\n"); + goto done; + } + + /* we template is inserted in the doc */ + encDataNode = NULL; + + /* print encrypted data with document to stdout */ + xmlDocDump(stdout, doc); + + /* success */ + res = 0; + +done: + + /* cleanup */ + if(encCtx != NULL) { + xmlSecEncCtxDestroy(encCtx); + } + + if(encDataNode != NULL) { + xmlFreeNode(encDataNode); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} + + ]]></programlisting> + <simpara><link linkend="xmlsec-example-encrypt3">Full program listing</link></simpara> + </example> + </para> + </sect1> + + <sect1 id="xmlsec-notes-keys-mngr-verify-decrypt"> + <title>Using keys manager for verification/decryption.</title> + <para>If more than one key could be used for signature or encryption, + then using <structfield>signKey</structfield> member of + <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> structure or + <structfield>encKey</structfield> member of + <link linkend="xmlSecEncCtx">xmlSecEncCtx</link> structure + is not possible. Instead, the application should load known keys in + the keys manager and use <dsig:KeyName/> element to specify + the key name. + </para> + <para> + <example> + <title>Initializing keys manager and loading DES keys from binary files.</title> + <programlisting><![CDATA[ +/** + * load_des_keys: + * @files: the list of filenames. + * @files_size: the number of filenames in #files. + * + * Creates default keys manager and load DES keys from #files in it. + * The caller is responsible for destroing returned keys manager using + * @xmlSecKeysMngrDestroy. + * + * Returns the pointer to newly created keys manager or NULL if an error + * occurs. + */ +xmlSecKeysMngrPtr +load_des_keys(char** files, int files_size) { + xmlSecKeysMngrPtr mngr; + xmlSecKeyPtr key; + int i; + + assert(files); + assert(files_size > 0); + + /* create and initialize keys manager, we use a default list based + * keys manager, implement your own xmlSecKeysStore klass if you need + * something more sophisticated + */ + mngr = xmlSecKeysMngrCreate(); + if(mngr == NULL) { + fprintf(stderr, "Error: failed to create keys manager.\n"); + return(NULL); + } + if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) { + fprintf(stderr, "Error: failed to initialize keys manager.\n"); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + for(i = 0; i < files_size; ++i) { + assert(files[i]); + + /* load DES key */ + key = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, files[i]); + if(key == NULL) { + fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", files[i]); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(key, BAD_CAST files[i]) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", files[i]); + xmlSecKeyDestroy(key); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* add key to keys manager, from now on keys manager is responsible + * for destroying key + */ + if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) { + fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", files[i]); + xmlSecKeyDestroy(key); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + } + + return(mngr); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-decrypt2">Full program listing</link></simpara> + </example> + </para> + </sect1> + + <sect1 id="xmlsec-notes-custom-keys-store"> + <title>Implementing a custom keys store.</title> + <para>In many cases, a default built-in list based keys store + is not good enough. For example, XML Security Library (and + the built-in default keys store) have no synchronization and + you'll need to implement a custom keys store if you want to + add or remove keys while other threads use the store.</para> + <para> + <example> + <title>Creating a custom keys manager.</title> + <programlisting><![CDATA[ +/** + * create_files_keys_mngr: + * + * Creates a files based keys manager: we assume that key name is + * the key file name, + * + * Returns pointer to newly created keys manager or NULL if an error occurs. + */ +xmlSecKeysMngrPtr +create_files_keys_mngr(void) { + xmlSecKeyStorePtr keysStore; + xmlSecKeysMngrPtr mngr; + + /* create files based keys store */ + keysStore = xmlSecKeyStoreCreate(files_keys_store_get_klass()); + if(keysStore == NULL) { + fprintf(stderr, "Error: failed to create keys store.\n"); + return(NULL); + } + + /* create keys manager */ + mngr = xmlSecKeysMngrCreate(); + if(mngr == NULL) { + fprintf(stderr, "Error: failed to create keys manager.\n"); + xmlSecKeyStoreDestroy(keysStore); + return(NULL); + } + + /* add store to keys manager, from now on keys manager destroys the store if needed */ + if(xmlSecKeysMngrAdoptKeysStore(mngr, keysStore) < 0) { + fprintf(stderr, "Error: failed to add keys store to keys manager.\n"); + xmlSecKeyStoreDestroy(keysStore); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* initialize crypto library specific data in keys manager */ + if(xmlSecCryptoKeysMngrInit(mngr) < 0) { + fprintf(stderr, "Error: failed to initialize crypto data in keys manager.\n"); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + /* set the get key callback */ + mngr->getKey = xmlSecKeysMngrGetKey; + return(mngr); +} + +/**************************************************************************** + * + * Files Keys Store: we assume that key's name (content of the + * <dsig:KeyName/> element is a name of the file with a key. + * Attention: this probably not a good solution for high traffic systems. + * + ***************************************************************************/ +static xmlSecKeyPtr files_keys_store_find_key (xmlSecKeyStorePtr store, + const xmlChar* name, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static xmlSecKeyStoreKlass files_keys_store_klass = { + sizeof(xmlSecKeyStoreKlass), + sizeof(xmlSecKeyStore), + BAD_CAST "files-based-keys-store", /* const xmlChar* name; */ + NULL, /* xmlSecKeyStoreInitializeMethod initialize; */ + NULL, /* xmlSecKeyStoreFinalizeMethod finalize; */ + files_keys_store_find_key, /* xmlSecKeyStoreFindKeyMethod findKey; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * files_keys_store_get_klass: + * + * The files based keys store klass: we assume that key name is the + * key file name, + * + * Returns files based keys store klass. + */ +xmlSecKeyStoreId +files_keys_store_get_klass(void) { + return(&files_keys_store_klass); +} + +/** + * files_keys_store_find_key: + * @store: the pointer to default keys store. + * @name: the desired key name. + * @keyInfoCtx: the pointer to <dsig:KeyInfo/> node processing context. + * + * Lookups key in the @store. + * + * Returns pointer to key or NULL if key not found or an error occurs. + */ +static xmlSecKeyPtr +files_keys_store_find_key(xmlSecKeyStorePtr store, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyPtr key; + const xmlChar* p; + + assert(store); + assert(keyInfoCtx); + + /* it's possible to do not have the key name or desired key type + * but we could do nothing in this case */ + if((name == NULL) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataIdUnknown)){ + return(NULL); + } + + /* we don't want to open files in a folder other than "current"; + * to prevent it limit the characters in the key name to alpha/digit, + * '.', '-' or '_'. + */ + for(p = name; (*p) != '\0'; ++p) { + if(!isalnum((*p)) && ((*p) != '.') && ((*p) != '-') && ((*p) != '_')) { + return(NULL); + } + } + + if((keyInfoCtx->keyReq.keyId == xmlSecKeyDataDsaId) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataRsaId)) { + /* load key from a pem file, if key is not found then it's an error (is it?) */ + key = xmlSecCryptoAppKeyLoad(name, xmlSecKeyDataFormatPem, NULL, NULL, NULL); + if(key == NULL) { + fprintf(stderr,"Error: failed to load pem key from \"%s\"\n", name); + return(NULL); + } + } else { + /* otherwise it's a binary key, if key is not found then it's an error (is it?) */ + key = xmlSecKeyReadBinaryFile(keyInfoCtx->keyReq.keyId, name); + if(key == NULL) { + fprintf(stderr,"Error: failed to load key from binary file \"%s\"\n", name); + return(NULL); + } + } + + /* set key name */ + if(xmlSecKeySetName(key, name) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", name); + xmlSecKeyDestroy(key); + return(NULL); + } + + return(key); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-decrypt3">Full program listing</link></simpara> + </example> + </para> + </sect1> +</chapter> diff --git a/docs/api/src/chapters/using-transforms.sgml b/docs/api/src/chapters/using-transforms.sgml new file mode 100644 index 00000000..874f41ca --- /dev/null +++ b/docs/api/src/chapters/using-transforms.sgml @@ -0,0 +1,67 @@ +<chapter id="xmlsec-notes-transforms"> + <title>Transforms and transforms chain.</title> + <para>XML Digital Signature and XML Encryption standards are + very flexible and provide an XML developer many different ways to + sign or encrypt any part (or even parts) of an XML document. + The key for such great flexibility is the "transforms" model. + Transform is defined as a method of pre-processing binary or XML data + before calculating digest or signature. XML Security Library extends + this definition and names "transform" any operation performed on + the data: reading data from an URI, xml parsing, xml transformation, + calculation digest, encrypting or decrypting. Each XML Security Library + transform provides at least one of the following callbacks: + <itemizedlist> + <listitem><para> + <link linkend="xmlSecTransformPushBinMethod">push binary data</link>; + </para></listitem> + <listitem><para> + <link linkend="xmlSecTransformPushXmlMethod">push xml data</link>; + </para></listitem> + <listitem><para> + <link linkend="xmlSecTransformPopBinMethod">pop binary data</link>; + </para></listitem> + <listitem><para> + <link linkend="xmlSecTransformPopXmlMethod">pop xml data</link>. + </para></listitem> + </itemizedlist> + </para> + <para>One additional <link linkend="xmlSecTransformExecuteMethod">execute</link> + callback was added to simplify the development and reduce code size. + This callback is used by default + implementations of the four external callbacks from the list above. + For example, most of the crypto transforms could be implemented by + just implementing one "execute" callback and using default push/pop + binary data callbacks. However, in some cases using push/pop callbacks + directly is more efficient. + </para> + <figure> + <title>The XML Security Library transform.</title> + <graphic fileref="images/transform.png" align="center"></graphic> + </figure> + <para>XML Security Library constructs transforms chain according to the + signature/encryption template or signed/encrypted document. + If necessary, XML Security Library inserts XML parser or defaul + canonicalization to ensure that the output data type (binary or XML) + of previous transform matches the input of the next transform. + </para> + <para>The data are processed by pushing through or poping from the chain + depending on the transforms in the chain. For example, then binary + data chunk is pushed through a binary-to-binary transform, it + processes this chunk and pushes the result to the next transform + in the chain. + </para> + <figure> + <title>Transforms chain created for <dsig:Reference/> element processing.</title> + <graphic fileref="images/transforms-chain.png" align="center"></graphic> + </figure> + + <para> + <example> + <title>Walking through transforms chain.</title> + <programlisting><![CDATA[ +TODO + ]]></programlisting> + </example> + </para> +</chapter> + diff --git a/docs/api/src/chapters/using-x509-certs.sgml b/docs/api/src/chapters/using-x509-certs.sgml new file mode 100644 index 00000000..8ff029d9 --- /dev/null +++ b/docs/api/src/chapters/using-x509-certs.sgml @@ -0,0 +1,197 @@ +<chapter id="xmlsec-notes-x509"> + <title>Using X509 Certificates.</title> + <sect1 id="xmlsec-notes-x509-overview"> + <title>Overview.</title> + <para>X509 certificate is one of many possible keys data object that can be + associated with a key. Application may read and write X509 data + from/to XML file. The X509 certificates management policies significantly + vary from one crypto library to another. The examples in this chapter + were tested with OpenSSL and they might be broken if anither crypto + engine is used. Check API reference documentation for more specific + information about your crypto engine. + </para> + </sect1> + + <sect1 id="xmlsec-notes-sign-x509" > + <title>Signing data with X509 certificate.</title> + <para>To sign a file using X509 certificate, + an application need to associate the certificate (or certificates) + with the private key using one of the following functions: + <itemizedlist> + <listitem><para> + <link linkend="xmlSecOpenSSLAppKeyCertLoad">xmlSecOpenSSLAppKeyCertLoad</link> - loads + certificate from a file and adds to the key; + </para></listitem> + + <listitem><para> + <link linkend="xmlSecOpenSSLAppPkcs12Load">xmlSecOpenSSLAppPkcs12Load</link> - + loads private key and all the certificates associated with it from a PKCS12 file; + </para></listitem> + + <listitem><para> + <link linkend="xmlSecKeyAdoptData">xmlSecKeyAdoptData</link> - low level + function to add key data (including X509 key data) to the key. + </para></listitem> + </itemizedlist> + <example> + <title>Loading private key and X509 certificate.</title> + <programlisting><![CDATA[ + /* load private key, assuming that there is not password */ + key = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL); + if(key == NULL) { + fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file); + goto done; + } + + /* load certificate and add to the key */ + if(xmlSecCryptoAppKeyCertLoad(key, cert_file, xmlSecKeyDataFormatPem) < 0) { + fprintf(stderr,"Error: failed to load pem certificate \"%s\"\n", cert_file); + goto done; + } + ]]></programlisting> + <simpara><link linkend="xmlsec-example-sign3">Full program listing</link></simpara> + </example> + </para> + <para>Next step is to prepare signature template with <dsig:X509Data/> + child of the <dsig:KeyInfo/> element. When XML Security Library finds + this node in the template, it automaticaly creates <dsig:X509Certificate/> + children of the <dsig:X509Data/> element and writes to result XML document + all the certificates associated with the signature key. + <example> + <title>Dynamicaly creating a signature template for signing document using X509 certificate.</title> + <programlisting><![CDATA[ + /* create signature template for RSA-SHA1 enveloped signature */ + signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId, + xmlSecTransformRsaSha1Id, NULL); + if(signNode == NULL) { + fprintf(stderr, "Error: failed to create signature template\n"); + goto done; + } + + /* add <dsig:Signature/> node to the doc */ + xmlAddChild(xmlDocGetRootElement(doc), signNode); + + /* add reference */ + refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id, + NULL, NULL, NULL); + if(refNode == NULL) { + fprintf(stderr, "Error: failed to add reference to signature template\n"); + goto done; + } + + /* add enveloped transform */ + if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) { + fprintf(stderr, "Error: failed to add enveloped transform to reference\n"); + goto done; + } + + /* add <dsig:KeyInfo/> and <dsig:X509Data/> */ + keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL); + if(keyInfoNode == NULL) { + fprintf(stderr, "Error: failed to add key info\n"); + goto done; + } + + if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) { + fprintf(stderr, "Error: failed to add X509Data node\n"); + goto done; + } + ]]></programlisting> + <simpara><link linkend="xmlsec-example-sign3">Full program listing</link></simpara> + </example> + </para> + </sect1> + + <sect1 id="xmlsec-notes-verify-x509" > + <title>Verifing document signed with X509 certificates.</title> + <para> + If the document is signed with an X509 certificate then the signature + verification consist of two steps: + <itemizedlist> + <listitem><para>Creating and verifing X509 certificates chain. + </para></listitem> + <listitem><para>Verifing signature itself using key exrtacted from + a certificate verified on previous step. + </para></listitem> + </itemizedlist> + Certificates chain is constructed from certificates in a way that + each certificate in the chain is signed with previous one: + <figure> + <title>Certificates chain.</title> + <programlisting> +Certificate A (signed with B) <- Certificate B (signed with C) <- ... <- Root Certificate (signed by itself) + </programlisting> + </figure> + At the end of the chain there is a "Root Certificate" which + is signed by itself. There is no way to verify the validity of the + root certificate and application have to "trust" it + (another name for root certificates is "trusted" certificates). + </para> + + <para> + Application can use <link linkend="xmlSecCryptoAppKeysMngrCertLoad">xmlSecCryptoAppKeysMngrCertLoad</link> + function to load both "trusted" and "un-trusted" + certificates. However, the selection of "trusted" + certificates is very sensitive process and this function might be + not implemented for some crypto engines. In this case, the + "trusted" certificates list is loaded during initialization + or specified in crypto engine configuration files. + Check XML Security Library API reference for more details. + <example> + <title>Loading trusted X509 certificate.</title> + <programlisting><![CDATA[ +/** + * load_trusted_certs: + * @files: the list of filenames. + * @files_size: the number of filenames in #files. + * + * Creates simple keys manager and load trusted certificates from PEM #files. + * The caller is responsible for destroing returned keys manager using + * @xmlSecKeysMngrDestroy. + * + * Returns the pointer to newly created keys manager or NULL if an error + * occurs. + */ +xmlSecKeysMngrPtr +load_trusted_certs(char** files, int files_size) { + xmlSecKeysMngrPtr mngr; + int i; + + assert(files); + assert(files_size > 0); + + /* create and initialize keys manager, we use a simple list based + * keys manager, implement your own xmlSecKeysStore klass if you need + * something more sophisticated + */ + mngr = xmlSecKeysMngrCreate(); + if(mngr == NULL) { + fprintf(stderr, "Error: failed to create keys manager.\n"); + return(NULL); + } + if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) { + fprintf(stderr, "Error: failed to initialize keys manager.\n"); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + + for(i = 0; i < files_size; ++i) { + assert(files[i]); + + /* load trusted cert */ + if(xmlSecCryptoAppKeysMngrCertLoad(mngr, files[i], xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted) < 0) { + fprintf(stderr,"Error: failed to load pem certificate from \"%s\"\n", files[i]); + xmlSecKeysMngrDestroy(mngr); + return(NULL); + } + } + + return(mngr); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-verify3">Full program listing</link></simpara> + </example> + </para> + </sect1> +</chapter> + diff --git a/docs/api/src/chapters/verify-and-decrypt.sgml b/docs/api/src/chapters/verify-and-decrypt.sgml new file mode 100644 index 00000000..382c97c1 --- /dev/null +++ b/docs/api/src/chapters/verify-and-decrypt.sgml @@ -0,0 +1,265 @@ +<chapter id="xmlsec-notes-verify-decrypt"> + <title>Verifing and decrypting documents.</title> + <sect1 id="xmlsec-notes-verify-decrypt-overview"> + <title>Overview.</title> + <para>Since the template is just an XML file, it might be created in advance + and saved in a file. It's also possible for application to create + templates without using XML Security Library functions. Also in some + cases template should be inserted in the signed or encrypted data + (for example, if you want to create an enveloped or enveloping + signature).</para> + <para>Signature verification and data decryption do not require template + because all the necessary information is provided in the signed or + encrypted document. + <figure> + <title>The verification or decryption processing model.</title> + <graphic fileref="images/verif-dec-model.png" align="center"></graphic> + </figure> + </para> + </sect1> + + <sect1 id="xmlsec-notes-verify" > + <title>Verifying a signed document</title> + <para>The typical signature verification process includes following steps: + <itemizedlist> + <listitem><para> + Load keys, X509 certificates, etc. in the <link linkend="xmlSecKeysMngr">keys manager</link> . + </para></listitem> + <listitem><para> + Create signature context <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> + using <link linkend="xmlSecDSigCtxCreate">xmlSecDSigCtxCreate</link> or + <link linkend="xmlSecDSigCtxInitialize">xmlSecDSigCtxInitialize</link> + functions. + </para></listitem> + <listitem><para> + Select start verification + <ulink URL="http://www.w3.org/TR/xmldsig-core/#sec-Signature"><dsig:Signature/></ulink> + node in the signed XML document. + </para></listitem> + <listitem><para> + Verify signature by calling <link linkend="xmlSecDSigCtxVerify">xmlSecDSigCtxVerify</link> + function. + </para></listitem> + <listitem><para> + Check returned value and verification status (<structfield>status</structfield> + member of <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> structure). + If necessary, consume returned data from the <link linkend="xmlSecDSigCtx">context</link>. + </para></listitem> + <listitem><para> + Destroy signature context <link linkend="xmlSecDSigCtx">xmlSecDSigCtx</link> + using <link linkend="xmlSecDSigCtxDestroy">xmlSecDSigCtxDestroy</link> or + <link linkend="xmlSecDSigCtxFinalize">xmlSecDSigCtxFinalize</link> + functions. + </para></listitem> + </itemizedlist> + </para> + <para> + <example> + <title>Verifying a document.</title> + <programlisting><![CDATA[ +/** + * verify_file: + * @xml_file: the signed XML file name. + * @key_file: the PEM public key file name. + * + * Verifies XML signature in #xml_file using public key from #key_file. + * + * Returns 0 on success or a negative value if an error occurs. + */ +int +verify_file(const char* xml_file, const char* key_file) { + xmlDocPtr doc = NULL; + xmlNodePtr node = NULL; + xmlSecDSigCtxPtr dsigCtx = NULL; + int res = -1; + + assert(xml_file); + assert(key_file); + + /* load file */ + doc = xmlParseFile(xml_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file); + goto done; + } + + /* find start node */ + node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs); + if(node == NULL) { + fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file); + goto done; + } + + /* create signature context, we don't need keys manager in this example */ + dsigCtx = xmlSecDSigCtxCreate(NULL); + if(dsigCtx == NULL) { + fprintf(stderr,"Error: failed to create signature context\n"); + goto done; + } + + /* load public key */ + dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file,xmlSecKeyDataFormatPem, NULL, NULL, NULL); + if(dsigCtx->signKey == NULL) { + fprintf(stderr,"Error: failed to load public pem key from \"%s\"\n", key_file); + goto done; + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); + goto done; + } + + /* Verify signature */ + if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) { + fprintf(stderr,"Error: signature verify\n"); + goto done; + } + + /* print verification result to stdout */ + if(dsigCtx->status == xmlSecDSigStatusSucceeded) { + fprintf(stdout, "Signature is OK\n"); + } else { + fprintf(stdout, "Signature is INVALID\n"); + } + + /* success */ + res = 0; + +done: + /* cleanup */ + if(dsigCtx != NULL) { + xmlSecDSigCtxDestroy(dsigCtx); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-verify1">Full Program Listing</link></simpara> + </example> + </para> + </sect1> + + <sect1 id="xmlsec-notes-decrypt" > + <title>Decrypting an encrypted document</title> + <para>The typical decryption process includes following steps: + <itemizedlist> + <listitem><para> + Load keys, X509 certificates, etc. in the <link linkend="xmlSecKeysMngr">keys manager</link> . + </para></listitem> + <listitem><para> + Create encryption context <link linkend="xmlSecEncCtx">xmlSecEncCtx</link> + using <link linkend="xmlSecEncCtxCreate">xmlSecEncCtxCreate</link> or + <link linkend="xmlSecEncCtxInitialize">xmlSecEncCtxInitialize</link> + functions. + </para></listitem> + <listitem><para> + Select start decryption <enc:EncryptedData> node. + </para></listitem> + <listitem><para> + Decrypt by calling <link linkend="xmlSecEncCtxDecrypt">xmlSecencCtxDecrypt</link> + function. + </para></listitem> + <listitem><para> + Check returned value and if necessary consume encrypted data. + </para></listitem> + <listitem><para> + Destroy encryption context <link linkend="xmlSecEncCtx">xmlSecEncCtx</link> + using <link linkend="xmlSecEncCtxDestroy">xmlSecEncCtxDestroy</link> or + <link linkend="xmlSecEncCtxFinalize">xmlSecEncCtxFinalize</link> + functions. + </para></listitem> + </itemizedlist> + </para> + <para> + <example> + <title>Decrypting a document.</title> + <programlisting><![CDATA[ +int +decrypt_file(const char* enc_file, const char* key_file) { + xmlDocPtr doc = NULL; + xmlNodePtr node = NULL; + xmlSecEncCtxPtr encCtx = NULL; + int res = -1; + + assert(enc_file); + assert(key_file); + + /* load template */ + doc = xmlParseFile(enc_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file); + goto done; + } + + /* find start node */ + node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs); + if(node == NULL) { + fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file); + goto done; + } + + /* create encryption context, we don't need keys manager in this example */ + encCtx = xmlSecEncCtxCreate(NULL); + if(encCtx == NULL) { + fprintf(stderr,"Error: failed to create encryption context\n"); + goto done; + } + + /* load DES key */ + encCtx->encKey = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, key_file); + if(encCtx->encKey == NULL) { + fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", key_file); + goto done; + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(encCtx->encKey, key_file) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); + goto done; + } + + /* decrypt the data */ + if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) { + fprintf(stderr,"Error: decryption failed\n"); + goto done; + } + + /* print decrypted data to stdout */ + if(encCtx->resultReplaced != 0) { + fprintf(stdout, "Decrypted XML data:\n"); + xmlDocDump(stdout, doc); + } else { + fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result)); + if(xmlSecBufferGetData(encCtx->result) != NULL) { + fwrite(xmlSecBufferGetData(encCtx->result), + 1, + xmlSecBufferGetSize(encCtx->result), + stdout); + } + } + fprintf(stdout, "\n"); + + /* success */ + res = 0; + +done: + /* cleanup */ + if(encCtx != NULL) { + xmlSecEncCtxDestroy(encCtx); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} + ]]></programlisting> + <simpara><link linkend="xmlsec-example-decrypt1">Full Program Listing</link></simpara> + </example> + </para> + </sect1> +</chapter> diff --git a/docs/api/src/xmlsec.sgml b/docs/api/src/xmlsec.sgml new file mode 100644 index 00000000..fdb3ac1f --- /dev/null +++ b/docs/api/src/xmlsec.sgml @@ -0,0 +1,307 @@ +<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ +<!ENTITY chapter-compiling-and-linking SYSTEM "chapters/compiling-and-linking.sgml"> +<!ENTITY chapter-init-and-shutdown SYSTEM "chapters/init-and-shutdown.sgml"> +<!ENTITY chapter-sign-and-encrypt SYSTEM "chapters/sign-and-encrypt.sgml"> +<!ENTITY chapter-verify-and-decrypt SYSTEM "chapters/verify-and-decrypt.sgml"> +<!ENTITY chapter-creating-templates SYSTEM "chapters/creating-templates.sgml"> +<!ENTITY chapter-using-keys SYSTEM "chapters/using-keys.sgml"> +<!ENTITY chapter-using-keysmngr SYSTEM "chapters/using-keysmngr.sgml"> +<!ENTITY chapter-using-x509-certs SYSTEM "chapters/using-x509-certs.sgml"> +<!ENTITY chapter-using-transforms SYSTEM "chapters/using-transforms.sgml"> +<!ENTITY chapter-using-contexts SYSTEM "chapters/using-contexts.sgml"> +<!ENTITY chapter-new-crypto SYSTEM "chapters/new-crypto.sgml"> +<!ENTITY chapter-examples SYSTEM "chapters/examples.sgml"> + +<!ENTITY xmlsec-index SYSTEM "xmlsec-index.sgml"> + +<!ENTITY xmlsec-app SYSTEM "app.sgml"> +<!ENTITY xmlsec-base64 SYSTEM "base64.sgml"> +<!ENTITY xmlsec-bn SYSTEM "bn.sgml"> +<!ENTITY xmlsec-buffer SYSTEM "buffer.sgml"> +<!ENTITY xmlsec-dl SYSTEM "dl.sgml"> +<!ENTITY xmlsec-errors SYSTEM "errors.sgml"> +<!ENTITY xmlsec-io SYSTEM "io.sgml"> +<!ENTITY xmlsec-keyinfo SYSTEM "keyinfo.sgml"> +<!ENTITY xmlsec-keysdata SYSTEM "keysdata.sgml"> +<!ENTITY xmlsec-keys SYSTEM "keys.sgml"> +<!ENTITY xmlsec-keysmngr SYSTEM "keysmngr.sgml"> +<!ENTITY xmlsec-list SYSTEM "list.sgml"> +<!ENTITY xmlsec-membuf SYSTEM "membuf.sgml"> +<!ENTITY xmlsec-nodeset SYSTEM "nodeset.sgml"> +<!ENTITY xmlsec-parser SYSTEM "parser.sgml"> +<!ENTITY xmlsec-templates SYSTEM "templates.sgml"> +<!ENTITY xmlsec-transforms SYSTEM "transforms.sgml"> +<!ENTITY xmlsec-version SYSTEM "version.sgml"> +<!ENTITY xmlsec-xmldsig SYSTEM "xmldsig.sgml"> +<!ENTITY xmlsec-xmlenc SYSTEM "xmlenc.sgml"> +<!ENTITY xmlsec-xmlsec SYSTEM "xmlsec.sgml"> +<!ENTITY xmlsec-xmltree SYSTEM "xmltree.sgml"> +<!ENTITY xmlsec-x509 SYSTEM "x509.sgml"> + +<!ENTITY xmlsec-openssl-app SYSTEM "openssl/app.sgml"> +<!ENTITY xmlsec-openssl-bn SYSTEM "openssl/bn.sgml"> +<!ENTITY xmlsec-openssl-ciphers SYSTEM "openssl/ciphers.sgml"> +<!ENTITY xmlsec-openssl-crypto SYSTEM "openssl/crypto.sgml"> +<!ENTITY xmlsec-openssl-evp SYSTEM "openssl/evp.sgml"> +<!ENTITY xmlsec-openssl-x509 SYSTEM "openssl/x509.sgml"> + +<!ENTITY xmlsec-gnutls-app SYSTEM "gnutls/app.sgml"> +<!ENTITY xmlsec-gnutls-crypto SYSTEM "gnutls/crypto.sgml"> + +<!ENTITY xmlsec-gcrypt-app SYSTEM "gcrypt/app.sgml"> +<!ENTITY xmlsec-gcrypt-crypto SYSTEM "gcrypt/crypto.sgml"> + +<!ENTITY xmlsec-nss-app SYSTEM "nss/app.sgml"> +<!ENTITY xmlsec-nss-bignum SYSTEM "nss/bignum.sgml"> +<!ENTITY xmlsec-nss-crypto SYSTEM "nss/crypto.sgml"> +<!ENTITY xmlsec-nss-keysstore SYSTEM "nss/keysstore.sgml"> +<!ENTITY xmlsec-nss-pkikeys SYSTEM "nss/pkikeys.sgml"> +<!ENTITY xmlsec-nss-x509 SYSTEM "nss/x509.sgml"> + +<!ENTITY xmlsec-mscrypto-app SYSTEM "mscrypto/app.sgml"> +<!ENTITY xmlsec-mscrypto-certkeys SYSTEM "mscrypto/certkeys.sgml"> +<!ENTITY xmlsec-mscrypto-crypto SYSTEM "mscrypto/crypto.sgml"> +<!ENTITY xmlsec-mscrypto-keysstore SYSTEM "mscrypto/keysstore.sgml"> +<!ENTITY xmlsec-mscrypto-x509 SYSTEM "mscrypto/x509.sgml"> + +<!ENTITY xmlsec-example-sign1 SYSTEM "examples/sign1.sgml"> +<!ENTITY xmlsec-example-sign2 SYSTEM "examples/sign2.sgml"> +<!ENTITY xmlsec-example-sign3 SYSTEM "examples/sign3.sgml"> + +<!ENTITY xmlsec-example-verify1 SYSTEM "examples/verify1.sgml"> +<!ENTITY xmlsec-example-verify2 SYSTEM "examples/verify2.sgml"> +<!ENTITY xmlsec-example-verify3 SYSTEM "examples/verify3.sgml"> +<!ENTITY xmlsec-example-verify4 SYSTEM "examples/verify4.sgml"> + +<!ENTITY xmlsec-example-encrypt1 SYSTEM "examples/encrypt1.sgml"> +<!ENTITY xmlsec-example-encrypt2 SYSTEM "examples/encrypt2.sgml"> +<!ENTITY xmlsec-example-encrypt3 SYSTEM "examples/encrypt3.sgml"> + +<!ENTITY xmlsec-example-decrypt1 SYSTEM "examples/decrypt1.sgml"> +<!ENTITY xmlsec-example-decrypt2 SYSTEM "examples/decrypt2.sgml"> +<!ENTITY xmlsec-example-decrypt3 SYSTEM "examples/decrypt3.sgml"> + +<!ENTITY xmlsec-example-sign1-tmpl SYSTEM "examples/sign1-tmpl.sgml"> +<!ENTITY xmlsec-example-sign1-res SYSTEM "examples/sign1-res.sgml"> +<!ENTITY xmlsec-example-sign2-doc SYSTEM "examples/sign2-doc.sgml"> +<!ENTITY xmlsec-example-sign2-res SYSTEM "examples/sign2-res.sgml"> +<!ENTITY xmlsec-example-sign3-doc SYSTEM "examples/sign3-doc.sgml"> +<!ENTITY xmlsec-example-sign3-res SYSTEM "examples/sign3-res.sgml"> +<!ENTITY xmlsec-example-verify4-res SYSTEM "examples/verify4-res.sgml"> +<!ENTITY xmlsec-example-verify4-tmpl SYSTEM "examples/verify4-tmpl.sgml"> +<!ENTITY xmlsec-example-verify4-bad-res SYSTEM "examples/verify4-bad-res.sgml"> +<!ENTITY xmlsec-example-verify4-bad-tmpl SYSTEM "examples/verify4-bad-tmpl.sgml"> + +<!ENTITY xmlsec-example-encrypt1-tmpl SYSTEM "examples/encrypt1-tmpl.sgml"> +<!ENTITY xmlsec-example-encrypt1-res SYSTEM "examples/encrypt1-res.sgml"> +<!ENTITY xmlsec-example-encrypt2-doc SYSTEM "examples/encrypt2-doc.sgml"> +<!ENTITY xmlsec-example-encrypt2-res SYSTEM "examples/encrypt2-res.sgml"> +<!ENTITY xmlsec-example-encrypt3-doc SYSTEM "examples/encrypt3-doc.sgml"> +<!ENTITY xmlsec-example-encrypt3-res SYSTEM "examples/encrypt3-res.sgml"> +]> +<book id="index"> + <bookinfo> + <title>XML Security Library Reference Manual</title> + <authorgroup> + <author> + <firstname>Aleksey</firstname> + <surname>Sanin</surname> + <affiliation> + <address> + <email>aleksey@aleksey.com</email> + </address> + </affiliation> + </author> + </authorgroup> + <copyright> + <year>2002-2003</year> + <holder>Aleksey Sanin</holder> + </copyright> + <legalnotice> + <para>Permission is granted to make and distribute verbatim + copies of this manual provided the copyright notice and this + permission notice are preserved on all copies.</para> + <para>Permission is granted to copy and distribute modified + versions of this manual under the conditions for verbatim + copying, provided also that the entire resulting derived work is + distributed under the terms of a permission notice identical to + this one.</para> + + <para>Permission is granted to copy and distribute translations + of this manual into another language, under the above conditions + for modified versions.</para> + </legalnotice> + + <abstract> + <para>This manual documents the interfaces of the xmlsec + library and has some short notes to help get you up to speed + with using the library.</para> + </abstract> + </bookinfo> + + <part id="xmlsec-notes"> + <title>XML Security Library Tutorial</title> + <chapter id="xmlsec-notes-overview"> + <title>Overview.</title> + <para>XML Security Library provides support for XML Digital Signature + and XML Encryption. It is based on LibXML/LibXSLT and can use + practicaly any crypto library (currently there is "out of the box" + support for OpenSSL, MSCrypto, GnuTLS, GCrypt and NSS). + </para> + </chapter> + <chapter id="xmlsec-notes-structure"> + <title>XML Security Library Structure.</title> + <para>In order to provide the an ability to use different crypto engines, + the XML Security Library is splitted in two parts: core library (xmlsec) + and crypto library (xmlsec-openssl, xmlsec-mscrypt, xmlsec-gnutls, + xmlsec-gcrypt, xmlsec-nss, ...). + <figure> + <title>The library structure and dependencies.</title> + <graphic fileref="images/structure.png" align="center"></graphic> + </figure> + </para> + <para>The core library has no dependency on any crypto library and provides + implementation of all the engines as well as support for all the non + crypto transforms (xml parser, c14n transforms, xpath and xslt + transforms,...). The XML Security Crypto library provides + implementations for crypto transforms, crypto keys data and key + data stores. Application is linked with particular XML Security + Crypto library (or even libraries), but the actual application + code might be general enough so switching crypto engine would be + a matter of changing several #include directives.</para> + </chapter> + + &chapter-compiling-and-linking; + &chapter-init-and-shutdown; + &chapter-sign-and-encrypt; + &chapter-creating-templates; + &chapter-verify-and-decrypt; + &chapter-using-keys; + &chapter-using-keysmngr; + &chapter-using-x509-certs; + &chapter-using-transforms; + &chapter-using-contexts; + &chapter-new-crypto; + &chapter-examples; + + <chapter id="xmlsec-signature-klasses"> + <title>APPENDIX A. XML Security Library Signature Klasses.</title> + <figure> + <title>XML Security Library Signature Klasses.</title> + <graphic fileref="images/signature-structure.png" align="center"></graphic> + </figure> + </chapter> + + <chapter id="xmlsec-encryption-klasses"> + <title>APPENDIX B. XML Security Library Encryption Klasses.</title> + <figure> + <title>XML Security Library Encryption Klasses.</title> + <graphic fileref="images/encryption-structure.png" align="center"></graphic> + </figure> + </chapter> + </part> + + <part id="xmlsec-reference"> + <title>XML Security Library API Reference.</title> + + <chapter id="xmlsec-ref"> + <title>XML Security Core Library API Reference.</title> + <para>This section contains the API reference for xmlsec. All + the public interfaces are documented here. This reference guide is + build by extracting comments from the code sources. </para> + + &xmlsec-app; + &xmlsec-base64; + &xmlsec-bn; + &xmlsec-buffer; + &xmlsec-dl; + &xmlsec-errors; + &xmlsec-io; + &xmlsec-keyinfo; + &xmlsec-keysdata; + &xmlsec-keys; + &xmlsec-keysmngr; + &xmlsec-list; + &xmlsec-membuf; + &xmlsec-nodeset; + &xmlsec-parser; + &xmlsec-templates; + &xmlsec-transforms; + &xmlsec-version; + &xmlsec-xmldsig; + &xmlsec-xmlenc; + &xmlsec-xmlsec; + &xmlsec-xmltree; + &xmlsec-x509; + </chapter> + + <chapter id="xmlsec-openssl-ref"> + <title>XML Security Library for OpenSLL API Reference.</title> + <para>This section contains the API reference for xmlsec-openssl. All + the public interfaces are documented here. This reference guide is + build by extracting comments from the code sources. </para> + + &xmlsec-openssl-app; + &xmlsec-openssl-bn; + &xmlsec-openssl-crypto; + &xmlsec-openssl-evp; + &xmlsec-openssl-x509; + </chapter> + + <chapter id="xmlsec-gnutls-ref"> + <title>XML Security Library for GnuTLS API Reference.</title> + <para>This section contains the API reference for xmlsec-gnutls. All + the public interfaces are documented here. This reference guide is + build by extracting comments from the code sources. </para> + + &xmlsec-gnutls-app; + &xmlsec-gnutls-crypto; + </chapter> + + <chapter id="xmlsec-gcrypt-ref"> + <title>XML Security Library for GCrypt API Reference.</title> + <para>This section contains the API reference for xmlsec-gcrypt. All + the public interfaces are documented here. This reference guide is + build by extracting comments from the code sources. </para> + + &xmlsec-gcrypt-app; + &xmlsec-gcrypt-crypto; + </chapter> + + <chapter id="xmlsec-nss-ref"> + <title>XML Security Library for NSS API Reference.</title> + <para>This section contains the API reference for xmlsec-nss. All + the public interfaces are documented here. This reference guide is + build by extracting comments from the code sources. </para> + + &xmlsec-nss-app; + &xmlsec-nss-bignum; + &xmlsec-nss-crypto; + &xmlsec-nss-keysstore; + &xmlsec-nss-pkikeys; + &xmlsec-nss-x509; + </chapter> + + <chapter id="xmlsec-mscrypto-ref"> + <title>XML Security Library for MSCrypto API Reference.</title> + <para>This section contains the API reference for xmlsec-mscrypto. All + the public interfaces are documented here. This reference guide is + build by extracting comments from the code sources. </para> + + &xmlsec-mscrypto-app; + &xmlsec-mscrypto-certkeys; + &xmlsec-mscrypto-crypto; + &xmlsec-mscrypto-keysstore; + &xmlsec-mscrypto-x509; + </chapter> + + <chapter id="xmlsec-index"> + <title>XML Security Library Reference Index</title> + <para> + <itemizedlist> + &xmlsec-index; + </itemizedlist> + </para> + </chapter> + </part> +</book> |