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 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 static void *file_open_cb(const char *file)
53 struct filedesc *fdesc;
56 fdesc = file_of_name(file);
58 syslog(LOG_ERR, "shouldn't open uri %s", file);
64 syslog(LOG_ERR, "can't open file %s for reading", file);
66 fdesc->flags |= flag_opened;
71 static int file_read_cb(void *context, char *buffer, int len)
73 size_t r = fread(buffer, 1, len, (FILE*)context);
74 return r ? (int)r : feof((FILE*)context) ? 0 : - 1;
77 static int file_close_cb(void *context)
79 return (int)fclose((FILE*)context);
82 static void errors_cb(const char *file, int line, const char *func, const char *errorObject, const char *errorSubject, int reason, const char *msg)
84 syslog(LOG_ERR, "xmlSec error %3d: %s (subject=\"%s\", object=\"%s\")", reason, msg, errorSubject ? errorSubject : "?", errorObject ? errorObject : "?");
87 static int fill_trusted_keys()
92 char path[PATH_MAX], *e;
94 e = stpcpy(path, CA_ROOT_DIRECTORY);
97 syslog(LOG_ERR, "opendir %s failed in fill_trusted_keys", path);
103 while (ent != NULL) {
104 if (ent->d_type == DT_REG) {
105 strcpy(e, ent->d_name);
106 err = xmlSecCryptoAppKeysMngrCertLoad(keymgr, path, xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted);
108 syslog(LOG_ERR, "xmlSecCryptoAppKeysMngrCertLoadMemory failed for %s", path);
130 if(xmlSecInit() < 0) {
131 syslog(LOG_ERR, "xmlSecInit failed.");
135 if(xmlSecCryptoAppInit(NULL) < 0) {
136 syslog(LOG_ERR, "xmlSecCryptoAppInit failed.");
140 if(xmlSecCryptoInit() < 0) {
141 syslog(LOG_ERR, "xmlSecCryptoInit failed.");
145 xmlSecErrorsSetCallback(errors_cb);
147 xmlSecIOCleanupCallbacks();
148 if (xmlSecIORegisterCallbacks(file_match_cb,
149 file_open_cb, file_read_cb, file_close_cb)) {
150 syslog(LOG_ERR, "xmlSecIORegisterCallbacks failed.");
154 keymgr = xmlSecKeysMngrCreate();
155 if (keymgr == NULL) {
156 syslog(LOG_ERR, "xmlSecKeysMngrCreate failed.");
160 if(xmlSecCryptoAppDefaultKeysMngrInit(keymgr) < 0) {
161 syslog(LOG_ERR, "xmlSecCryptoAppDefaultKeysMngrInit failed.");
172 void xmlsec_shutdown()
174 xmlSecKeysMngrDestroy(keymgr);
176 xmlSecCryptoShutdown();
178 xmlSecCryptoAppShutdown();
183 int xmlsec_verify(xmlNodePtr node)
186 xmlSecDSigCtxPtr dsigctx;
188 assert(initdone && !initstatus);
190 dsigctx = xmlSecDSigCtxCreate(keymgr);
191 if (dsigctx == NULL) {
192 syslog(LOG_ERR, "xmlSecDSigCtxCreate failed.");
195 rc = xmlSecDSigCtxVerify(dsigctx, node);
197 syslog(LOG_ERR, "xmlSecDSigCtxVerify failed.");
198 else if (dsigctx->status != xmlSecDSigStatusSucceeded) {
199 syslog(LOG_ERR, "invalid signature.");
202 xmlSecDSigCtxDestroy(dsigctx);
208 static const struct { const char *id; const char *xml; } properties[2] = {
210 .id = "AuthorSignature",
212 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
213 "<SignatureProperty Id=\"profile\" Target=\"#AuthorSignature\">"
214 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
215 "</SignatureProperty>"
216 "<SignatureProperty Id=\"role\" Target=\"#AuthorSignature\">"
217 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-author\"></dsp:Role>"
218 "</SignatureProperty>"
219 "<SignatureProperty Id=\"identifier\" Target=\"#AuthorSignature\">"
220 "<dsp:Identifier></dsp:Identifier>"
221 "</SignatureProperty>"
222 "</SignatureProperties>"
225 .id = "DistributorSignature",
227 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
228 "<SignatureProperty Id=\"profile\" Target=\"#DistributorSignature\">"
229 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
230 "</SignatureProperty>"
231 "<SignatureProperty Id=\"role\" Target=\"#DistributorSignature\">"
232 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-distributor\"></dsp:Role>"
233 "</SignatureProperty>"
234 "<SignatureProperty Id=\"identifier\" Target=\"#DistributorSignature\">"
235 "<dsp:Identifier></dsp:Identifier>"
236 "</SignatureProperty>"
237 "</SignatureProperties>"
241 xmlDocPtr xmlsec_create(int index, const char *key, const char **certs)
243 unsigned int i, fc, mask;
244 struct filedesc *fdesc;
245 xmlNodePtr sign, obj, ref, kinfo, props;
248 xmlSecDSigCtxPtr dsigctx;
250 assert(initdone && !initstatus);
252 /* create the document */
253 doc = xmlNewDoc("1.0");
255 syslog(LOG_ERR, "xmlNewDoc failed");
259 /* create the root signature node */
260 sign = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14N11Id, xmlSecTransformRsaSha256Id, properties[!!index].id);
262 syslog(LOG_ERR, "xmlSecTmplSignatureCreate failed");
265 xmlDocSetRootElement(doc, sign);
267 /* create the object and its reference */
268 obj = xmlSecTmplSignatureAddObject(sign, "prop", NULL, NULL);
270 syslog(LOG_ERR, "xmlSecTmplSignatureAddObject failed");
273 rc = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, properties[!!index].xml, &props);
275 syslog(LOG_ERR, "xmlParseBalancedChunkMemory failed");
278 if (NULL == xmlAddChild(obj, props)) {
279 syslog(LOG_ERR, "filling object node failed");
284 /* create references to files */
285 mask = index ? flag_distributor_signature : flag_signature;
287 for (i = 0 ; i < fc ; i++) {
288 fdesc = file_of_index(i);
289 if (fdesc->type == type_file && (fdesc->flags & mask) == 0) {
290 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, fdesc->name, NULL);
292 syslog(LOG_ERR, "creation of reference to %s failed", fdesc->name);
298 /* create reference to object having properties */
299 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, "#prop", NULL);
301 syslog(LOG_ERR, "creation of reference to #prop failed");
304 if (NULL == xmlSecTmplReferenceAddTransform(ref, xmlSecTransformInclC14N11Id)) {
305 syslog(LOG_ERR, "setting transform reference to #prop failed");
309 /* adds the X509 data */
310 kinfo = xmlSecTmplSignatureEnsureKeyInfo(sign, NULL);
312 syslog(LOG_ERR, "xmlSecTmplSignatureEnsureKeyInfo failed");
315 if (NULL == xmlSecTmplKeyInfoAddX509Data(kinfo)) {
316 syslog(LOG_ERR, "xmlSecTmplKeyInfoAddX509Data failed");
321 dsigctx = xmlSecDSigCtxCreate(keymgr);
322 if (dsigctx == NULL) {
323 syslog(LOG_ERR, "xmlSecDSigCtxCreate failed.");
326 dsigctx->signKey = xmlSecCryptoAppKeyLoad(key, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
327 if (dsigctx->signKey == NULL) {
328 syslog(LOG_ERR, "loading key %s failed.", key);
332 if(xmlSecCryptoAppKeyCertLoad(dsigctx->signKey, *certs, xmlSecKeyDataFormatPem) < 0) {
333 syslog(LOG_ERR, "loading certificate %s failed.", *certs);
338 if(xmlSecDSigCtxSign(dsigctx, sign) < 0) {
339 syslog(LOG_ERR, "signing the document failed.");
342 xmlSecDSigCtxDestroy(dsigctx);
346 xmlSecDSigCtxDestroy(dsigctx);