facho-signer: se adiciona SigPolicyId

FossilOrigin-Name: c27a531da0a2dbca77e3c0b944735a4fc4266142e505b310d4ca8cf1f3d11596
This commit is contained in:
bit4bit 2021-12-14 02:00:44 +00:00
parent a320b5a7b0
commit 012615f984
4 changed files with 146 additions and 68 deletions

View File

@ -14,13 +14,21 @@
#define print_info(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
const xmlChar ublExtensionDSigNs[] = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2";
const xmlChar policyIdDescription[] = "Política de firma para facturas electrónicas de la República de Colombia.";
const xmlChar policyIdIdentifier[] = "https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf";
char *basename = NULL;
// crea elemento /Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent
xmlNodePtr
xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc);
// FeC requiere que el digest value del policy identifier sea
// apartir del contenido de la url.
xmlXadesPolicyIdentifierCtxPtr
xmlFachoPolicyIdentifierCtxFromFilename(const char *filename);
int
xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) {
xmlNodePtr qualifyingPropertiesNode = NULL;
@ -28,6 +36,9 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) {
xmlNodePtr signedSignaturePropertiesNode = NULL;
xmlNodePtr signingCertificateNode = NULL;
xmlNodePtr signaturePolicyIdentifierNode = NULL;
xmlNodePtr signaturePolicyIdNode = NULL;
xmlNodePtr sigPolicyIdNode = NULL;
xmlNodePtr sigPolicyHashNode = NULL;
xmlNodePtr signerRoleNode = NULL;
xmlNodePtr refNode = NULL;
const xmlChar signedPropertiesId[] = "xmldsig-facho-signed-props";
@ -78,12 +89,31 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) {
goto fail;
}
signaturePolicyIdNode = xmlXadesTmplAddSignaturePolicyId(signaturePolicyIdentifierNode);
if ( signaturePolicyIdNode == NULL ) {
print_error("error: failed to add SignaturePolicyId node.\n");
goto fail;
}
sigPolicyIdNode = xmlXadesTmplAddSigPolicyId(signaturePolicyIdNode, policyIdIdentifier, policyIdDescription);
if ( sigPolicyIdNode == NULL ) {
print_error("error: failed to add SigPolicyId node.\n");
goto fail;
}
sigPolicyHashNode = xmlXadesTmplAddSigPolicyHash(signaturePolicyIdNode, xmlSecTransformSha256Id);
if ( sigPolicyHashNode == NULL ) {
print_error("error: failed to add SigPolicyHash 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);
@ -217,7 +247,7 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw
refNode = xmlSecTmplSignatureAddReference(signNode,
xmlSecTransformSha256Id,
BAD_CAST "xmldsig-facho-ref1",
BAD_CAST "xmldsig-facho-ref2",
BAD_CAST "#xmldsig-facho-KeyInfo",
NULL);
if ( refNode == NULL ) {
@ -263,7 +293,7 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw
goto done;
}
xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx);
xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx, XADES_DIGEST_SHA256, NULL);
if ( xadesDsigCtx == NULL ) {
print_error("error: xades context creating failed.\n");
return(-1);
@ -358,3 +388,8 @@ xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc) {
return(node);
}
xmlXadesPolicyIdentifierCtxPtr
xmlFachoPolicyIdentifierCtxFromFilename(const char *filename) {
return(NULL);
}

View File

@ -215,7 +215,7 @@ xmlXadesTmplAddCertDigest(xmlNodePtr certNode, const xmlChar *digestMethod, cons
xmlNodePtr
xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode) {
xmlNodePtr cur;
xmlXadesAssert2(signedSignaturePropertiesNode != NULL, NULL);
cur = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSignaturePolicyIdentifier, xmlXadesDSigNs);
@ -230,20 +230,20 @@ xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNod
xmlNodePtr
xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode) {
xmlNodePtr cur;
xmlXadesAssert2(signaturePolicyIdentifierNode != NULL, NULL);
cur = xmlSecAddChild(signaturePolicyIdentifierNode, xmlXadesNodeSignaturePolicyId, xmlXadesDSigNs);
if (cur == NULL) {
xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSignaturePolicyId)", NULL);
xmlXadesInternalError("xmlsecAddChild(cur)", NULL);
return(NULL);
}
return(cur);
}
xmlNodePtr
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description, xmlSecTransformId policyDigestMethodId) {
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description) {
xmlNodePtr sigPolicyIdNode;
xmlNodePtr node;
int ret;
@ -276,7 +276,7 @@ xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifi
return(NULL);
}
ret = xmlSecNodeEncodeAndSetContent(node, identifier);
ret = xmlSecNodeEncodeAndSetContent(node, description);
if (ret < 0) {
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
xmlFreeNode(sigPolicyIdNode);
@ -288,7 +288,7 @@ xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifi
}
xmlNodePtr
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode) {
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode, xmlSecTransformId digestMethodId) {
xmlNodePtr node;
xmlXadesAssert2(parentNode != NULL, NULL);
@ -299,6 +299,11 @@ xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode) {
return(NULL);
}
if ( xmlXadesTmplAddDigest(node, digestMethodId->href, BAD_CAST "") == NULL) {
xmlXadesInternalError("xmlXadesTmplAddDigest(node, digestMethodId)", NULL);
return(NULL);
}
return node;
}

