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 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
136 if(xmlSecCryptoDLLoadLibrary(XMLSEC_CRYPTO) < 0) {
137 syslog(LOG_ERR, "xmlSecCryptoDLLoadLibrary %s failed.", XMLSEC_CRYPTO);
142 if(xmlSecCryptoAppInit(NULL) < 0) {
143 syslog(LOG_ERR, "xmlSecCryptoAppInit failed.");
147 if(xmlSecCryptoInit() < 0) {
148 syslog(LOG_ERR, "xmlSecCryptoInit failed.");
152 xmlSecErrorsSetCallback(errors_cb);
154 xmlSecIOCleanupCallbacks();
155 if (xmlSecIORegisterCallbacks(file_match_cb,
156 file_open_cb, file_read_cb, file_close_cb)) {
157 syslog(LOG_ERR, "xmlSecIORegisterCallbacks failed.");
161 keymgr = xmlSecKeysMngrCreate();
162 if (keymgr == NULL) {
163 syslog(LOG_ERR, "xmlSecKeysMngrCreate failed.");
167 if(xmlSecCryptoAppDefaultKeysMngrInit(keymgr) < 0) {
168 syslog(LOG_ERR, "xmlSecCryptoAppDefaultKeysMngrInit failed.");
179 void xmlsec_shutdown()
181 xmlSecKeysMngrDestroy(keymgr);
183 xmlSecCryptoShutdown();
185 xmlSecCryptoAppShutdown();
190 int xmlsec_verify(xmlNodePtr node)
193 xmlSecDSigCtxPtr dsigctx;
195 assert(initdone && !initstatus);
197 dsigctx = xmlSecDSigCtxCreate(keymgr);
198 if (dsigctx == NULL) {
199 syslog(LOG_ERR, "xmlSecDSigCtxCreate failed.");
202 rc = xmlSecDSigCtxVerify(dsigctx, node);
204 syslog(LOG_ERR, "xmlSecDSigCtxVerify failed.");
205 else if (dsigctx->status != xmlSecDSigStatusSucceeded) {
206 syslog(LOG_ERR, "invalid signature.");
209 xmlSecDSigCtxDestroy(dsigctx);
215 static const struct { const char *id; const char *xml; } properties[2] = {
217 .id = "AuthorSignature",
219 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
220 "<SignatureProperty Id=\"profile\" Target=\"#AuthorSignature\">"
221 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
222 "</SignatureProperty>"
223 "<SignatureProperty Id=\"role\" Target=\"#AuthorSignature\">"
224 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-author\"></dsp:Role>"
225 "</SignatureProperty>"
226 "<SignatureProperty Id=\"identifier\" Target=\"#AuthorSignature\">"
227 "<dsp:Identifier></dsp:Identifier>"
228 "</SignatureProperty>"
229 "</SignatureProperties>"
232 .id = "DistributorSignature",
234 "<SignatureProperties xmlns:dsp=\"http://www.w3.org/2009/xmldsig-properties\">"
235 "<SignatureProperty Id=\"profile\" Target=\"#DistributorSignature\">"
236 "<dsp:Profile URI=\"http://www.w3.org/ns/widgets-digsig#profile\"></dsp:Profile>"
237 "</SignatureProperty>"
238 "<SignatureProperty Id=\"role\" Target=\"#DistributorSignature\">"
239 "<dsp:Role URI=\"http://www.w3.org/ns/widgets-digsig#role-distributor\"></dsp:Role>"
240 "</SignatureProperty>"
241 "<SignatureProperty Id=\"identifier\" Target=\"#DistributorSignature\">"
242 "<dsp:Identifier></dsp:Identifier>"
243 "</SignatureProperty>"
244 "</SignatureProperties>"
248 xmlDocPtr xmlsec_create(int index, const char *key, const char **certs)
250 unsigned int i, fc, mask;
251 struct filedesc *fdesc;
252 xmlNodePtr sign, obj, ref, kinfo, props;
255 xmlSecDSigCtxPtr dsigctx;
257 assert(initdone && !initstatus);
259 /* create the document */
260 doc = xmlNewDoc("1.0");
262 syslog(LOG_ERR, "xmlNewDoc failed");
266 /* create the root signature node */
267 sign = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14N11Id, xmlSecTransformRsaSha256Id, properties[!!index].id);
269 syslog(LOG_ERR, "xmlSecTmplSignatureCreate failed");
272 xmlDocSetRootElement(doc, sign);
274 /* create the object and its reference */
275 obj = xmlSecTmplSignatureAddObject(sign, "prop", NULL, NULL);
277 syslog(LOG_ERR, "xmlSecTmplSignatureAddObject failed");
280 rc = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, properties[!!index].xml, &props);
282 syslog(LOG_ERR, "xmlParseBalancedChunkMemory failed");
285 if (NULL == xmlAddChild(obj, props)) {
286 syslog(LOG_ERR, "filling object node failed");
291 /* create references to files */
292 mask = index ? flag_distributor_signature : flag_signature;
294 for (i = 0 ; i < fc ; i++) {
295 fdesc = file_of_index(i);
296 if (fdesc->type == type_file && (fdesc->flags & mask) == 0) {
297 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, fdesc->name, NULL);
299 syslog(LOG_ERR, "creation of reference to %s failed", fdesc->name);
305 /* create reference to object having properties */
306 ref = xmlSecTmplSignatureAddReference(sign, xmlSecTransformSha256Id, NULL, "#prop", NULL);
308 syslog(LOG_ERR, "creation of reference to #prop failed");
311 if (NULL == xmlSecTmplReferenceAddTransform(ref, xmlSecTransformInclC14N11Id)) {
312 syslog(LOG_ERR, "setting transform reference to #prop failed");
316 /* adds the X509 data */
317 kinfo = xmlSecTmplSignatureEnsureKeyInfo(sign, NULL);
319 syslog(LOG_ERR, "xmlSecTmplSignatureEnsureKeyInfo failed");
322 if (NULL == xmlSecTmplKeyInfoAddX509Data(kinfo)) {
323 syslog(LOG_ERR, "xmlSecTmplKeyInfoAddX509Data failed");
328 dsigctx = xmlSecDSigCtxCreate(keymgr);
329 if (dsigctx == NULL) {
330 syslog(LOG_ERR, "xmlSecDSigCtxCreate failed.");
333 dsigctx->signKey = xmlSecCryptoAppKeyLoad(key, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
334 if (dsigctx->signKey == NULL) {
335 syslog(LOG_ERR, "loading key %s failed.", key);
339 if(xmlSecCryptoAppKeyCertLoad(dsigctx->signKey, *certs, xmlSecKeyDataFormatPem) < 0) {
340 syslog(LOG_ERR, "loading certificate %s failed.", *certs);
345 if(xmlSecDSigCtxSign(dsigctx, sign) < 0) {
346 syslog(LOG_ERR, "signing the document failed.");
349 xmlSecDSigCtxDestroy(dsigctx);
353 xmlSecDSigCtxDestroy(dsigctx);