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>
38 static int initstatus;
40 static xmlSecKeysMngrPtr keymgr;
42 static const char trusted_certificates_directory[] = WGTPKG_TRUSTED_CERT_DIR;
44 /* checks if a file match uri (should not be a distributor signature) */
45 static int file_match_cb(const char *uri)
47 struct filedesc *fdesc = file_of_name(uri);
48 return fdesc != NULL && fdesc->type == type_file && (fdesc->flags & flag_distributor_signature) == 0;
51 /* open the file of uri */
52 static void *file_open_cb(const char *file)
54 struct filedesc *fdesc;
58 fdesc = file_of_name(file);
60 ERROR("shouldn't open uri %s", file);
64 fd = openat(workdirfd, file, O_RDONLY);
65 f = fd < 0 ? NULL : fdopen(fd, "r");
67 ERROR("can't open file %s for reading", file);
71 fdesc->flags |= flag_opened;
76 /* read the opened file */
77 static int file_read_cb(void *context, char *buffer, int len)
79 size_t r = fread(buffer, 1, len, (FILE*)context);
80 return r ? (int)r : feof((FILE*)context) ? 0 : - 1;
83 /* close the opened file */
84 static int file_close_cb(void *context)
86 return (int)fclose((FILE*)context);
89 /* echo an error message */
90 static void errors_cb(const char *file, int line, const char *func, const char *errorObject, const char *errorSubject, int reason, const char *msg)
92 ERROR("xmlSec error %3d: %s (subject=\"%s\", object=\"%s\")", reason, msg, errorSubject ? errorSubject : "?", errorObject ? errorObject : "?");
95 /* fills database with trusted keys */
96 static int fill_trusted_keys_file(const char *file)
98 int err = xmlSecCryptoAppKeysMngrCertLoad(keymgr, file, xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted);
100 ERROR("xmlSecCryptoAppKeysMngrCertLoadMemory failed for %s", file);
106 /* fills database with trusted keys */
107 static int fill_trusted_keys_dir(const char *directory)
112 char path[PATH_MAX], *e;
114 e = stpcpy(path, directory);
117 ERROR("opendir %s failed in fill_trusted_keys_dir", path);
123 while (ent != NULL) {
124 if (ent->d_type == DT_REG) {
125 strcpy(e, ent->d_name);
126 err = fill_trusted_keys_file(path);
140 /* initialisation of access to xmlsec */
150 if(xmlSecInit() < 0) {
151 ERROR("xmlSecInit failed.");
155 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
156 if(xmlSecCryptoDLLoadLibrary(XMLSEC_CRYPTO) < 0) {
157 ERROR("xmlSecCryptoDLLoadLibrary %s failed.", XMLSEC_CRYPTO);
162 if(xmlSecCryptoAppInit(NULL) < 0) {
163 ERROR("xmlSecCryptoAppInit failed.");
167 if(xmlSecCryptoInit() < 0) {
168 ERROR("xmlSecCryptoInit failed.");
172 xmlSecErrorsSetCallback(errors_cb);
174 xmlSecIOCleanupCallbacks();
175 if (xmlSecIORegisterCallbacks(file_match_cb,
176 file_open_cb, file_read_cb, file_close_cb)) {
177 ERROR("xmlSecIORegisterCallbacks failed.");
181 keymgr = xmlSecKeysMngrCreate();
182 if (keymgr == NULL) {
183 ERROR("xmlSecKeysMngrCreate failed.");
187 if(xmlSecCryptoAppDefaultKeysMngrInit(keymgr) < 0) {
188 ERROR("xmlSecCryptoAppDefaultKeysMngrInit failed.");
191 fill_trusted_keys_dir(trusted_certificates_directory);
198 /* shuting down accesses to xmlsec */
199 void xmlsec_shutdown()
201 xmlSecKeysMngrDestroy(keymgr);
203 xmlSecCryptoShutdown();
205 xmlSecCryptoAppShutdown();
210 /* verify a signature */
211 int xmlsec_verify(xmlNodePtr node)
214 xmlSecDSigCtxPtr dsigctx;
216 assert(initdone && !initstatus);
218 dsigctx = xmlSecDSigCtxCreate(keymgr);
219 if (dsigctx == NULL) {
220 ERROR("xmlSecDSigCtxCreate failed.");
223 rc = xmlSecDSigCtxVerify(dsigctx, node);
225 ERROR("xmlSecDSigCtxVerify failed.");
226 else if (dsigctx->status != xmlSecDSigStatusSucceeded) {
227 ERROR("invalid signature.");
230 xmlSecDSigCtxDestroy(dsigctx);
236 /* templates for properties of signature files */
237 static const struct { const char *id; const char *xml; } properties[2] = {
239 .id = "AuthorSignature", /* template of properties for author signature */
241 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
242 "<SignatureProperty Id=\"profile\" Target=\"#AuthorSignature\">"
243 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
244 "</SignatureProperty>"
245 "<SignatureProperty Id=\"role\" Target=\"#AuthorSignature\">"
246 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-author\"></dsp:Role>"
247 "</SignatureProperty>"
248 "<SignatureProperty Id=\"identifier\" Target=\"#AuthorSignature\">"
249 "<dsp:Identifier></dsp:Identifier>"
250 "</SignatureProperty>"
251 "</SignatureProperties>"
254 .id = "DistributorSignature", /* template of properties for distributor signature */
256 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
257 "<SignatureProperty Id=\"profile\" Target=\"#DistributorSignature\">"
258 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
259 "</SignatureProperty>"
260 "<SignatureProperty Id=\"role\" Target=\"#DistributorSignature\">"
261 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-distributor\"></dsp:Role>"
262 "</SignatureProperty>"
263 "<SignatureProperty Id=\"identifier\" Target=\"#DistributorSignature\">"
264 "<dsp:Identifier></dsp:Identifier>"
265 "</SignatureProperty>"
266 "</SignatureProperties>"
270 /* create a signature of 'index' (0 for author, other values for distributors)
271 using the private 'key' (filename) and the certificates 'certs' (filenames)
273 xmlDocPtr xmlsec_create(int index, const char *key, const char **certs)
275 unsigned int i, fc, mask;
276 struct filedesc *fdesc;
277 xmlNodePtr sign, obj, ref, kinfo, props;
280 xmlSecDSigCtxPtr dsigctx;
282 assert(initdone && !initstatus);
284 /* create the document */
285 doc = xmlNewDoc("1.0");
287 ERROR("xmlNewDoc failed");
291 /* create the root signature node */
292 sign = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14N11Id, xmlSecTransformRsaSha256Id, properties[!!index].id);
294 ERROR("xmlSecTmplSignatureCreate failed");
297 xmlDocSetRootElement(doc, sign);
299 /* create the object and its reference */
300 obj = xmlSecTmplSignatureAddObject(sign, "prop", NULL, NULL);
302 ERROR("xmlSecTmplSignatureAddObject failed");
305 rc = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, properties[!!index].xml, &props);
307 ERROR("xmlParseBalancedChunkMemory failed");
310 if (NULL == xmlAddChild(obj, props)) {
311 ERROR("filling object node failed");
316 /* create references to files */
317 mask = index ? flag_distributor_signature : flag_signature;
319 for (i = 0 ; i < fc ; i++) {
320 fdesc = file_of_index(i);
321 if (fdesc->type == type_file && (fdesc->flags & mask) == 0) {
322 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, fdesc->name, NULL);
324 ERROR("creation of reference to %s failed", fdesc->name);
330 /* create reference to object having properties */
331 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, "#prop", NULL);
333 ERROR("creation of reference to #prop failed");
336 if (NULL == xmlSecTmplReferenceAddTransform(ref, xmlSecTransformInclC14N11Id)) {
337 ERROR("setting transform reference to #prop failed");
341 /* adds the X509 data */
342 kinfo = xmlSecTmplSignatureEnsureKeyInfo(sign, NULL);
344 ERROR("xmlSecTmplSignatureEnsureKeyInfo failed");
347 if (NULL == xmlSecTmplKeyInfoAddX509Data(kinfo)) {
348 ERROR("xmlSecTmplKeyInfoAddX509Data failed");
353 dsigctx = xmlSecDSigCtxCreate(keymgr);
354 if (dsigctx == NULL) {
355 ERROR("xmlSecDSigCtxCreate failed.");
358 dsigctx->signKey = xmlSecCryptoAppKeyLoad(key, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
359 if (dsigctx->signKey == NULL) {
360 ERROR("loading key %s failed.", key);
364 if(xmlSecCryptoAppKeyCertLoad(dsigctx->signKey, *certs, xmlSecKeyDataFormatPem) < 0) {
365 ERROR("loading certificate %s failed.", *certs);
370 if(xmlSecDSigCtxSign(dsigctx, sign) < 0) {
371 ERROR("signing the document failed.");
374 xmlSecDSigCtxDestroy(dsigctx);
378 xmlSecDSigCtxDestroy(dsigctx);