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.
26 #include <libxml/tree.h>
27 #include <xmlsec/xmlsec.h>
28 #include <xmlsec/xmltree.h>
29 #include <xmlsec/xmldsig.h>
30 #include <xmlsec/crypto.h>
31 #include <xmlsec/templates.h>
32 #include <xmlsec/errors.h>
33 #include <xmlsec/io.h>
38 static int initstatus;
40 static xmlSecKeysMngrPtr keymgr;
42 #ifndef CA_ROOT_DIRECTORY
43 #define CA_ROOT_DIRECTORY "./ca-certificates"
46 /* checks if a file match uri (should not be a distributor signature) */
47 static int file_match_cb(const char *uri)
49 struct filedesc *fdesc = file_of_name(uri);
50 return fdesc != NULL && fdesc->type == type_file && (fdesc->flags & flag_distributor_signature) == 0;
53 /* open the file of uri */
54 static void *file_open_cb(const char *file)
56 struct filedesc *fdesc;
60 fdesc = file_of_name(file);
62 syslog(LOG_ERR, "shouldn't open uri %s", file);
66 fd = openat(workdirfd, file, O_RDONLY);
67 f = fd < 0 ? NULL : fdopen(fd, "r");
69 syslog(LOG_ERR, "can't open file %s for reading", file);
73 fdesc->flags |= flag_opened;
78 /* read the opened file */
79 static int file_read_cb(void *context, char *buffer, int len)
81 size_t r = fread(buffer, 1, len, (FILE*)context);
82 return r ? (int)r : feof((FILE*)context) ? 0 : - 1;
85 /* close the opened file */
86 static int file_close_cb(void *context)
88 return (int)fclose((FILE*)context);
91 /* echo an error message */
92 static void errors_cb(const char *file, int line, const char *func, const char *errorObject, const char *errorSubject, int reason, const char *msg)
94 syslog(LOG_ERR, "xmlSec error %3d: %s (subject=\"%s\", object=\"%s\")", reason, msg, errorSubject ? errorSubject : "?", errorObject ? errorObject : "?");
97 /* fills database with trusted keys */
98 static int fill_trusted_keys()
103 char path[PATH_MAX], *e;
105 e = stpcpy(path, CA_ROOT_DIRECTORY);
108 syslog(LOG_ERR, "opendir %s failed in fill_trusted_keys", path);
114 while (ent != NULL) {
115 if (ent->d_type == DT_REG) {
116 strcpy(e, ent->d_name);
117 err = xmlSecCryptoAppKeysMngrCertLoad(keymgr, path, xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted);
119 syslog(LOG_ERR, "xmlSecCryptoAppKeysMngrCertLoadMemory failed for %s", path);
132 /* initialisation of access to xmlsec */
142 if(xmlSecInit() < 0) {
143 syslog(LOG_ERR, "xmlSecInit failed.");
147 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
148 if(xmlSecCryptoDLLoadLibrary(XMLSEC_CRYPTO) < 0) {
149 syslog(LOG_ERR, "xmlSecCryptoDLLoadLibrary %s failed.", XMLSEC_CRYPTO);
154 if(xmlSecCryptoAppInit(NULL) < 0) {
155 syslog(LOG_ERR, "xmlSecCryptoAppInit failed.");
159 if(xmlSecCryptoInit() < 0) {
160 syslog(LOG_ERR, "xmlSecCryptoInit failed.");
164 xmlSecErrorsSetCallback(errors_cb);
166 xmlSecIOCleanupCallbacks();
167 if (xmlSecIORegisterCallbacks(file_match_cb,
168 file_open_cb, file_read_cb, file_close_cb)) {
169 syslog(LOG_ERR, "xmlSecIORegisterCallbacks failed.");
173 keymgr = xmlSecKeysMngrCreate();
174 if (keymgr == NULL) {
175 syslog(LOG_ERR, "xmlSecKeysMngrCreate failed.");
179 if(xmlSecCryptoAppDefaultKeysMngrInit(keymgr) < 0) {
180 syslog(LOG_ERR, "xmlSecCryptoAppDefaultKeysMngrInit failed.");
190 /* shuting down accesses to xmlsec */
191 void xmlsec_shutdown()
193 xmlSecKeysMngrDestroy(keymgr);
195 xmlSecCryptoShutdown();
197 xmlSecCryptoAppShutdown();
202 /* verify a signature */
203 int xmlsec_verify(xmlNodePtr node)
206 xmlSecDSigCtxPtr dsigctx;
208 assert(initdone && !initstatus);
210 dsigctx = xmlSecDSigCtxCreate(keymgr);
211 if (dsigctx == NULL) {
212 syslog(LOG_ERR, "xmlSecDSigCtxCreate failed.");
215 rc = xmlSecDSigCtxVerify(dsigctx, node);
217 syslog(LOG_ERR, "xmlSecDSigCtxVerify failed.");
218 else if (dsigctx->status != xmlSecDSigStatusSucceeded) {
219 syslog(LOG_ERR, "invalid signature.");
222 xmlSecDSigCtxDestroy(dsigctx);
228 /* templates for properties of signature files */
229 static const struct { const char *id; const char *xml; } properties[2] = {
231 .id = "AuthorSignature", /* template of properties for author signature */
233 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
234 "<SignatureProperty Id=\"profile\" Target=\"#AuthorSignature\">"
235 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
236 "</SignatureProperty>"
237 "<SignatureProperty Id=\"role\" Target=\"#AuthorSignature\">"
238 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-author\"></dsp:Role>"
239 "</SignatureProperty>"
240 "<SignatureProperty Id=\"identifier\" Target=\"#AuthorSignature\">"
241 "<dsp:Identifier></dsp:Identifier>"
242 "</SignatureProperty>"
243 "</SignatureProperties>"
246 .id = "DistributorSignature", /* template of properties for distributor signature */
248 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
249 "<SignatureProperty Id=\"profile\" Target=\"#DistributorSignature\">"
250 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
251 "</SignatureProperty>"
252 "<SignatureProperty Id=\"role\" Target=\"#DistributorSignature\">"
253 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-distributor\"></dsp:Role>"
254 "</SignatureProperty>"
255 "<SignatureProperty Id=\"identifier\" Target=\"#DistributorSignature\">"
256 "<dsp:Identifier></dsp:Identifier>"
257 "</SignatureProperty>"
258 "</SignatureProperties>"
262 /* create a signature of 'index' (0 for author, other values for distributors)
263 using the private 'key' (filename) and the certificates 'certs' (filenames)
265 xmlDocPtr xmlsec_create(int index, const char *key, const char **certs)
267 unsigned int i, fc, mask;
268 struct filedesc *fdesc;
269 xmlNodePtr sign, obj, ref, kinfo, props;
272 xmlSecDSigCtxPtr dsigctx;
274 assert(initdone && !initstatus);
276 /* create the document */
277 doc = xmlNewDoc("1.0");
279 syslog(LOG_ERR, "xmlNewDoc failed");
283 /* create the root signature node */
284 sign = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14N11Id, xmlSecTransformRsaSha256Id, properties[!!index].id);
286 syslog(LOG_ERR, "xmlSecTmplSignatureCreate failed");
289 xmlDocSetRootElement(doc, sign);
291 /* create the object and its reference */
292 obj = xmlSecTmplSignatureAddObject(sign, "prop", NULL, NULL);
294 syslog(LOG_ERR, "xmlSecTmplSignatureAddObject failed");
297 rc = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, properties[!!index].xml, &props);
299 syslog(LOG_ERR, "xmlParseBalancedChunkMemory failed");
302 if (NULL == xmlAddChild(obj, props)) {
303 syslog(LOG_ERR, "filling object node failed");
308 /* create references to files */
309 mask = index ? flag_distributor_signature : flag_signature;
311 for (i = 0 ; i < fc ; i++) {
312 fdesc = file_of_index(i);
313 if (fdesc->type == type_file && (fdesc->flags & mask) == 0) {
314 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, fdesc->name, NULL);
316 syslog(LOG_ERR, "creation of reference to %s failed", fdesc->name);
322 /* create reference to object having properties */
323 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, "#prop", NULL);
325 syslog(LOG_ERR, "creation of reference to #prop failed");
328 if (NULL == xmlSecTmplReferenceAddTransform(ref, xmlSecTransformInclC14N11Id)) {
329 syslog(LOG_ERR, "setting transform reference to #prop failed");
333 /* adds the X509 data */
334 kinfo = xmlSecTmplSignatureEnsureKeyInfo(sign, NULL);
336 syslog(LOG_ERR, "xmlSecTmplSignatureEnsureKeyInfo failed");
339 if (NULL == xmlSecTmplKeyInfoAddX509Data(kinfo)) {
340 syslog(LOG_ERR, "xmlSecTmplKeyInfoAddX509Data failed");
345 dsigctx = xmlSecDSigCtxCreate(keymgr);
346 if (dsigctx == NULL) {
347 syslog(LOG_ERR, "xmlSecDSigCtxCreate failed.");
350 dsigctx->signKey = xmlSecCryptoAppKeyLoad(key, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
351 if (dsigctx->signKey == NULL) {
352 syslog(LOG_ERR, "loading key %s failed.", key);
356 if(xmlSecCryptoAppKeyCertLoad(dsigctx->signKey, *certs, xmlSecKeyDataFormatPem) < 0) {
357 syslog(LOG_ERR, "loading certificate %s failed.", *certs);
362 if(xmlSecDSigCtxSign(dsigctx, sign) < 0) {
363 syslog(LOG_ERR, "signing the document failed.");
366 xmlSecDSigCtxDestroy(dsigctx);
370 xmlSecDSigCtxDestroy(dsigctx);