View File

@ -12,48 +12,10 @@
#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);
}
}
}
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);
}
// obtener puntero a nodo
node = xpathResult->nodesetval->nodeTab[0];
if ( node->type != XML_ELEMENT_NODE ) {
xmlXadesInternalError("expected element QualifyingProperties\n", NULL);
return(NULL);
}
return(node);
}
xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath);
xmlXadesDSigCtxPtr
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx) {
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx, XADES_DIGEST_METHOD digestMethod, xmlXadesPolicyIdentifierCtxPtr policyCtx) {
xmlXadesDSigCtxPtr ctx = NULL;
ctx = malloc(sizeof(xmlXadesDSigCtx));
@ -62,6 +24,8 @@ xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx) {
}
ctx->dsigCtx = dsigCtx;
ctx->digestMethod = digestMethod;
ctx->policyCtx = policyCtx;
return ctx;
}
@ -88,8 +52,18 @@ xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode) {
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();
xmlChar *digestMethod = NULL;
EVP_MD *digest = NULL;
switch(ctx->digestMethod) {
case XADES_DIGEST_SHA256:
digestMethod = (xmlChar *)xmlSecTransformSha256Id->href;
digest = (EVP_MD *) EVP_sha256();
break;
default:
xmlXadesInternalError("xmlXadesDSigCtxSign not known how to handle digest method.\n", NULL);
return(-1);
}
X509 *cert = xmlSecOpenSSLKeyDataX509GetCert(keyDataX509, i);
if ( cert == NULL ) {
@ -144,6 +118,15 @@ xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode) {
OPENSSL_free(issuerNumber);
}
// digest de policy identifier
xmlNodePtr sigPolicyId = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//xades:SigPolicyId/xades:Identifier[1]");
if ( sigPolicyId == NULL ) {
xmlXadesInternalError("xmlXadesXPathFirstElement(xades:SigPolicyId/xades:Identifier\n", NULL);
return(-1);
}
xmlChar *identifier = xmlNodeListGetString(signNode->doc, sigPolicyId->xmlChildrenNode, 1);
printf("IDENTIFIER %s\n", identifier);
xmlFree(identifier);
return xmlSecDSigCtxSign(ctx->dsigCtx, signNode);
}
@ -157,3 +140,44 @@ xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx) {
free(ctx);
return(0);
}
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);
}
}
}
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);
}
// obtener puntero a nodo
node = xpathResult->nodesetval->nodeTab[0];
if ( node->type != XML_ELEMENT_NODE ) {
xmlXadesInternalError("expected element QualifyingProperties\n", NULL);
return(NULL);
}
return(node);
}

View File

@ -1,8 +1,6 @@
#ifndef XADES_H
#define XADES_H
#include <libxml/tree.h>
#include <xmlsec/xmltree.h>
@ -42,7 +40,7 @@ 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";
static const xmlChar xmlXadesNodeSigPolicyId[] = "SigPolicyId";
static const xmlChar xmlXadesNodeIdentifier[] = "Identifier";
static const xmlChar xmlXadesNodeDescription[] = "Description";
static const xmlChar xmlXadesNodeSigPolicyHash[] = "SigPolicyHash";
@ -56,14 +54,28 @@ static const xmlChar xmlXadesNodeX509IssuerNumber[] = "X509IssuerNumber";
static const xmlChar xmlXadesDSigNs[] = "http://uri.etsi.org/01903/v1.3.2#";
typedef int xmlXadesSize;
typedef enum _XADES_DIGEST_METHOD{
XADES_DIGEST_SHA256
} XADES_DIGEST_METHOD;
typedef int (*xmlXadesPolicyIdentifierContentCallback)(const xmlChar *policyId, xmlChar *content, xmlXadesSize *content_length);
typedef struct _xmlXadesPolicyIdentifierCtx *xmlXadesPolicyIdentifierCtxPtr;
struct _xmlXadesPolicyIdentifierCtx {
XADES_DIGEST_METHOD digestMethod;
xmlXadesPolicyIdentifierContentCallback contentCallback;
};
typedef struct _xmlXadesDSigCtx xmlXadesDSigCtx, *xmlXadesDSigCtxPtr;
struct _xmlXadesDSigCtx {
xmlSecDSigCtxPtr dsigCtx;
XADES_DIGEST_METHOD digestMethod;
xmlXadesPolicyIdentifierCtxPtr policyCtx;
};
xmlXadesDSigCtxPtr
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx);
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx, XADES_DIGEST_METHOD digestMethod, xmlXadesPolicyIdentifierCtxPtr policyCtx);
int
xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode);
@ -74,35 +86,37 @@ 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, xmlSecTransformId digestMethodId);
xmlNodePtr
xmlXadesTmplAddCert(xmlNodePtr signingCertificateNode);
xmlNodePtr
xmlXadesTmplAddCertDigest(xmlNodePtr signingCertificateNode, const xmlChar *digestMethod, const xmlChar *digestValue);
xmlNodePtr
xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr parentNode, struct tm* signingTime);
xmlNodePtr
xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode);
xmlNodePtr
xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode);
xmlNodePtr
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description);
xmlNodePtr
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode, xmlSecTransformId digestMethodId);
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