4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
25 #include <libxml/tree.h>
26 #include <xmlsec/xmlsec.h>
27 #include <xmlsec/xmltree.h>
28 #include <xmlsec/xmldsig.h>
29 #include <xmlsec/crypto.h>
30 #include <xmlsec/templates.h>
31 #include <xmlsec/errors.h>
32 #include <xmlsec/io.h>
37 static int initstatus;
39 static xmlSecKeysMngrPtr keymgr;
41 #ifndef CA_ROOT_DIRECTORY
42 #define CA_ROOT_DIRECTORY "./ca-certificates"
45 /* checks if a file match uri (should not be a distributor signature) */
46 static int file_match_cb(const char *uri)
48 struct filedesc *fdesc = file_of_name(uri);
49 return fdesc != NULL && fdesc->type == type_file && (fdesc->flags & flag_distributor_signature) == 0;
52 /* open the file of uri */
53 static void *file_open_cb(const char *file)
55 struct filedesc *fdesc;
58 fdesc = file_of_name(file);
60 syslog(LOG_ERR, "shouldn't open uri %s", file);
66 syslog(LOG_ERR, "can't open file %s for reading", file);
68 fdesc->flags |= flag_opened;
73 /* read the opened file */
74 static int file_read_cb(void *context, char *buffer, int len)
76 size_t r = fread(buffer, 1, len, (FILE*)context);
77 return r ? (int)r : feof((FILE*)context) ? 0 : - 1;
80 /* close the opened file */
81 static int file_close_cb(void *context)
83 return (int)fclose((FILE*)context);
86 /* echo an error message */
87 static void errors_cb(const char *file, int line, const char *func, const char *errorObject, const char *errorSubject, int reason, const char *msg)
89 syslog(LOG_ERR, "xmlSec error %3d: %s (subject=\"%s\", object=\"%s\")", reason, msg, errorSubject ? errorSubject : "?", errorObject ? errorObject : "?");
92 /* fills database with trusted keys */
93 static int fill_trusted_keys()
98 char path[PATH_MAX], *e;
100 e = stpcpy(path, CA_ROOT_DIRECTORY);
103 syslog(LOG_ERR, "opendir %s failed in fill_trusted_keys", path);
109 while (ent != NULL) {
110 if (ent->d_type == DT_REG) {
111 strcpy(e, ent->d_name);
112 err = xmlSecCryptoAppKeysMngrCertLoad(keymgr, path, xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted);
114 syslog(LOG_ERR, "xmlSecCryptoAppKeysMngrCertLoadMemory failed for %s", path);
127 /* initialisation of access to xmlsec */
137 if(xmlSecInit() < 0) {
138 syslog(LOG_ERR, "xmlSecInit failed.");
142 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
143 if(xmlSecCryptoDLLoadLibrary(XMLSEC_CRYPTO) < 0) {
144 syslog(LOG_ERR, "xmlSecCryptoDLLoadLibrary %s failed.", XMLSEC_CRYPTO);
149 if(xmlSecCryptoAppInit(NULL) < 0) {
150 syslog(LOG_ERR, "xmlSecCryptoAppInit failed.");
154 if(xmlSecCryptoInit() < 0) {
155 syslog(LOG_ERR, "xmlSecCryptoInit failed.");
159 xmlSecErrorsSetCallback(errors_cb);
161 xmlSecIOCleanupCallbacks();
162 if (xmlSecIORegisterCallbacks(file_match_cb,
163 file_open_cb, file_read_cb, file_close_cb)) {
164 syslog(LOG_ERR, "xmlSecIORegisterCallbacks failed.");
168 keymgr = xmlSecKeysMngrCreate();
169 if (keymgr == NULL) {
170 syslog(LOG_ERR, "xmlSecKeysMngrCreate failed.");
174 if(xmlSecCryptoAppDefaultKeysMngrInit(keymgr) < 0) {
175 syslog(LOG_ERR, "xmlSecCryptoAppDefaultKeysMngrInit failed.");
185 /* shuting down accesses to xmlsec */
186 void xmlsec_shutdown()
188 xmlSecKeysMngrDestroy(keymgr);
190 xmlSecCryptoShutdown();
192 xmlSecCryptoAppShutdown();
197 /* verify a signature */
198 int xmlsec_verify(xmlNodePtr node)
201 xmlSecDSigCtxPtr dsigctx;
203 assert(initdone && !initstatus);
205 dsigctx = xmlSecDSigCtxCreate(keymgr);
206 if (dsigctx == NULL) {
207 syslog(LOG_ERR, "xmlSecDSigCtxCreate failed.");
210 rc = xmlSecDSigCtxVerify(dsigctx, node);
212 syslog(LOG_ERR, "xmlSecDSigCtxVerify failed.");
213 else if (dsigctx->status != xmlSecDSigStatusSucceeded) {
214 syslog(LOG_ERR, "invalid signature.");
217 xmlSecDSigCtxDestroy(dsigctx);
223 /* templates for properties of signature files */
224 static const struct { const char *id; const char *xml; } properties[2] = {
226 .id = "AuthorSignature", /* template of properties for author signature */
228 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
229 "<SignatureProperty Id=\"profile\" Target=\"#AuthorSignature\">"
230 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
231 "</SignatureProperty>"
232 "<SignatureProperty Id=\"role\" Target=\"#AuthorSignature\">"
233 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-author\"></dsp:Role>"
234 "</SignatureProperty>"
235 "<SignatureProperty Id=\"identifier\" Target=\"#AuthorSignature\">"
236 "<dsp:Identifier></dsp:Identifier>"
237 "</SignatureProperty>"
238 "</SignatureProperties>"
241 .id = "DistributorSignature", /* template of properties for distributor signature */
243 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
244 "<SignatureProperty Id=\"profile\" Target=\"#DistributorSignature\">"
245 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
246 "</SignatureProperty>"
247 "<SignatureProperty Id=\"role\" Target=\"#DistributorSignature\">"
248 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-distributor\"></dsp:Role>"
249 "</SignatureProperty>"
250 "<SignatureProperty Id=\"identifier\" Target=\"#DistributorSignature\">"
251 "<dsp:Identifier></dsp:Identifier>"
252 "</SignatureProperty>"
253 "</SignatureProperties>"
257 /* create a signature of 'index' (0 for author, other values for distributors)
258 using the private 'key' (filename) and the certificates 'certs' (filenames)
260 xmlDocPtr xmlsec_create(int index, const char *key, const char **certs)
262 unsigned int i, fc, mask;
263 struct filedesc *fdesc;
264 xmlNodePtr sign, obj, ref, kinfo, props;
267 xmlSecDSigCtxPtr dsigctx;
269 assert(initdone && !initstatus);
271 /* create the document */
272 doc = xmlNewDoc("1.0");
274 syslog(LOG_ERR, "xmlNewDoc failed");
278 /* create the root signature node */
279 sign = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14N11Id, xmlSecTransformRsaSha256Id, properties[!!index].id);
281 syslog(LOG_ERR, "xmlSecTmplSignatureCreate failed");
284 xmlDocSetRootElement(doc, sign);
286 /* create the object and its reference */
287 obj = xmlSecTmplSignatureAddObject(sign, "prop", NULL, NULL);
289 syslog(LOG_ERR, "xmlSecTmplSignatureAddObject failed");
292 rc = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, properties[!!index].xml, &props);
294 syslog(LOG_ERR, "xmlParseBalancedChunkMemory failed");
297 if (NULL == xmlAddChild(obj, props)) {
298 syslog(LOG_ERR, "filling object node failed");
303 /* create references to files */
304 mask = index ? flag_distributor_signature : flag_signature;
306 for (i = 0 ; i < fc ; i++) {
307 fdesc = file_of_index(i);
308 if (fdesc->type == type_file && (fdesc->flags & mask) == 0) {
309 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, fdesc->name, NULL);
311 syslog(LOG_ERR, "creation of reference to %s failed", fdesc->name);
317 /* create reference to object having properties */
318 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, "#prop", NULL);
320 syslog(LOG_ERR, "creation of reference to #prop failed");
323 if (NULL == xmlSecTmplReferenceAddTransform(ref, xmlSecTransformInclC14N11Id)) {
324 syslog(LOG_ERR, "setting transform reference to #prop failed");
328 /* adds the X509 data */
329 kinfo = xmlSecTmplSignatureEnsureKeyInfo(sign, NULL);
331 syslog(LOG_ERR, "xmlSecTmplSignatureEnsureKeyInfo failed");
334 if (NULL == xmlSecTmplKeyInfoAddX509Data(kinfo)) {
335 syslog(LOG_ERR, "xmlSecTmplKeyInfoAddX509Data failed");
340 dsigctx = xmlSecDSigCtxCreate(keymgr);
341 if (dsigctx == NULL) {
342 syslog(LOG_ERR, "xmlSecDSigCtxCreate failed.");
345 dsigctx->signKey = xmlSecCryptoAppKeyLoad(key, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
346 if (dsigctx->signKey == NULL) {
347 syslog(LOG_ERR, "loading key %s failed.", key);
351 if(xmlSecCryptoAppKeyCertLoad(dsigctx->signKey, *certs, xmlSecKeyDataFormatPem) < 0) {
352 syslog(LOG_ERR, "loading certificate %s failed.", *certs);
357 if(xmlSecDSigCtxSign(dsigctx, sign) < 0) {
358 syslog(LOG_ERR, "signing the document failed.");
361 xmlSecDSigCtxDestroy(dsigctx);
365 xmlSecDSigCtxDestroy(dsigctx);