packages feed

xml-verify-0.1.0.0: cbits/xml-verify.c

#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

#include "xml-verify.h"
#include <xmlsec/xmlsec.h>
#include <xmlsec/xmltree.h>
#include <xmlsec/xmldsig.h>
#include <xmlsec/crypto.h>

int init() {
    xmlInitParser();
    LIBXML_TEST_VERSION
    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
    xmlSubstituteEntitiesDefault(1);

    if(xmlSecInit() < 0) {
        return(-2);
    }

    if(xmlSecCheckVersion() != 1) {
        return(-3);
    }

#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
    if(xmlSecCryptoDLLoadLibrary(NULL) < 0) {
        return(-4);     
    }
#endif

    if(xmlSecCryptoAppInit(NULL) < 0) {
        return(-5);
    }

    if(xmlSecCryptoInit() < 0) {
        return(-6);
    }
    return 0;
}

void deinit() {
    xmlSecCryptoShutdown();
    xmlSecCryptoAppShutdown();
    xmlSecShutdown();
    xmlCleanupParser();
}

// If either len is 0, we assume a file path.
int verify(const char *xml, size_t xml_len, const char *key, size_t key_len) {
    init();
    xmlDocPtr doc = NULL;
    xmlNodePtr node = NULL;
    xmlSecDSigCtxPtr dsigCtx = NULL;
    int res = -1;
    
    if (xml_len == 0) {
      doc = xmlParseFile(xml);
    } else {
      doc = xmlParseMemory(xml, xml_len);
    }
    if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
        res = -7;
        goto done;      
    }
    
    node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
    if(node == NULL) {
        res = -8;
        goto done;      
    }

    dsigCtx = xmlSecDSigCtxCreate(NULL);
    if(dsigCtx == NULL) {
        res = -9;
        goto done;
    }

    if (key_len == 0) {
      dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
    } else {
      dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((const xmlSecByte *)key, (xmlSecSize)key_len, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
    }
    if(dsigCtx->signKey == NULL) {
        res = -10;
        goto done;
    }

    if(xmlSecKeySetName(dsigCtx->signKey, "memory pem") < 0) {
        res = -11;
        goto done;
    }

    if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
        res = -12;
        goto done;
    }
        
    if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
        res = 0;
    } else {
        res = -1;
    }    

done:    
    if(dsigCtx != NULL) {
        xmlSecDSigCtxDestroy(dsigCtx);
    }
    
    if(doc != NULL) {
        xmlFreeDoc(doc); 
    }
    deinit();
    return(res);
}

int verify_file(const char* xml_file, const char* key, size_t key_len) {
  return verify(xml_file, 0, key, key_len);
}

int verify_file_pem(const char* xml_file, const char* key_file) {
  return verify(xml_file, 0, key_file, 0);
}

int verify_doc(const char* xml, size_t xml_len , const char* key, size_t key_len) {
  return verify(xml, xml_len, key, key_len);
}

int verify_doc_pem(const char* xml, size_t xml_len, const char* key_file) {
  return verify(xml, xml_len, key_file, 0);
}