facho-signer: se adicionan digest de certificados

FossilOrigin-Name: 86d510a9c5ea4bf2ec5e297d9fb9fbc04b99761bd62f364b4d32dc749a1cf3bc
This commit is contained in:
bit4bit 2021-12-12 02:53:41 +00:00
parent ebc67d1327
commit a320b5a7b0
5 changed files with 732 additions and 56 deletions

View File

@ -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) $^

View File

@ -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);
}

View 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);
}

View File

@ -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);
}

View File

@ -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