1 /**
2 * XML Security Library example: Decrypting an encrypted file using keys manager.
3 *
4 * Decrypts encrypted XML file using keys manager and a list of
5 * DES key from a binary file
6 *
7 * Usage:
8 * ./decrypt2 <xml-enc> <des-key-file1> [<des-key-file2> [...]]
9 *
10 * Example:
11 * ./decrypt2 encrypt1-res.xml deskey.bin
12 * ./decrypt2 encrypt2-res.xml deskey.bin
13 *
14 * This is free software; see Copyright file in the source
15 * distribution for preciese wording.
16 *
17 * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
18 */
19 #include <stdlib.h>
20 #include <string.h>
21 #include <assert.h>
22
23 #include <libxml/tree.h>
24 #include <libxml/xmlmemory.h>
25 #include <libxml/parser.h>
26
27 #ifndef XMLSEC_NO_XSLT
28 #include <libxslt/xslt.h>
29 #include <libxslt/security.h>
30 #endif /* XMLSEC_NO_XSLT */
31
32 #include <xmlsec/xmlsec.h>
33 #include <xmlsec/xmltree.h>
34 #include <xmlsec/xmlenc.h>
35 #include <xmlsec/crypto.h>
36
37 xmlSecKeysMngrPtr load_des_keys(char** files, int files_size);
38 int decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file);
39
40 int
main(int argc,char ** argv)41 main(int argc, char **argv) {
42 xmlSecKeysMngrPtr mngr;
43 #ifndef XMLSEC_NO_XSLT
44 xsltSecurityPrefsPtr xsltSecPrefs = NULL;
45 #endif /* XMLSEC_NO_XSLT */
46
47 assert(argv);
48
49 if(argc != 3) {
50 fprintf(stderr, "Error: wrong number of arguments.\n");
51 fprintf(stderr, "Usage: %s <enc-file> <key-file1> [<key-file2> [...]]\n", argv[0]);
52 return(1);
53 }
54
55 /* Init libxml and libxslt libraries */
56 xmlInitParser();
57 LIBXML_TEST_VERSION
58 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
59 xmlSubstituteEntitiesDefault(1);
60 #ifndef XMLSEC_NO_XSLT
61 xmlIndentTreeOutput = 1;
62 #endif /* XMLSEC_NO_XSLT */
63
64 /* Init libxslt */
65 #ifndef XMLSEC_NO_XSLT
66 /* disable everything */
67 xsltSecPrefs = xsltNewSecurityPrefs();
68 xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
69 xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
70 xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
71 xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
72 xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
73 xsltSetDefaultSecurityPrefs(xsltSecPrefs);
74 #endif /* XMLSEC_NO_XSLT */
75
76
77 /* Init xmlsec library */
78 if(xmlSecInit() < 0) {
79 fprintf(stderr, "Error: xmlsec initialization failed.\n");
80 return(-1);
81 }
82
83 /* Check loaded library version */
84 if(xmlSecCheckVersion() != 1) {
85 fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
86 return(-1);
87 }
88
89 /* Load default crypto engine if we are supporting dynamic
90 * loading for xmlsec-crypto libraries. Use the crypto library
91 * name ("openssl", "nss", etc.) to load corresponding
92 * xmlsec-crypto library.
93 */
94 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
95 if(xmlSecCryptoDLLoadLibrary(NULL) < 0) {
96 fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
97 "that you have it installed and check shared libraries path\n"
98 "(LD_LIBRARY_PATH and/or LTDL_LIBRARY_PATH) environment variables.\n");
99 return(-1);
100 }
101 #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
102
103 /* Init crypto library */
104 if(xmlSecCryptoAppInit(NULL) < 0) {
105 fprintf(stderr, "Error: crypto initialization failed.\n");
106 return(-1);
107 }
108
109 /* Init xmlsec-crypto library */
110 if(xmlSecCryptoInit() < 0) {
111 fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
112 return(-1);
113 }
114
115 /* create keys manager and load keys */
116 mngr = load_des_keys(&(argv[2]), argc - 2);
117 if(mngr == NULL) {
118 return(-1);
119 }
120
121 if(decrypt_file(mngr, argv[1]) < 0) {
122 xmlSecKeysMngrDestroy(mngr);
123 return(-1);
124 }
125
126 /* destroy keys manager */
127 xmlSecKeysMngrDestroy(mngr);
128
129 /* Shutdown xmlsec-crypto library */
130 xmlSecCryptoShutdown();
131
132 /* Shutdown crypto library */
133 xmlSecCryptoAppShutdown();
134
135 /* Shutdown xmlsec library */
136 xmlSecShutdown();
137
138 /* Shutdown libxslt/libxml */
139 #ifndef XMLSEC_NO_XSLT
140 xsltFreeSecurityPrefs(xsltSecPrefs);
141 xsltCleanupGlobals();
142 #endif /* XMLSEC_NO_XSLT */
143 xmlCleanupParser();
144
145 return(0);
146 }
147
148 /**
149 * load_des_keys:
150 * @files: the list of filenames.
151 * @files_size: the number of filenames in #files.
152 *
153 * Creates simple keys manager and load DES keys from #files in it.
154 * The caller is responsible for destroying returned keys manager using
155 * @xmlSecKeysMngrDestroy.
156 *
157 * Returns the pointer to newly created keys manager or NULL if an error
158 * occurs.
159 */
160 xmlSecKeysMngrPtr
load_des_keys(char ** files,int files_size)161 load_des_keys(char** files, int files_size) {
162 xmlSecKeysMngrPtr mngr;
163 xmlSecKeyPtr key;
164 int i;
165
166 assert(files);
167 assert(files_size > 0);
168
169 /* create and initialize keys manager, we use a simple list based
170 * keys manager, implement your own xmlSecKeysStore klass if you need
171 * something more sophisticated
172 */
173 mngr = xmlSecKeysMngrCreate();
174 if(mngr == NULL) {
175 fprintf(stderr, "Error: failed to create keys manager.\n");
176 return(NULL);
177 }
178 if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
179 fprintf(stderr, "Error: failed to initialize keys manager.\n");
180 xmlSecKeysMngrDestroy(mngr);
181 return(NULL);
182 }
183
184 for(i = 0; i < files_size; ++i) {
185 assert(files[i]);
186
187 /* load DES key */
188 key = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, files[i]);
189 if(key == NULL) {
190 fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", files[i]);
191 xmlSecKeysMngrDestroy(mngr);
192 return(NULL);
193 }
194
195 /* set key name to the file name, this is just an example! */
196 if(xmlSecKeySetName(key, BAD_CAST files[i]) < 0) {
197 fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", files[i]);
198 xmlSecKeyDestroy(key);
199 xmlSecKeysMngrDestroy(mngr);
200 return(NULL);
201 }
202
203 /* add key to keys manager, from now on keys manager is responsible
204 * for destroying key
205 */
206 if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
207 fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", files[i]);
208 xmlSecKeyDestroy(key);
209 xmlSecKeysMngrDestroy(mngr);
210 return(NULL);
211 }
212 }
213
214 return(mngr);
215 }
216
217 /**
218 * decrypt_file:
219 * @mngr: the pointer to keys manager.
220 * @enc_file: the encrypted XML file name.
221 *
222 * Decrypts the XML file #enc_file using DES key from #key_file and
223 * prints results to stdout.
224 *
225 * Returns 0 on success or a negative value if an error occurs.
226 */
227 int
decrypt_file(xmlSecKeysMngrPtr mngr,const char * enc_file)228 decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file) {
229 xmlDocPtr doc = NULL;
230 xmlNodePtr node = NULL;
231 xmlSecEncCtxPtr encCtx = NULL;
232 int res = -1;
233
234 assert(mngr);
235 assert(enc_file);
236
237 /* load template */
238 doc = xmlParseFile(enc_file);
239 if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
240 fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file);
241 goto done;
242 }
243
244 /* find start node */
245 node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
246 if(node == NULL) {
247 fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file);
248 goto done;
249 }
250
251 /* create encryption context */
252 encCtx = xmlSecEncCtxCreate(mngr);
253 if(encCtx == NULL) {
254 fprintf(stderr,"Error: failed to create encryption context\n");
255 goto done;
256 }
257
258 /* decrypt the data */
259 if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
260 fprintf(stderr,"Error: decryption failed\n");
261 goto done;
262 }
263
264 /* print decrypted data to stdout */
265 if(encCtx->resultReplaced != 0) {
266 fprintf(stdout, "Decrypted XML data:\n");
267 xmlDocDump(stdout, doc);
268 } else {
269 fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
270 if(xmlSecBufferGetData(encCtx->result) != NULL) {
271 fwrite(xmlSecBufferGetData(encCtx->result),
272 1,
273 xmlSecBufferGetSize(encCtx->result),
274 stdout);
275 }
276 }
277 fprintf(stdout, "\n");
278
279 /* success */
280 res = 0;
281
282 done:
283 /* cleanup */
284 if(encCtx != NULL) {
285 xmlSecEncCtxDestroy(encCtx);
286 }
287
288 if(doc != NULL) {
289 xmlFreeDoc(doc);
290 }
291 return(res);
292 }
293
294