/* $Id: diFirmaSat2.h $ */ /* Copyright (C) 2006-12 DI Management Services Pty Limited. All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net> Last updated: $Date: 2012-02-23 07:33 $ $Revision: 5.1.0 $ */ /* [v5.1] updated this source file with markup for Doxygen documentation <http://www.doxygen.org/> */ /** @file @brief The C/C++ interface to the \b diFirmaSat2.dll library. @par Note re output to szOut buffer Functions that provide output in `szOut` require the buffer to be pre-dimensioned (i.e. allocated) to at least the specified length \c nOutChars PLUS one extra for the null-terminating byte. These functions always return the total length in bytes of the string they tried to create. To find the required length, pass a NULL `szOut` or zero `nOutChars` argument, then add one to the result for the required buffer size. For example: @code char *xmlfile = "test.xml"; long nchars; char *lpszOut; // Find out how many bytes we need nchars = SAT_MakePipeStringFromXml(NULL, 0, xmlfile, 0); if (nchars <= 0) error(); // Pre-dimension, i.e allocate memory for string buffer lpszOut = malloc(nchars+1); // NB +1 if (!lpszOut) error(); nchars = SAT_MakePipeStringFromXml(lpszOut, nchars, xmlfile, 0); // ... // do something with lpszOut... // ... free(lpszOut); @endcode */ #ifndef DIFIRMASAT2_H_ #define DIFIRMASAT2_H_ 1 /* __stdcall convention required for Win32 DLL only */ #if defined(unix) || defined (linux) || defined(__linux) #define _stdcall #endif /* OPTION FLAGS */ /** Use default hash algorithm (SHA-1) */ #define SAT_HASH_DEFAULT 0 /* Default is SHA-1 */ /** Use MD5 hash algorithm (not relevant after 2010-12-31) */ #define SAT_HASH_MD5 0x10 /** Force the SHA-1 hash algorithm [\e deprecated - use 0 instead] */ #define SAT_HASH_SHA1 0x20 /** Return start date instead of expiry when using SAT_GetCertExpiry() [\e deprecated - use SAT_QueryCert() with \c notBefore instead] */ #define SAT_DATE_NOTBEFORE 0x1000 /** Operate on Timbre Fiscal Digital (TFD) instead of Combrobante */ #define SAT_TFD 0x8000 /* New in [v4.0] */ /** Use strict XML type checking with SAT_ValidateXml() (default in v5.0 and above) */ #define SAT_XML_STRICT 0 /** Use loose XML type checking with SAT_ValidateXml() (like default before v5.0) */ #define SAT_XML_LOOSE 0x4000 /** Encode output in UTF-8 (default) */ #define SAT_ENCODE_UTF8 0 /** Encode output in Latin-1 (ISO-8859-1) */ #define SAT_ENCODE_LATIN1 1 /** Flag to retrieve platform type with SAT_ModuleName() */ #define SAT_GEN_PLATFORM 0x40 /* CONSTANTS */ /** Maximum number of characters in hex-encoded hash digest value */ #define SAT_MAX_HASH_CHARS 40 #ifdef __cplusplus extern "C" { #endif /* GENERAL DIAGNOSTIC FUNCTIONS */ /** Gets version number of the core DLL @return Version number as an integer in the form \c major*100+minor*10+revision e.g. DLL file version 3.2.x.1 will return 321 */ long _stdcall SAT_Version(void); /** Gets date and time the core DLL module was last compiled @param [out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. */ long _stdcall SAT_CompileTime(char *szOut, long nOutChars); /** Gets full path name of core DLL module @param [out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @param [in] nOptions \c SAT_GEN_PLATFORM to retrieve platform type ("Win32" or "Win64") instead @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink */ long _stdcall SAT_ModuleName(char *szOut, long nOutChars, long nOptions); /** Gets the licence type. @return The ASCII value of the licence type, either 'D' (68, 0x44) for the Developer Edition or 'T' (84, 0x54) for the Trial Edition. */ long _stdcall SAT_LicenceType(void); /* ERROR-RELATED FUNCTIONS */ /** Retrieves the last error message (if available). @param [out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark Call this function to find out more information about the last error. Not all functions set this. */ long _stdcall SAT_LastError(char *szOut, long nOutChars); /** Looks up error code. @param [out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @param [in] nErrCode Value of error code to lookup (positive or negative) @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. */ long _stdcall SAT_ErrorLookup(char *szOut, long nOutChars, long nErrCode); /** @cond */ /******************************************************************************/ /* NOTE: As of [v4.0] these queries of the CryptoSys PKI DLL are redundant /* -- because the CryptoSys PKI Toolkit (diCrPKI.dll) is no longer required. /******************************************************************************/ /** Returns version number of CryptoSys PKI DLL as called by diFirmaSAT2.dll */ long _stdcall SAT_PKIVersion(void); /** Gets date and time the CryptoSys PKI DLL module was last compiled */ long _stdcall SAT_PKICompileTime(char *szOut, long nOutChars); /** Gets full path name of CryptoSys PKI DLL module */ long _stdcall SAT_PKIModuleName(char *szOut, long nOutChars, long reserved); /******************************************************************************/ /** @endcond */ /* SAT XML FUNCTIONS */ /** Creates the "pipe" string (cadena original) from an XML file. @param [out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @param [in] szXmlFile Name of XML file to be processed @param [in] nOptions Use \c SAT_ENCODE_LATIN1 to encode in Latin1. The default (0) is \c SAT_ENCODE_UTF8 for UTF-8. @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark Final string length may be shorter after extra spaces are removed. @see Note re output to szOut buffer. */ long _stdcall SAT_MakePipeStringFromXml(char *szOut, long nOutChars, const char *szXmlFile, long nOptions); /** Creates the signature as a base64 string ready for insertion as `sello` node @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @param [in] szXmlFile Name of XML file to be processed @param [in] szKeyFile Encrypted key file @param [in] szPassword Password for encrypted key file @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark This will use the default hash algorithm (SHA-1). For advanced options use SAT_MakeSignatureFromXmlEx(). */ long _stdcall SAT_MakeSignatureFromXml(char *szOut, long nOutChars, const char *szXmlFile, const char *szKeyFile, const char *szPassword); /** Creates the signature as a base64 string ready for insertion as `sello` node @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @param [in] szXmlFile Name of XML file to be processed @param [in] szKeyFile Encrypted key file @param [in] szPassword Password for encrypted key file @param [in] nOptions \c SAT_HASH_SHA1 | \c SAT_HASH_MD5 to select hash algorithm. The default (0) is SHA-1. Add \c SAT_TFD to make `selloSAT` for Timbre Fiscal Digital instead. @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. */ long _stdcall SAT_MakeSignatureFromXmlEx(char *szOut, long nOutChars, const char *szXmlFile, const char *szKeyFile, const char *szPassword, long nOptions); /** Validates an XML file against SAT specification. @param [in] szXmlFile Name of XML file to be processed @param [in] nOptions \c SAT_XML_LOOSE to stop strict checks on XML restrictions [new in v5.0]. Default (0) is \c SAT_XML_STRICT. @return Zero (0) on success or a @link SAT_ErrorLookup() negative error code @endlink. @remark This only does a check that the XML elements are well-formed and in the correct order. It does not check the signature and may not catch all XML facet restriction errors that a strict XML parser may find. This function is meant as a quick check for structural problems in the XML file, not as a replacement for a full XSD checker. */ long _stdcall SAT_ValidateXml(const char *szXmlFile, long nOptions); /** Verifies the signature (`sello`) in an XML file. @param [in] szXmlFile Name of XML file to be processed. @param [in] szCertFile (optional) certificate file @param [in] nOptions \c SAT_TFD to verify `selloSAT` in Timbre Fiscal Digital instead [new in v4.0]. @return Zero (0) on success or a @link SAT_ErrorLookup() negative error code @endlink. @remark If no certificate file is specified, then the `certificado` node in the XML file will be used. If a separate certificate file is specified, it will be used instead. @note A separate certificate file is always required for the \c SAT_TFD option. */ long _stdcall SAT_VerifySignature(const char *szXmlFile, const char *szCertFile, long nOptions); /** Signs an XML file. @param [in] szOutputFile Name of new output file to be created with `sello`, `certificado` and `noCertificado` nodes completed. @param [in] szXmlFile Name of input XML file to be processed with empty `sello` and (optionally) `certificado` and `noCertificado` nodes. @param [in] szKeyFile Encrypted private key file @param [in] szPassword Password for encrypted key file @param [in] szCertFile (optional) X.509 certificate file @param [in] nOptions \c SAT_HASH_SHA1 | \c SAT_HASH_MD5 to select hash algorithm. The default (0) is SHA-1. @return Zero (0) on success or a @link SAT_ErrorLookup() negative error code @endlink. @remark This will complete an empty `Comprobante/\@sello` node found in the input file (i.e. \c sello="" ) and write the result to the output file. Any existing file called `szOutputFile` will be over-written without warning. The input and output files can be the same. If a certificate file is specified and empty `certificado` and `noCertificado` nodes exist in the input file, then these nodes will also be completed in the output file. @code <Comprobante ... noCertificado="" certificado="" sello="" ...> @endcode @note It is an error if the private key and certificate do not match. */ long _stdcall SAT_SignXml(const char *szOutputFile, const char *szXmlFile, const char *szKeyFile, const char *szPassword, const char *szCertFile, long nOptions); /** Forms the hex-encoded hash digest of piped string (cadena original) from an XML file. @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes (expect 40 by default) @param [in] szXmlFile Name of XML file to be processed @param [in] nOptions \c SAT_HASH_SHA1 | \c SAT_HASH_MD5 to select hash algorithm. The default (0) is SHA-1. Add \c SAT_TFD to make digest of the cadena original del Timbre Fiscal Digital instead. @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. */ long _stdcall SAT_MakeDigestFromXml(char *szOut, long nOutChars, const char *szXmlFile, long nOptions); /** Extracts the hex-encoded message digest from the signature (sello) in an XML file. @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes (expect 40 by default) @param [in] szXmlFile Name of XML file to be processed @param [in] szCertFile (optional) certificate file @param [in] nOptions \c SAT_TFD to extract digest instead from `selloSAT` of Timbre Fiscal Digital. @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark If the XML file contains a `certificado` node, then that certificate will be used for the public key; otherwise the user must specify a separate certificate file. @note A separate certificate file \e must be specified to use the \c SAT_TFD option. */ long _stdcall SAT_ExtractDigestFromSignature(char *szOut, long nOutChars, const char *szXmlFile, const char *szCertFile, long nOptions); /** Gets the serial number of the X.509 certificate in special SAT format (20 ASCII digits) [\e deprecated]. @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes (expect 20 characters) @param [in] szFileName X.509 certificate file or XML file with a `certificado` node @param [in] nOptions None. Use 0. @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark This only works with a certificate issed by SAT with their special serial number format. If input is an XML file, this extracts the number indirectly from the `certificado` node, not the `noCertificado` node. @see Use instead @link SAT_QueryCert() @endlink with query \c serialNumber. */ long _stdcall SAT_GetCertNumber(char *szOut, long nOutChars, const char *szFileName, long nOptions); /** Gets the expiry date of the X.509 certificate in ISO time format 'yyyy-mm-ddThh:nn:ssZ' [\e deprecated]. @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes (expect 20 characters) @param [in] szFileName X.509 certificate file or XML file with a `certificado` node @param [in] nOptions Use \c SAT_DATE_NOTBEFORE to get start date instead of expiry date; otherwise use 0. @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark The time is GMT (UTC, Zulu time), not local. @see Use instead @link SAT_QueryCert() @endlink with query \c notAfter or \c notBefore. */ long _stdcall SAT_GetCertExpiry(char *szOut, long nOutChars, const char *szFileName, long nOptions); /** Gets the certificate data as a base64 string. @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes. @param [in] szFileName X.509 certificate file or XML file with a `certificado` node @param [in] nOptions None. Use 0. @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark Use to obtain the base64 value for the `certificado` node from a .CER file. It is an error if szOut is too small. If the input is an XML file, this function is equivalent to @code SAT_GetXmlAttribute(szFileName, "certificado", "Comprobante"); @endcode */ long _stdcall SAT_GetCertAsString(char *szOut, long nOutChars, const char *szFileName, long nOptions); /** Extracts attribute data for a given element in an XML file @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @param [in] szXmlFile Name of XML file to be processed @param [in] szAttribute Name of attribute to find @param [in] szElement Name of element to find @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark Attribute and element names are case-sensitive. The default behaviour is to get the attribute from the \e first element found with the given name. Specify the element name in the form \c "element[N]" to extract the attribute for the N'th element found in the XML document, where \c N=1,2,3,... For example: @code char buf[256]; char *fname = "ejemplo1cfdv3.xml"; nchars = SAT_GetXmlAttribute(buf, sizeof(buf)-1, fname, "descripcion", "Concepto[1]"); nchars = SAT_GetXmlAttribute(buf, sizeof(buf)-1, fname, "descripcion", "Concepto[2]"); nchars = SAT_GetXmlAttribute(buf, sizeof(buf)-1, fname, "descripcion", "Concepto[3]"); @endcode will get the attribute `descripcion` from the 1st, 2nd and 3rd elements named `Concepto` found in the file \c fname. The XML fragment @code <cfdi:Conceptos> <cfdi:Concepto unidad="CAPSULAS" importe="244.00" cantidad="1.0" descripcion="VIBRAMICINA 100MG 10" valorUnitario="244.00"/> <cfdi:Concepto unidad="BOTELLA" importe="137.93" cantidad="1.0" descripcion="CLORUTO 500M" valorUnitario="137.93"/> <cfdi:Concepto unidad="TABLETAS" importe="84.50" cantidad="1.0" descripcion="SEDEPRON 250MG 10" valorUnitario="84.50"/> </cfdi:Conceptos> @endcode will yield the result <pre> VIBRAMICINA 100MG 10 CLORUTO 500M SEDEPRON 250MG 10 </pre> @note It is an error if the element or attribute is not present. For example, attempting to use "Concepto[4]" in the above example will return error code -21 (\c NO_MATCH_ERROR). */ long _stdcall SAT_GetXmlAttribute(char *szOut, long nOutChars, const char *szXmlFile, const char *szAttribute, const char *szElement); /** Verifies that the public key in an X.509 certificate matches the private key. @param [in] szKeyFile PKCS#8 encrypted key file @param [in] szPassword Password for encrypted key file @param [in] szCertFile X.509 certificate file or XML file with a `certificado` node @param [in] nOptions None. Use 0. @return Zero (0) if keys match or a @link SAT_ErrorLookup() negative error code @endlink. @remark This will also verify that the password is correct for the key file. */ long _stdcall SAT_CheckKeyAndCert(const char *szKeyFile, const char *szPassword, const char *szCertFile, long nOptions); /** Finds version number of `Comprobante` element in a XML file. @param [in] szXmlFile Name of XML file to be processed @param [in] nOptions None. Use 0. @return A positive integer: 2 if version="2.0", 3 if version="3.0", 22 if version="2.2", 32 if version="3.2"; or a @link SAT_ErrorLookup() negative error code @endlink. */ long _stdcall SAT_XmlReceiptVersion(const char *szXmlFile, long nOptions); /* [v4.0.1] ADDED TO FIX JULY 2011 SAT PROBLEM */ /** Adds a UTF-8 byte order mark (BOM) to a file if not already present. @param [in] szOutputFile Name of output file to be created. @param [in] szInputFile Name of input file to be processed. @param [in] nOptions None. Use 0. @return Zero (0) if output file with BOM successfully created, or a @link SAT_ErrorLookup() negative error code @endlink. @remark This works with \e any UTF-8 input file. It is an error if the input file contains invalid UTF-8 characters. */ long _stdcall SAT_FixBOM(const char *szOutputFile, const char *szInputFile, long nOptions); /* [v5.0] ADDED NEW FUNCTION */ /** Gets the private key as a base64 string to use in XML de Cancelación. @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @param [in] szKeyFile Encrypted key file @param [in] szPassword Password for encrypted key file @param [in] nOptions None. Use 0. @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark This creates a private key in base64 form suitable for a `llaveCertificado` node in a `Cancelacion` element. @warning This outputs your private key in \e unencrypted form. Using it is a huge security risk. Use with caution. */ long _stdcall SAT_GetKeyAsString(char *szOut, long nOutChars, const char *szKeyFile, const char *szPassword, long nOptions); /* [v5.1] NEW FUNCTIONS */ /** Creates a PFX (PKCS-12) file in PEM format suitable for a Cancelación. @param [in] szOutputFile Name of output PFX file to be created. @param [in] szPfxPassword Password to open new PFX file @param [in] szKeyFile Name of encrypted key file @param [in] szKeyPassword Password for encrypted key file @param [in] szCertFile Name of X.509 certificate file @param [in] nOptions None. Use 0. @return Zero (0) if output file is successfully created, or a @link SAT_ErrorLookup() negative error code @endlink. @warning Giving the PFX password to a third party is a security risk. Use with caution. */ long _stdcall SAT_WritePfxFile(const char *szOutputFile, const char *szPfxPassword, const char *szKeyFile, const char *szKeyPassword, const char *szCertFile, long nOptions); /** Queries an X.509 certificate. @param[out] szOut Buffer to receive output string @param [in] nOutChars Maximum length of output string in bytes @param [in] szFileName X.509 certificate file or XML file with a `certificado` node @param [in] szQuery Query string. Select one from { \b rfc | \b organizationName | \b notAfter | \b notBefore | \b serialNumber }. @param [in] nOptions None. Use 0 @return Number of characters in or required for output string; or a @link SAT_ErrorLookup() negative error code @endlink. @remark New in v5.1. Valid queries are: - \b rfc to get the subject's RFC (expect 12 or 13 characters) - \b organizationName to get the issuer's organization name (expect "Servicio de Administración Tributaria", always in Latin-1 encoding) - \b notAfter to get the expiry date [a replacement for SAT_GetCertExpiry()] - \b notBefore to get the start date [a replacement for SAT_GetCertExpiry() with \c SAT_DATE_NOTBEFORE option] - \b serialNumber to get the 20-digit SAT-specific serial number [a replacement for SAT_GetCertNumber()] . @note Times are GMT (UTC, Zulu time), not local, and are in the ISO time format 'yyyy-mm-ddThh:nn:ssZ'. */ long _stdcall SAT_QueryCert(char *szOut, long nOutChars, const char *szFileName, const char *szQuery, long nOptions); #ifdef __cplusplus } #endif #endif /* DIFIRMASAT2_H_ */