1 /**
2  * XML Security Library example: Decrypting an encrypted file using a single key.
3  *
4  * Decrypts encrypted XML file using a single DES key from a binary file
5  *
6  * Usage:
7  *      ./decrypt1 <xml-enc> <des-key-file>
8  *
9  * Example:
10  *      ./decrypt1 encrypt1-res.xml deskey.bin
11  *      ./decrypt1 encrypt2-res.xml deskey.bin
12  *
13  * This is free software; see Copyright file in the source
14  * distribution for preciese wording.
15  *
16  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
17  */
18 #include <stdlib.h>
19 #include <string.h>
20 #include <assert.h>
21 
22 #include <libxml/tree.h>
23 #include <libxml/xmlmemory.h>
24 #include <libxml/parser.h>
25 
26 #ifndef XMLSEC_NO_XSLT
27 #include <libxslt/xslt.h>
28 #include <libxslt/security.h>
29 #endif /* XMLSEC_NO_XSLT */
30 
31 #include <xmlsec/xmlsec.h>
32 #include <xmlsec/xmltree.h>
33 #include <xmlsec/xmlenc.h>
34 #include <xmlsec/crypto.h>
35 
36 int decrypt_file(const char* enc_file, const char* key_file);
37 
38 int
main(int argc,char ** argv)39 main(int argc, char **argv) {
40 #ifndef XMLSEC_NO_XSLT
41     xsltSecurityPrefsPtr xsltSecPrefs = NULL;
42 #endif /* XMLSEC_NO_XSLT */
43 
44     assert(argv);
45 
46     if(argc != 3) {
47         fprintf(stderr, "Error: wrong number of arguments.\n");
48         fprintf(stderr, "Usage: %s <enc-file> <key-file>\n", argv[0]);
49         return(1);
50     }
51 
52     /* Init libxml and libxslt libraries */
53     xmlInitParser();
54     LIBXML_TEST_VERSION
55     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
56     xmlSubstituteEntitiesDefault(1);
57 #ifndef XMLSEC_NO_XSLT
58     xmlIndentTreeOutput = 1;
59 #endif /* XMLSEC_NO_XSLT */
60 
61     /* Init libxslt */
62 #ifndef XMLSEC_NO_XSLT
63     /* disable everything */
64     xsltSecPrefs = xsltNewSecurityPrefs();
65     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_READ_FILE,        xsltSecurityForbid);
66     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_WRITE_FILE,       xsltSecurityForbid);
67     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
68     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_READ_NETWORK,     xsltSecurityForbid);
69     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_WRITE_NETWORK,    xsltSecurityForbid);
70     xsltSetDefaultSecurityPrefs(xsltSecPrefs);
71 #endif /* XMLSEC_NO_XSLT */
72 
73 
74     /* Init xmlsec library */
75     if(xmlSecInit() < 0) {
76         fprintf(stderr, "Error: xmlsec initialization failed.\n");
77         return(-1);
78     }
79 
80     /* Check loaded library version */
81     if(xmlSecCheckVersion() != 1) {
82         fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
83         return(-1);
84     }
85 
86     /* Load default crypto engine if we are supporting dynamic
87      * loading for xmlsec-crypto libraries. Use the crypto library
88      * name ("openssl", "nss", etc.) to load corresponding
89      * xmlsec-crypto library.
90      */
91 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
92     if(xmlSecCryptoDLLoadLibrary(NULL) < 0) {
93         fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
94                         "that you have it installed and check shared libraries path\n"
95                         "(LD_LIBRARY_PATH and/or LTDL_LIBRARY_PATH) environment variables.\n");
96         return(-1);
97     }
98 #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
99 
100     /* Init crypto library */
101     if(xmlSecCryptoAppInit(NULL) < 0) {
102         fprintf(stderr, "Error: crypto initialization failed.\n");
103         return(-1);
104     }
105 
106     /* Init xmlsec-crypto library */
107     if(xmlSecCryptoInit() < 0) {
108         fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
109         return(-1);
110     }
111 
112     if(decrypt_file(argv[1], argv[2]) < 0) {
113         return(-1);
114     }
115 
116     /* Shutdown xmlsec-crypto library */
117     xmlSecCryptoShutdown();
118 
119     /* Shutdown crypto library */
120     xmlSecCryptoAppShutdown();
121 
122     /* Shutdown xmlsec library */
123     xmlSecShutdown();
124 
125     /* Shutdown libxslt/libxml */
126 #ifndef XMLSEC_NO_XSLT
127     xsltCleanupGlobals();
128 #endif /* XMLSEC_NO_XSLT */
129     xmlCleanupParser();
130 
131     return(0);
132 }
133 
134 /**
135  * decrypt_file:
136  * @enc_file:           the encrypted XML  file name.
137  * @key_file:           the Triple DES key file.
138  *
139  * Decrypts the XML file #enc_file using DES key from #key_file and
140  * prints results to stdout.
141  *
142  * Returns 0 on success or a negative value if an error occurs.
143  */
144 int
decrypt_file(const char * enc_file,const char * key_file)145 decrypt_file(const char* enc_file, const char* key_file) {
146     xmlDocPtr doc = NULL;
147     xmlNodePtr node = NULL;
148     xmlSecEncCtxPtr encCtx = NULL;
149     int res = -1;
150 
151     assert(enc_file);
152     assert(key_file);
153 
154     /* load template */
155     doc = xmlParseFile(enc_file);
156     if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
157         fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file);
158         goto done;
159     }
160 
161     /* find start node */
162     node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
163     if(node == NULL) {
164         fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file);
165         goto done;
166     }
167 
168     /* create encryption context, we don't need keys manager in this example */
169     encCtx = xmlSecEncCtxCreate(NULL);
170     if(encCtx == NULL) {
171         fprintf(stderr,"Error: failed to create encryption context\n");
172         goto done;
173     }
174 
175     /* load DES key */
176     encCtx->encKey = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, key_file);
177     if(encCtx->encKey == NULL) {
178         fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", key_file);
179         goto done;
180     }
181 
182     /* set key name to the file name, this is just an example! */
183     if(xmlSecKeySetName(encCtx->encKey, key_file) < 0) {
184         fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
185         goto done;
186     }
187 
188     /* decrypt the data */
189     if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
190         fprintf(stderr,"Error: decryption failed\n");
191         goto done;
192     }
193 
194     /* print decrypted data to stdout */
195     if(encCtx->resultReplaced != 0) {
196         fprintf(stdout, "Decrypted XML data:\n");
197         xmlDocDump(stdout, doc);
198     } else {
199         fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
200         if(xmlSecBufferGetData(encCtx->result) != NULL) {
201             fwrite(xmlSecBufferGetData(encCtx->result),
202                   1,
203                   xmlSecBufferGetSize(encCtx->result),
204                   stdout);
205         }
206     }
207     fprintf(stdout, "\n");
208 
209     /* success */
210     res = 0;
211 
212 done:
213     /* cleanup */
214     if(encCtx != NULL) {
215         xmlSecEncCtxDestroy(encCtx);
216     }
217 
218     if(doc != NULL) {
219         xmlFreeDoc(doc);
220     }
221     return(res);
222 }
223 
224