facho-signer: se adicionan digest de certificados
FossilOrigin-Name: 86d510a9c5ea4bf2ec5e297d9fb9fbc04b99761bd62f364b4d32dc749a1cf3bc
This commit is contained in:
parent
ebc67d1327
commit
a320b5a7b0
experimental/facho-signer
@ -6,10 +6,12 @@ CFLAGS = -Wall -Werror -std=gnu11
|
||||
CFLAGS += $(shell pkg-config libxml-2.0 --cflags)
|
||||
CFLAGS += $(shell pkg-config xmlsec1 --cflags)
|
||||
CFLAGS += $(shell pkg-config xmlsec1-openssl --cflags)
|
||||
CFLAGS += -Ixades
|
||||
|
||||
LDFLAGS = $(shell pkg-config libxml-2.0 --libs)
|
||||
LDFLAGS += $(shell pkg-config xmlsec1 --libs)
|
||||
LDFLAGS += $(shell pkg-config xmlsec1-openssl --libs)
|
||||
LDFLAGS += xades/templates.c xades/xades.c
|
||||
|
||||
facho-signer: crypto.c facho-signer.c
|
||||
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "xades/xades.h"
|
||||
|
||||
#include <xmlsec/xmlsec.h>
|
||||
#include <xmlsec/xmltree.h>
|
||||
@ -8,6 +6,9 @@
|
||||
#include <xmlsec/templates.h>
|
||||
#include <xmlsec/crypto.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define print_error(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
|
||||
#define print_info(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
|
||||
@ -20,6 +21,76 @@ char *basename = NULL;
|
||||
xmlNodePtr
|
||||
xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc);
|
||||
|
||||
int
|
||||
xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) {
|
||||
xmlNodePtr qualifyingPropertiesNode = NULL;
|
||||
xmlNodePtr signedPropertiesNode = NULL;
|
||||
xmlNodePtr signedSignaturePropertiesNode = NULL;
|
||||
xmlNodePtr signingCertificateNode = NULL;
|
||||
xmlNodePtr signaturePolicyIdentifierNode = NULL;
|
||||
xmlNodePtr signerRoleNode = NULL;
|
||||
xmlNodePtr refNode = NULL;
|
||||
const xmlChar signedPropertiesId[] = "xmldsig-facho-signed-props";
|
||||
const xmlChar signedPropertiesRef[] = "#xmldsig-facho-signed-props";
|
||||
|
||||
qualifyingPropertiesNode = xmlXadesTmplQualifyingPropertiesCreate(doc, signNode, BAD_CAST "xades-ref1");
|
||||
if ( qualifyingPropertiesNode == NULL ) {
|
||||
print_error("error: failed to add QualifyingProperties node.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
signedPropertiesNode = xmlXadesTmplAddSignedProperties(qualifyingPropertiesNode, signedPropertiesId);
|
||||
if ( signedPropertiesNode == NULL ) {
|
||||
print_error("error: xades failed to add signed properties node.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
refNode = xmlSecTmplSignatureAddReference(signNode,
|
||||
xmlSecTransformSha256Id,
|
||||
BAD_CAST "xmldsig-facho-ref1",
|
||||
signedPropertiesRef,
|
||||
BAD_CAST "http://uri.etsi.org/01903#SignedProperties");
|
||||
if ( refNode == NULL ) {
|
||||
print_error("error: failed to add reference to signature template xades.\n");
|
||||
goto fail;
|
||||
}
|
||||
if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformInclC14NId) == NULL ) {
|
||||
print_error("error: failed to add enveloped transform to reference for xades\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
const time_t now = time(NULL);
|
||||
signedSignaturePropertiesNode = xmlXadesTmplAddSignedSignatureProperties(signedPropertiesNode, localtime(&now));
|
||||
if ( signedSignaturePropertiesNode == NULL ) {
|
||||
print_error("error: xades failed to add signed signature properties node.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
signingCertificateNode = xmlXadesTmplAddSigningCertificate(signedSignaturePropertiesNode, xmlSecTransformSha256Id);
|
||||
if ( signingCertificateNode == NULL ) {
|
||||
print_error("error: failed to add SigningCertificate node \n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
signaturePolicyIdentifierNode = xmlXadesTmplAddSignaturePolicyIdentifier(signedSignaturePropertiesNode);
|
||||
if ( signaturePolicyIdentifierNode == NULL ) {
|
||||
print_error("error: failed to add PolicyIdentifier node\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
signerRoleNode = xmlXadesTmplAddSignerRole(signedSignaturePropertiesNode, BAD_CAST "supplier");
|
||||
if ( signerRoleNode == NULL ) {
|
||||
print_error("error: failed to add SignerRole node.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return(0);
|
||||
fail:
|
||||
xmlUnlinkNode(qualifyingPropertiesNode);
|
||||
xmlFreeNode(qualifyingPropertiesNode);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int
|
||||
xmlXadesAppInit() {
|
||||
xmlInitParser();
|
||||
@ -107,6 +178,7 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw
|
||||
xmlNodePtr x509DataNode = NULL;
|
||||
xmlNodePtr node = NULL;
|
||||
xmlSecDSigCtxPtr dsigCtx = NULL;
|
||||
xmlXadesDSigCtxPtr xadesDsigCtx = NULL;
|
||||
|
||||
int res = -1;
|
||||
|
||||
@ -170,6 +242,12 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
if ( xmlFachoTmplXadesCreate(doc, signNode) < 0 ){
|
||||
print_error("error: xmlFachoTmplXadesCreate failed.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
dsigCtx = xmlSecDSigCtxCreate(NULL);
|
||||
if ( dsigCtx == NULL ) {
|
||||
print_error("error: dsig context creating failed\n");
|
||||
@ -185,7 +263,13 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( xmlSecDSigCtxSign(dsigCtx, signNode) < 0 ) {
|
||||
xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx);
|
||||
if ( xadesDsigCtx == NULL ) {
|
||||
print_error("error: xades context creating failed.\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if ( xmlXadesDSigCtxSign(xadesDsigCtx, signNode) < 0 ) {
|
||||
print_error("error: signature failed\n");
|
||||
goto done;
|
||||
}
|
||||
@ -203,6 +287,10 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw
|
||||
res = 0;
|
||||
|
||||
done:
|
||||
if ( xadesDsigCtx != NULL ) {
|
||||
xmlXadesDSigCtxDestroy(xadesDsigCtx);
|
||||
}
|
||||
|
||||
if ( dsigCtx != NULL ) {
|
||||
xmlSecDSigCtxDestroy(dsigCtx);
|
||||
}
|
||||
|
422
experimental/facho-signer/xades/templates.c
Normal file
422
experimental/facho-signer/xades/templates.c
Normal file
@ -0,0 +1,422 @@
|
||||
#include "xades.h"
|
||||
|
||||
#include <xmlsec/templates.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static xmlNodePtr
|
||||
xmlXadesTmplAddDigest(xmlNodePtr parentNode, const xmlChar *digestMethod, const xmlChar *digestValue);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesAddChildRecursiveNs(xmlNodePtr startNode, const xmlChar* path, const xmlChar* nsPrefix) {
|
||||
char *curToken;
|
||||
char* cpath = strdup((char *)path);
|
||||
char* savePtr;
|
||||
xmlNodePtr curNode = NULL;
|
||||
xmlNodePtr parentNode = startNode;
|
||||
|
||||
|
||||
curToken = strtok_r(cpath, "/", &savePtr);
|
||||
while(curToken != NULL) {
|
||||
curNode = xmlSecFindChild(parentNode, BAD_CAST curToken, nsPrefix);
|
||||
if (curNode == NULL) {
|
||||
curNode = xmlSecAddChild(parentNode, BAD_CAST curToken, nsPrefix);
|
||||
if (curNode == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(%s)", curToken);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
parentNode = curNode;
|
||||
|
||||
curToken = strtok_r(NULL, "/", &savePtr);
|
||||
}
|
||||
|
||||
free(cpath);
|
||||
return(curNode);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplQualifyingPropertiesCreate(xmlDocPtr doc, xmlNodePtr signatureNode, const xmlChar *id) {
|
||||
xmlNodePtr objectNode;
|
||||
xmlNodePtr qualifyingPropertiesNode;
|
||||
|
||||
xmlNewGlobalNs(doc, xmlXadesDSigNs, BAD_CAST "xades");
|
||||
|
||||
objectNode = xmlSecTmplSignatureAddObject(signatureNode, NULL, NULL, NULL);
|
||||
if (objectNode == NULL) {
|
||||
xmlXadesInternalError("xmlSecTmplSignatureAddObject(signatureNode)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
qualifyingPropertiesNode = xmlSecAddChild(objectNode, xmlXadesNodeQualifyingProperties, xmlXadesDSigNs);
|
||||
if (qualifyingPropertiesNode == NULL) {
|
||||
xmlXadesXmlError2("xmlNewDocNode", NULL, "node=%s", xmlXadesErrorsSafeString(xmlXadesNodeQualifyingProperties));
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (id != NULL) {
|
||||
xmlSetProp(qualifyingPropertiesNode, BAD_CAST "Id", id);
|
||||
}
|
||||
|
||||
return(qualifyingPropertiesNode);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplQualifyingPropertiesCreateNsPref(xmlDocPtr doc, const xmlChar* id, const xmlChar* nsPrefix) {
|
||||
xmlNodePtr qualifyingPropertiesNode;
|
||||
xmlNsPtr ns;
|
||||
|
||||
// crear nodo
|
||||
qualifyingPropertiesNode = xmlNewDocNode(doc, NULL, xmlXadesNodeQualifyingProperties, NULL);
|
||||
if (qualifyingPropertiesNode == NULL) {
|
||||
xmlXadesXmlError2("xmlNewDocNode", NULL, "node=%s", xmlXadesErrorsSafeString(xmlXadesNodeQualifyingProperties));
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// crear namespace y asignar
|
||||
ns = xmlNewNs(qualifyingPropertiesNode, xmlXadesDSigNs, nsPrefix);
|
||||
if (ns == NULL) {
|
||||
xmlXadesXmlError2("xmlNewNs", NULL,
|
||||
"ns=%s", xmlXadesErrorsSafeString(xmlXadesDSigNs));
|
||||
xmlFreeNode(qualifyingPropertiesNode);
|
||||
return(NULL);
|
||||
}
|
||||
xmlSetNs(qualifyingPropertiesNode, ns);
|
||||
|
||||
if (id != NULL) {
|
||||
xmlSetProp(qualifyingPropertiesNode, BAD_CAST "Id", id);
|
||||
}
|
||||
|
||||
|
||||
return (qualifyingPropertiesNode);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignedProperties(xmlNodePtr qualifyingPropertiesNode, const xmlChar* id) {
|
||||
xmlNodePtr cur;
|
||||
|
||||
xmlXadesAssert2(qualifyingPropertiesNode != NULL, NULL);
|
||||
|
||||
cur = xmlSecAddChild(qualifyingPropertiesNode, xmlXadesNodeSignedProperties, xmlXadesDSigNs);
|
||||
if (cur == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignedProperties)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (id != NULL) {
|
||||
xmlSetProp(cur, BAD_CAST "Id", id);
|
||||
}
|
||||
|
||||
return(cur);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr signedPropertiesNode, struct tm* signingTime) {
|
||||
xmlNodePtr cur;
|
||||
xmlNodePtr node;
|
||||
|
||||
xmlXadesAssert2(signedPropertiesNode != NULL, NULL);
|
||||
|
||||
// add SignedSignatureProperties
|
||||
node = xmlSecAddChild(signedPropertiesNode, xmlXadesNodeSignedSignatureProperties, xmlXadesDSigNs);
|
||||
if (node == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignedSignatureProperties)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// add SignigTime
|
||||
cur = xmlSecAddChild(node, xmlXadesNodeSigningTime, xmlXadesDSigNs);
|
||||
if (cur == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigningTime)", NULL);
|
||||
xmlFreeNode(node);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
{
|
||||
int ret;
|
||||
char strtime[200];
|
||||
|
||||
if (strftime(strtime, sizeof(strtime), "%Y-%m-%dT%T", signingTime) == 0) {
|
||||
xmlXadesInternalError("strftime", NULL);
|
||||
xmlFreeNode(cur);
|
||||
xmlFreeNode(node);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ret = xmlSecNodeEncodeAndSetContent(cur, BAD_CAST strtime);
|
||||
if (ret < 0) {
|
||||
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||
xmlFreeNode(cur);
|
||||
xmlFreeNode(node);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigningCertificate(xmlNodePtr signedSignaturePropertiesNode, xmlSecTransformId digestMethodId) {
|
||||
xmlNodePtr node;
|
||||
|
||||
xmlXadesAssert2(signedSignaturePropertiesNode != NULL, NULL);
|
||||
if (xmlSecFindChild(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, xmlXadesDSigNs) != NULL) {
|
||||
xmlXadesNodeAlreadyPresentError(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
node = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, xmlXadesDSigNs);
|
||||
if (node == NULL) {
|
||||
xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSigningCertificate)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddCert(xmlNodePtr signingCertificateNode) {
|
||||
xmlNodePtr certNode;
|
||||
|
||||
xmlXadesAssert2(signingCertificateNode != NULL, NULL);
|
||||
|
||||
certNode = xmlSecAddChild(signingCertificateNode, xmlXadesNodeCert, xmlXadesDSigNs);
|
||||
if (certNode == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeCert)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(certNode);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddCertDigest(xmlNodePtr certNode, const xmlChar *digestMethod, const xmlChar *digestValue) {
|
||||
xmlNodePtr node;
|
||||
|
||||
xmlXadesAssert2(certNode != NULL, NULL);
|
||||
|
||||
node = xmlSecAddChild(certNode, xmlXadesNodeCertDigest, xmlXadesDSigNs);
|
||||
if ( node == NULL ) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeCertDigest)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if ( xmlXadesTmplAddDigest(node, digestMethod, digestValue) == NULL) {
|
||||
xmlXadesInternalError("xmlXadesTmplAddDigest(node, digestMethodId)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(certNode);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode) {
|
||||
xmlNodePtr cur;
|
||||
|
||||
xmlXadesAssert2(signedSignaturePropertiesNode != NULL, NULL);
|
||||
|
||||
cur = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSignaturePolicyIdentifier, xmlXadesDSigNs);
|
||||
if (cur == NULL) {
|
||||
xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSignaturePolicyIdentifier)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(cur);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode) {
|
||||
xmlNodePtr cur;
|
||||
|
||||
xmlXadesAssert2(signaturePolicyIdentifierNode != NULL, NULL);
|
||||
|
||||
cur = xmlSecAddChild(signaturePolicyIdentifierNode, xmlXadesNodeSignaturePolicyId, xmlXadesDSigNs);
|
||||
if (cur == NULL) {
|
||||
xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSignaturePolicyId)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(cur);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description, xmlSecTransformId policyDigestMethodId) {
|
||||
xmlNodePtr sigPolicyIdNode;
|
||||
xmlNodePtr node;
|
||||
int ret;
|
||||
|
||||
sigPolicyIdNode = xmlSecAddChild(signaturePolicyId, xmlXadesNodeSigPolicyId, xmlXadesDSigNs);
|
||||
if (sigPolicyIdNode == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigPolicyId)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
node = xmlSecAddChild(sigPolicyIdNode, xmlXadesNodeIdentifier, xmlXadesDSigNs);
|
||||
if (node == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeIdentifier)", NULL);
|
||||
xmlFreeNode(sigPolicyIdNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ret = xmlSecNodeEncodeAndSetContent(node, identifier);
|
||||
if (ret < 0) {
|
||||
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||
xmlFreeNode(sigPolicyIdNode);
|
||||
xmlFreeNode(node);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
node = xmlSecAddChild(sigPolicyIdNode, xmlXadesNodeDescription, xmlXadesDSigNs);
|
||||
if (node == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeDescription)", NULL);
|
||||
xmlFreeNode(sigPolicyIdNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ret = xmlSecNodeEncodeAndSetContent(node, identifier);
|
||||
if (ret < 0) {
|
||||
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||
xmlFreeNode(sigPolicyIdNode);
|
||||
xmlFreeNode(node);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(sigPolicyIdNode);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode) {
|
||||
xmlNodePtr node;
|
||||
xmlXadesAssert2(parentNode != NULL, NULL);
|
||||
|
||||
//add policyHash
|
||||
node = xmlSecAddChild(parentNode, xmlXadesNodeSigPolicyHash, xmlXadesDSigNs);
|
||||
if (node == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigPolicyHash)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// MACHETE(bit4bit) como usar SecTransform para almacenar el digest
|
||||
static xmlNodePtr
|
||||
xmlXadesTmplAddDigest(xmlNodePtr parentNode, const xmlChar *digestMethod, const xmlChar *digestValue) {
|
||||
xmlNodePtr node;
|
||||
|
||||
xmlXadesAssert2(parentNode != NULL, NULL);
|
||||
|
||||
node = xmlSecAddChild(parentNode, xmlSecNodeDigestMethod, xmlSecDSigNs);
|
||||
if (node == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlSecNodeDigestMethod)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
if (xmlSetProp(node, xmlSecAttrAlgorithm, digestMethod) == NULL) {
|
||||
xmlXadesXmlError2("xmlSetProp", NULL,
|
||||
"name=%s", xmlXadesErrorsSafeString(xmlSecAttrAlgorithm));
|
||||
xmlUnlinkNode(node);
|
||||
xmlFreeNode(node);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
node = xmlSecAddChild(parentNode, xmlSecNodeDigestValue, xmlSecDSigNs);
|
||||
if (node == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlSecNodeDigestValue)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (xmlSecNodeEncodeAndSetContent(node, digestValue) < 0) {
|
||||
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return parentNode;
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignerRole(xmlNodePtr signedSignaturePropertiesNode, const xmlChar* role) {
|
||||
xmlNodePtr signerRoleNode;
|
||||
xmlNodePtr claimedRolesNode;
|
||||
xmlNodePtr claimedRoleNode;
|
||||
int ret;
|
||||
|
||||
signerRoleNode = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSignerRole, xmlXadesDSigNs);
|
||||
if (signerRoleNode == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignerRole)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
claimedRolesNode = xmlSecAddChild(signerRoleNode, xmlXadesNodeClaimedRoles, xmlXadesDSigNs);
|
||||
if (claimedRolesNode == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeClaimedRoles)", NULL);
|
||||
xmlUnlinkNode(signerRoleNode);
|
||||
xmlFreeNode(signerRoleNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
claimedRoleNode = xmlSecAddChild(claimedRolesNode, xmlXadesNodeClaimedRole, xmlXadesDSigNs);
|
||||
if (claimedRoleNode == NULL) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeClaimedRole)", NULL);
|
||||
xmlUnlinkNode(signerRoleNode);
|
||||
xmlFreeNode(signerRoleNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ret = xmlSecNodeEncodeAndSetContent(claimedRoleNode, role);
|
||||
if (ret < 0) {
|
||||
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||
xmlUnlinkNode(signerRoleNode);
|
||||
xmlFreeNode(signerRoleNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(signerRoleNode);
|
||||
}
|
||||
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddIssuerSerial(xmlNodePtr certNode, const xmlChar *issuerName, const xmlChar *issuerNumber) {
|
||||
xmlNodePtr issuerSerialNode;
|
||||
xmlNodePtr node;
|
||||
|
||||
xmlXadesAssert2(certNode != NULL, NULL);
|
||||
|
||||
issuerSerialNode = xmlSecAddChild(certNode, xmlXadesNodeIssuerSerial, xmlXadesDSigNs);
|
||||
if ( issuerSerialNode == NULL ) {
|
||||
xmlXadesInternalError("xmlSecAddChild(certNode, xmlXadesIssuerSerial)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
node = xmlSecAddChild(issuerSerialNode, xmlXadesNodeX509IssuerName, xmlSecDSigNs);
|
||||
if ( node == NULL ) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeX509IssuerName)", NULL);
|
||||
xmlFreeNode(issuerSerialNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (xmlSecNodeEncodeAndSetContent(node, issuerName) < 0) {
|
||||
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||
xmlUnlinkNode(issuerSerialNode);
|
||||
xmlFreeNode(issuerSerialNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
node = xmlSecAddChild(issuerSerialNode, xmlXadesNodeX509IssuerNumber, xmlSecDSigNs);
|
||||
if ( node == NULL ) {
|
||||
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeX509IssuerNumber)", NULL);
|
||||
xmlFreeNode(issuerSerialNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (xmlSecNodeEncodeAndSetContent(node, issuerNumber) < 0) {
|
||||
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||
xmlUnlinkNode(issuerSerialNode);
|
||||
xmlFreeNode(issuerSerialNode);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(issuerSerialNode);
|
||||
}
|
@ -1,58 +1,159 @@
|
||||
#include "xades.h"
|
||||
|
||||
int
|
||||
xmlFachoAppSign(xmlDocPtr doc,
|
||||
xmlSecTransformId hashMethodId) {
|
||||
xmlXadesAssert2(doc != NULL, NULL);
|
||||
xmlNodePtr cur;
|
||||
xmlNodePtr signedSignaturePropertiesNode;
|
||||
xmlNodePtr signaturePolicyIdentifierNode;
|
||||
xmlNodePtr signaturePolicyIdNode;
|
||||
xmlChar* signedPropertiesId = BAD_CAST "ref1-signedprops";
|
||||
time_t now = time(NULL);
|
||||
|
||||
cur = xmlXadesTmplQualifyingPropertiesCreateNsPref(doc, "qualify-ref1", BAD_CAST "ds");
|
||||
if (cur == NULL) {
|
||||
return(-1);
|
||||
#include <libxml/xpath.h>
|
||||
#include <libxml/xpathInternals.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static xmlNodePtr
|
||||
xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath) {
|
||||
xmlXPathContextPtr xpathCtx;
|
||||
xmlXPathObjectPtr xpathResult;
|
||||
xmlNodePtr node;
|
||||
|
||||
// obtener QualifyingProteries
|
||||
|
||||
xpathCtx = xmlXPathNewContext(doc);
|
||||
/* register namespaces */
|
||||
// TOMADO DE: xmlsec1/src/xpath.c
|
||||
for(xmlNsPtr ns = xmlDocGetRootElement(doc)->nsDef; ns != NULL; ns = ns->next) {
|
||||
/* check that we have no other namespace with same prefix already */
|
||||
if((ns->prefix != NULL) && (xmlXPathNsLookup(xpathCtx, ns->prefix) == NULL)){
|
||||
int ret = xmlXPathRegisterNs(xpathCtx, ns->prefix, ns->href);
|
||||
if(ret != 0) {
|
||||
xmlXadesXmlError2("xmlXPathRegisterNs", NULL,
|
||||
"prefix=%s", xmlSecErrorsSafeString(ns->prefix));
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur = xmlXadesTmplAddSignedProperties(cur, signedPropertiesId);
|
||||
if (cur == NULL) {
|
||||
return(-1);
|
||||
|
||||
xpathResult = xmlXPathEvalExpression(BAD_CAST "//ds:Object/xades:QualifyingProperties[1]", xpathCtx);
|
||||
if ( xmlXPathNodeSetIsEmpty( xpathResult->nodesetval ) ) {
|
||||
xmlXadesInternalError("can't find ds:Signature/ds:Object/xades:QualifyingProperties \n", NULL);
|
||||
xmlXPathFreeObject(xpathResult);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
signedSignaturePropertiesNode = xmlXadesTmplAddSignedSignatureProperties(cur, now);
|
||||
if (signedSignaturePropertiesNode == NULL) {
|
||||
return(-1);
|
||||
// obtener puntero a nodo
|
||||
node = xpathResult->nodesetval->nodeTab[0];
|
||||
if ( node->type != XML_ELEMENT_NODE ) {
|
||||
xmlXadesInternalError("expected element QualifyingProperties\n", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// addSigningCertificate
|
||||
|
||||
// addSignaturePolicyIdentifier
|
||||
|
||||
signaturePolicyIdNode = xmlXadesAddChildRecursiveNs(signedSignaturePropertiesNode, BAD_CAST "SignaturePolicyIdentifier/SignaturePolicyId", xmlXadesDSigNs)
|
||||
if (signaturePolicyIdNode == NULL) {
|
||||
return(-1);
|
||||
}
|
||||
cur = xmlXadesTmplAddSigPolicyId(signaturePolicyIdNode, identifier, description, hashMethodId);
|
||||
if (cur == NULL) {
|
||||
return(-1);
|
||||
}
|
||||
// SignaturePolicyIdentifier/SignaturePolicyId/SigPolicyHash
|
||||
cur = xmlXadesTmplAddSigPolicyHash(signaturePolicyIdNode);
|
||||
if (cur == NULL) {
|
||||
return(-1);
|
||||
}
|
||||
cur = xmlXadesTmplAddDigest(cur, hashMethodId);
|
||||
if (cur == NULL) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// addSignerRole
|
||||
xmlXadesTmplAddSignerRole(signedSignaturePropertiesNode, BAD_CAST "supplier");
|
||||
|
||||
cur = xmlSecTmplSignatureAddReference(xmlDocGetRootElement(doc),
|
||||
hashMethodId,
|
||||
signedPropertiesId,
|
||||
NULL, NULL);
|
||||
return(node);
|
||||
}
|
||||
|
||||
xmlXadesDSigCtxPtr
|
||||
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx) {
|
||||
xmlXadesDSigCtxPtr ctx = NULL;
|
||||
|
||||
ctx = malloc(sizeof(xmlXadesDSigCtx));
|
||||
if ( ctx == NULL ) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ctx->dsigCtx = dsigCtx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int
|
||||
xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode) {
|
||||
xmlNodePtr signingCertificateNode = NULL;
|
||||
xmlSecKeyDataPtr keyDataX509;
|
||||
xmlSecSize certsSize;
|
||||
|
||||
signingCertificateNode = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//ds:Object/xades:QualifyingProperties//xades:SigningCertificate[1]");
|
||||
if ( signingCertificateNode == NULL ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
keyDataX509 = xmlSecKeyEnsureData(ctx->dsigCtx->signKey, xmlSecKeyDataX509Id);
|
||||
if ( keyDataX509 == NULL ) {
|
||||
xmlXadesInternalError("failed to get X509.\n", NULL);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
certsSize = xmlSecOpenSSLKeyDataX509GetCertsSize(keyDataX509);
|
||||
for (xmlSecSize i = 0; i < certsSize; i++) {
|
||||
// calculamos el digest del certificado
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_n;
|
||||
// TODO(bit4bit) podemos obtener el digest de openssl por medio de la transformacion? o se puede usar la transformacion para generar el digest?
|
||||
xmlChar *digestMethod = (xmlChar *)xmlSecTransformSha256Id->href;
|
||||
const EVP_MD *digest = EVP_sha256();
|
||||
|
||||
X509 *cert = xmlSecOpenSSLKeyDataX509GetCert(keyDataX509, i);
|
||||
if ( cert == NULL ) {
|
||||
xmlXadesInternalError("openssl: failed to get X509 cert.\n", NULL);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
X509_digest(cert, digest, md, &md_n);
|
||||
xmlChar *digestValue = xmlSecBase64Encode(md, md_n, 0);
|
||||
|
||||
xmlNodePtr certNode = xmlXadesTmplAddCert(signingCertificateNode);
|
||||
if ( certNode == NULL ) {
|
||||
xmlXadesInternalError("xmlXadesTmplAddCert(signingCertificateNode)\n", NULL);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// adicionamos digest
|
||||
xmlXadesTmplAddCertDigest(certNode,
|
||||
digestMethod,
|
||||
digestValue);
|
||||
|
||||
char *issuerName = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
|
||||
|
||||
/* TODO(bit4bit) formatear?
|
||||
char *issuerNamePtr = issuerName;
|
||||
|
||||
for(issuerNamePtr = strchr(issuerNamePtr, '/'); issuerNamePtr != NULL; issuerNamePtr = strchr(issuerNamePtr, '/')) {
|
||||
if (issuerNamePtr == issuerName) {
|
||||
issuerName += 1;
|
||||
} else {
|
||||
*issuerNamePtr = ',';
|
||||
}
|
||||
}*/
|
||||
|
||||
ASN1_INTEGER *serial = X509_get_serialNumber(cert);
|
||||
BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL);
|
||||
if ( bn == NULL ) {
|
||||
xmlXadesInternalError("unable to convert ASN1_INTEGER_to_BN to BN\n", NULL);
|
||||
return(-1);
|
||||
}
|
||||
char *issuerNumber = BN_bn2dec(bn);
|
||||
if ( issuerNumber == NULL ) {
|
||||
xmlXadesInternalError("unable to convert BN to decimal string\n", NULL);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (xmlXadesTmplAddIssuerSerial(certNode, BAD_CAST issuerName, BAD_CAST issuerNumber) == NULL) {
|
||||
xmlXadesInternalError("xmlXadesTmplAddIssuerSerial", NULL);
|
||||
return(-1);
|
||||
}
|
||||
BN_free(bn);
|
||||
OPENSSL_free(issuerNumber);
|
||||
}
|
||||
|
||||
return xmlSecDSigCtxSign(ctx->dsigCtx, signNode);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx) {
|
||||
if ( ctx == NULL ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
free(ctx);
|
||||
return(0);
|
||||
}
|
||||
|
@ -1,20 +1,45 @@
|
||||
#ifndef XADES_H
|
||||
#define XADES_H
|
||||
|
||||
|
||||
|
||||
#include <libxml/tree.h>
|
||||
|
||||
#include <xmlsec/xmltree.h>
|
||||
#include <xmlsec/transforms.h>
|
||||
#include <xmlsec/app.h>
|
||||
#include <xmlsec/xmldsig.h>
|
||||
#include <xmlsec/openssl/x509.h>
|
||||
#include <xmlsec/base64.h>
|
||||
|
||||
#include "xmlsec1/errors_helpers.h"
|
||||
|
||||
#define xmlXadesAssert2(p, ret) \
|
||||
xmlSecAssert2(p, ret)
|
||||
|
||||
#define xmlXadesNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) \
|
||||
xmlSecNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject)
|
||||
|
||||
#define xmlXadesXmlError2(errorFunction, errorObject, msg, param) \
|
||||
xmlSecXmlError2(errorFunction, errorObject, msg, param)
|
||||
|
||||
#define xmlXadesErrorsSafeString(msg) \
|
||||
xmlSecErrorsSafeString(msg)
|
||||
|
||||
#define xmlXadesInternalError(errorFunction, errorObject) \
|
||||
xmlSecInternalError(errorFunction, errorObject)
|
||||
|
||||
#define xmlXadesNodeAlreadyPresentError(parent, nodeName, errObject) \
|
||||
xmlSecNodeAlreadyPresentError(parent, nodeName, errObject)
|
||||
|
||||
static const xmlChar xmlXadesNodeQualifyingProperties[] = "QualifyingProperties";
|
||||
static const xmlChar xmlXadesNodeSignedProperties[] = "SignedProperties";
|
||||
|
||||
static const xmlChar xmlXadesNodeSignedSignatureProperties[] = "SignedSignatureProperties";
|
||||
static const xmlChar xmlXadesNodeSigningTime[] = "SigningTime";
|
||||
static const xmlChar xmlXadesNodeSigningCertificate[] = "SigningCertificate";
|
||||
static const xmlChar xmlXadesNodeCertificate[] = "Cert";
|
||||
static const xmlChar xmlXadesNodeCert[] = "Cert";
|
||||
static const xmlChar xmlXadesNodeCertDigest[] = "CertDigest";
|
||||
static const xmlChar xmlXadesNodeSignaturePolicyIdentifier[] = "SignaturePolicyIdentifier";
|
||||
static const xmlChar xmlXadesNodeSignaturePolicyId[] = "SignaturePolicyId";
|
||||
static const xmlChar xmlXadesNodeSigPolicyId[] = "SignaturePolicyId";
|
||||
@ -25,21 +50,59 @@ static const xmlChar xmlXadesNodeSigPolicyHash[] = "SigPolicyHash";
|
||||
static const xmlChar xmlXadesNodeSignerRole[] = "SignerRole";
|
||||
static const xmlChar xmlXadesNodeClaimedRoles[] = "ClaimedRoles";
|
||||
static const xmlChar xmlXadesNodeClaimedRole[] = "ClaimedRole";
|
||||
|
||||
static const xmlChar xmlXadesNodeIssuerSerial[] = "IssuerSerial";
|
||||
static const xmlChar xmlXadesNodeX509IssuerName[] = "X509IssuerName";
|
||||
static const xmlChar xmlXadesNodeX509IssuerNumber[] = "X509IssuerNumber";
|
||||
|
||||
static const xmlChar xmlXadesDSigNs[] = "http://uri.etsi.org/01903/v1.3.2#";
|
||||
|
||||
typedef struct _xmlXadesDSigCtx xmlXadesDSigCtx, *xmlXadesDSigCtxPtr;
|
||||
struct _xmlXadesDSigCtx {
|
||||
xmlSecDSigCtxPtr dsigCtx;
|
||||
};
|
||||
|
||||
|
||||
xmlXadesDSigCtxPtr
|
||||
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx);
|
||||
|
||||
int
|
||||
xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode);
|
||||
|
||||
int
|
||||
xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplQualifyingPropertiesCreate(xmlDocPtr doc, xmlNodePtr signatureNode, const xmlChar *id);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplQualifyingPropertiesCreateNsPref(xmlDocPtr doc, const xmlChar* id, const xmlChar* nsPrefix);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignedProperties(xmlNodePtr qualifyingPropertiesNode, const xmlChar* id);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigningCertificate(xmlNodePtr parentNode);
|
||||
xmlXadesTmplAddSigningCertificate(xmlNodePtr parentNode, xmlSecTransformId digestMethodId);
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddCert(xmlNodePtr signingCertificateNode);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddCertDigest(xmlNodePtr signingCertificateNode, const xmlChar *digestMethod, const xmlChar *digestValue);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignerRole(xmlNodePtr signedSignaturePropertiesNode, const xmlChar* role);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignaturePolicyIdentifierSignaturePolicyId(xmlNodePtr signedSignaturePropertiesNode);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr parentNode, struct tm* signingTime);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddIssuerSerial(xmlNodePtr certNode, const xmlChar *issuerName, const xmlChar *issuerNumber);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesAddChildRecursiveNs(xmlNodePtr parentNode, const xmlChar* path, const xmlChar* nsPrefix);
|
||||
#endif //XADES_H
|
||||
|
Loading…
Reference in New Issue
Block a user