//================================================== // FILE: digidoc.c // PROJECT: Digi Doc // DESCRIPTION: Utility program to demonstrate the // functionality of DigiDocLib // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 12.01.2004 Veiko Sinivee // Creation //================================================== #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #define snprintf _snprintf #include #endif #include #include #include #include #include #include //==========< global constants >==================== // programm arguments char* p_szInFile = 0; char* p_szInEncFile = 0; char* p_szInDecFile = 0; char* p_szOutFile = 0; char* p_szConfigFile = 0; int p_parseMode = 1, g_nLibErrors = 0; int g_cgiMode = 1; // 1=output in CGI mode, 0=normal e.g. human readable mode char* g_szOutputSeparator = 0; char *errorClass[] = {"NO_ERRORS", "TECHNICAL", "USER", "LIBRARY"}; char* g_szProgNameVer = "cdigidoc/"DIGIDOC_VERSION; //==========< forward defs >======================== void printErrorsAndWarnings(SignedDoc* pSigDoc); //==========< helper functions for argument handling >==================== //-------------------------------------------------- // Handles one argument //-------------------------------------------------- int checkArguments(int argc, char** argv, int* pCounter, char** dest) { int nLen = 0; if(argc > (*pCounter)+1 && argv[(*pCounter)+1][0] != '-') { nLen = strlen(argv[(*pCounter)+1]) * 2; ddocConvertInput((const char*)argv[(*pCounter)+1], dest); (*pCounter)++; } return nLen; } //-------------------------------------------------- // checks the existence of one command line argument //-------------------------------------------------- int hasCmdLineArg(int argc, char** argv, const char* argName) { int i; for(i = 1; i < argc; i++) { if(argv[i] != NULL && argv[i][0] == '-' && !strcmp(argv[i], argName)) { return i; } } return 0; } //-------------------------------------------------- // Returns the value of one command line argument //-------------------------------------------------- int checkCmdLineArg(int argc, char** argv, const char* argName, char** dest) { int i; *dest = 0; // mark as not found for(i = 1; i < argc; i++) { if(argv[i] != NULL && argv[i][0] == '-' && !strcmp(argv[i], argName)) { if((i + 1 < argc) && (argv[i+1][0] != '-')) { ddocConvertInput((const char*)argv[i+1], dest); return 0; } else return ERR_BAD_PARAM; } } return 0; // not found but no error } //-------------------------------------------------- // prints usage statement //-------------------------------------------------- void printUsage() { fprintf(stderr, "USAGE: cdigidoc [-in ] [-out ] [-config ]\n"); fprintf(stderr, "COMMANDS:\n"); fprintf(stderr, "\t[-new] \n"); fprintf(stderr, "\t-check-cert <-cerificate-file-name (PEM format)>\n"); fprintf(stderr, "\t-add [] []\n"); fprintf(stderr, "\t-verify \n"); fprintf(stderr, "\t-sign [[[] [ ]] [slot(0)] [ocsp(1)] [PKCS11/CNG/PKCS12] [pkcs12-file-name]]\n"); fprintf(stderr, "\t-extract [] []\n"); fprintf(stderr, "\t-encrypt \n"); fprintf(stderr, "\t-encrypt-sk \n"); fprintf(stderr, "\t-encrecv [] [] []\n"); fprintf(stderr, "\t-decrypt [pkcs12-file] [slot(0)]\n"); fprintf(stderr, "\t-decrypt-sk [pkcs12-file] [slot(0)]\n"); fprintf(stderr, "\t-denc-list \n"); fprintf(stderr, "\t-encrypt-file []\n"); fprintf(stderr, "\t-decrypt-file [pkcs12-file]\n"); fprintf(stderr, "\t-calc-sign [] [ ]\n"); fprintf(stderr, "\t-add-sign-value \n"); fprintf(stderr, "\t-del-sign \n"); fprintf(stderr, "\t-get-confirmation \n"); fprintf(stderr, "\t-mid-sign [[(EE)] [(EST)] [(Testing)] [] [ ]]\n"); fprintf(stderr, "\t-mid-test [ (Testimine)]\n"); fprintf(stderr, "\t-in-mem \n"); fprintf(stderr, "\t-add-mem []\n"); fprintf(stderr, "\t-out-mem \n"); fprintf(stderr, "\t-extract-mem \n"); fprintf(stderr, "OPTIONS:\n"); fprintf(stderr, "\t-cgimode [ print usage if(!err && (hasCmdLineArg(argc, argv, "-?") || hasCmdLineArg(argc, argv, "-help"))) printUsage(); // -in if(!err) if((err = checkCmdLineArg(argc, argv, "-in", &p_szInFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid input file name"); // -in-mem if(!err && hasCmdLineArg(argc, argv, "-in-mem")) { if((err = checkCmdLineArg(argc, argv, "-in-mem", &p_szInFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid input file name"); p_parseMode = 3; } // -SAX -> use Sax parser (default) if(!err) if(hasCmdLineArg(argc, argv, "-SAX")) p_parseMode = 1; // -SAX -> use Sax parser (default) if(!err) if(hasCmdLineArg(argc, argv, "-XRDR")) p_parseMode = 2; // -libraryerrors if(!err) if(hasCmdLineArg(argc, argv, "-libraryerrors")) g_nLibErrors = 1; // -out if(!err) if((err = checkCmdLineArg(argc, argv, "-out", &p_szOutFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid output file name"); if(!err && hasCmdLineArg(argc, argv, "-out-mem")) { if((err = checkCmdLineArg(argc, argv, "-out-mem", &p_szOutFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid output file name"); p_parseMode = 3; } // -encrypt if(!err && hasCmdLineArg(argc, argv, "-encrypt")) if((err = checkCmdLineArg(argc, argv, "-encrypt", &p_szInEncFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid encrypt input file name"); // -encrypt-sk if(!err && hasCmdLineArg(argc, argv, "-encrypt-sk")) if((err = checkCmdLineArg(argc, argv, "-encrypt-sk", &p_szInEncFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid encrypt input file name"); // -config if(!err) if((err = checkCmdLineArg(argc, argv, "-config", &p_szConfigFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid configuration file name"); // -CGI -> use CGI output mode if(!err) if(hasCmdLineArg(argc, argv, "-cgimode")) { g_cgiMode = 1; if((err = checkCmdLineArg(argc, argv, "-cgimode", &g_szOutputSeparator)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid cgi output separator"); if(!g_szOutputSeparator || !g_szOutputSeparator[0] || err) { g_szOutputSeparator = strdup("|"); err = ERR_OK; } } if(hasCmdLineArg(argc, argv, "-consolemode")) { g_cgiMode = 0; } return err; } //-------------------------------------------------- // reads various statusflags from config file //-------------------------------------------------- void readConfigParams() { int n = 0; const char* s = 0; // check if we are in CGI mode n = ConfigItem_lookup_bool("DIGIDOC_CGI_MODE", 0); if(!g_cgiMode && n) g_cgiMode = n; s = ConfigItem_lookup("DIGIDOC_CGI_SEPARATOR"); if(!g_szOutputSeparator && s) g_szOutputSeparator = (char*)strdup(s); if(!g_szOutputSeparator || !g_szOutputSeparator[0]) { if(g_szOutputSeparator) free(g_szOutputSeparator); g_szOutputSeparator = strdup("|"); } } //==========< command handlers >==================== //-------------------------------------------------- // Creates a new signed doc //-------------------------------------------------- int cmdNew(SignedDoc** ppSigDoc, const char* pFormat, const char* pVersion) { int err = ERR_OK; const char* format = pFormat, *version = pVersion; if(!p_szOutFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No output file specified"); return err; } if(!format) format = "DIGIDOC-XML"; if(!version) version = "1.3"; if(format && version) { err = SignedDoc_new(ppSigDoc, format, version); RETURN_IF_NOT(err == ERR_OK, err); } else { err = ERR_UNSUPPORTED_FORMAT; addError(err, __FILE__, __LINE__, "Error finding new document format or version"); } return err; } //-------------------------------------------------- // Adds a DataFile to signed doc //-------------------------------------------------- int cmdAddDataFile(SignedDoc** ppSigDoc, const char* file, const char* mime, const char* content, const char* charset) { int err = ERR_OK, l1; DataFile *pDataFile; char *p = 0, buf1[300]; // if there was no new command then implicitly create a new document if(!(*ppSigDoc)) { err = cmdNew(ppSigDoc, NULL, NULL); RETURN_IF_NOT(err == ERR_OK, err); } // convert to UTF-8 err = ddocConvertInput(file, &p); l1 = sizeof(buf1); getFullFileName(p, buf1, l1); freeLibMem(p); // add a file err = DataFile_new(&pDataFile, *ppSigDoc, NULL, buf1, content, mime, 0, NULL, 0, NULL, charset); if(!err) err = calculateDataFileSizeAndDigest(*ppSigDoc, pDataFile->szId, buf1, DIGEST_SHA1); RETURN_IF_NOT(err == ERR_OK, err); return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- int runAddCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-new")) { char* format = NULL; char* version = NULL; // optional content and charset checkArguments(argc, argv, &i, &format); checkArguments(argc, argv, &i, &version); //printf("format: %s version: %s\n", format, version); err = cmdNew(ppSigDoc, format, version); freeLibMem(format); freeLibMem(version); RETURN_IF_NOT(err == ERR_OK, err); } // add a DataFile if(!strcmp(argv[i], "-add")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* file = argv[i+1]; char* mime = argv[i+2]; char* content = NULL; char* charset = NULL; i += 2; // optional content and charset checkArguments(argc, argv, &i, &content); checkArguments(argc, argv, &i, &charset); err = cmdAddDataFile(ppSigDoc, (const char*)file, (const char*)mime, (const char*)(content ? content : CONTENT_EMBEDDED_BASE64), (const char*)(charset ? charset : CHARSET_UTF_8)); freeLibMem(content); freeLibMem(charset); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing and arguments of -add command"); } } } } return err; } //-------------------------------------------------- // Adds a DataFile to signed doc //-------------------------------------------------- int cmdAddDataFileFromMem(SignedDoc** ppSigDoc, const char* file, const char* mime, const char* content) { int err = ERR_OK; DataFile *pDf = NULL; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; // if there was no new command then implicitly create a new document if(!(*ppSigDoc)) { err = cmdNew(ppSigDoc, NULL, NULL); RETURN_IF_NOT(err == ERR_OK, err); } err = ddocReadFile(file, &mbuf1); if(!err) err = createDataFileInMemory(&pDf, *ppSigDoc, NULL, file, content, mime, mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- int runAddMemCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a DataFile if(!strcmp(argv[i], "-add-mem")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* file = argv[i+1]; char* mime = argv[i+2]; char* content = NULL; i += 2; // optional content and charset checkArguments(argc, argv, &i, &content); err = cmdAddDataFileFromMem(ppSigDoc, (const char*)file, (const char*)mime, (const char*)(content ? content : CONTENT_EMBEDDED_BASE64)); freeLibMem(content); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing and arguments of -add-mem command"); } } } } return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- /*int runAddSignValue(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-addsignvalue")) { char* infile = NULL; char* sigid = NULL; char* sigvalf = NULL; checkArguments(argc, argv, &i, &infile); checkArguments(argc, argv, &i, &sigid); checkArguments(argc, argv, &i, &sigvalf); err = cmdReadDigiDoc(ppSigDoc, 0, 1); } // add a DataFile if(!strcmp(argv[i], "-addsignvalue")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* file = argv[i+1]; char* mime = argv[i+2]; char* content = CONTENT_EMBEDDED_BASE64; char* charset = CHARSET_UTF_8; i += 2; // optional content and charset checkArguments(argc, argv, &i, &content); checkArguments(argc, argv, &i, &charset); err = cmdAddDataFile(ppSigDoc, (const char*)file, (const char*)mime, (const char*)content, (const char*)charset); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing and or arguments of -addsignvalue command"); } } } return err; }*/ //-------------------------------------------------- // Add ecryption recipients //-------------------------------------------------- int runRecipientCmds(int argc, char** argv, DEncEncryptedData** ppEncData) { int err = ERR_OK, i, rb = 0; DEncEncryptedKey* pEncKey = 0; X509* pCert = 0; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a recipients key if(!strcmp(argv[i], "-encrecv")) { if(argc > i+1 && argv[i+1][0] != '-') { char* certfile = argv[i+1]; char* recipient = NULL; char* keyname = NULL; char* carriedkeyname = NULL; char* id = NULL; i++; if(!(*ppEncData)) err = dencEncryptedData_new(ppEncData, DENC_XMLNS_XMLENC, DENC_ENC_METHOD_AES128, 0, 0, 0); if(!err) { err = dencMetaInfo_SetLibVersion(*ppEncData); if(!err) { err = dencMetaInfo_SetFormatVersion(*ppEncData); if(!err) { // optional arguments checkArguments(argc, argv, &i, &recipient); checkArguments(argc, argv, &i, &keyname); checkArguments(argc, argv, &i, &carriedkeyname); err = ReadCertificate(&pCert, certfile); if(!err) { if(!recipient) { ddocCertGetSubjectCN(pCert, &mbuf1); recipient = (char*)mbuf1.pMem; rb = 1; } err = dencEncryptedKey_new(*ppEncData, &pEncKey, pCert, DENC_ENC_METHOD_RSA1_5, id, recipient, keyname, carriedkeyname); if(rb) recipient = NULL; // was not malloc separately from mbuf1 } } } } ddocMemBuf_free(&mbuf1); freeLibMem(recipient); freeLibMem(keyname); freeLibMem(carriedkeyname); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -encrecv command"); } } } } return err; } unsigned char* findFileExt(unsigned char* szFileName) { int i = 0; if(szFileName && strlen(szFileName) > 0) { for(i = strlen(szFileName)-1; (i > 0) && (szFileName[i] != '.'); i--); if(szFileName[i] == '.') return szFileName + i + 1; } return 0; } int checkOldFormatVer(SignedDoc* pSigDoc) { if(!pSigDoc || !pSigDoc->szFormat || !pSigDoc->szFormatVer) { addError(ERR_BAD_PARAM, __FILE__, __LINE__, "Format or version not specified"); return ERR_BAD_PARAM; } if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) || (!strcmp(pSigDoc->szFormat, DIGIDOC_XML_1_1_NAME) && (!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)))) { SET_LAST_ERROR(ERR_OLD_VERSION); return ERR_OLD_VERSION; } return ERR_OK; } //-------------------------------------------------- // reads in a signed doc //-------------------------------------------------- int cmdReadDigiDoc(SignedDoc** ppSigDoc, DEncEncryptedData** ppEncData, int nMode) { int err = ERR_OK, e; int nMaxDfLen; unsigned char* pExt = 0; if(!p_szInFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No input file specified"); return err; } nMaxDfLen = ConfigItem_lookup_int("DATAFILE_MAX_CACHE", 0); pExt = findFileExt(p_szInFile); //printf("Read file: %s - ext: %s", p_szInFile, pExt); if(pExt && strcmp(pExt, "cdoc") == 0) { err = dencSaxReadEncryptedData(ppEncData, p_szInFile); } else if(pExt && strcmp(pExt, "ddoc") == 0) { switch(nMode) { case 2: // new XMLReader interface //err = ddocXRdrReadSignedDocFromFile(p_szInFile, CHARSET_ISO_8859_1, ppSigDoc, nMaxDfLen); break; case 1: default: err = ddocSaxReadSignedDocFromFile(ppSigDoc, p_szInFile, 0, nMaxDfLen); } } else { err = ERR_FILE_READ; } e = checkOldFormatVer(*ppSigDoc); if(!err && e) err = e; printErrorsAndWarnings(*ppSigDoc); return err; } //-------------------------------------------------- // reads in a signed doc //-------------------------------------------------- int cmdReadDigiDocFromMem(SignedDoc** ppSigDoc, DEncEncryptedData** ppEncData) { int err = ERR_OK, e; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; if(!p_szInFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No input file specified"); return err; } //nMaxDfLen = ConfigItem_lookup_int("DATAFILE_MAX_CACHE", 0); if(strstr(p_szInFile, ".cdoc")) { err = ddocReadFile(p_szInFile, &mbuf1); if(!err) err = dencSaxReadEncryptedDataFromMemory(ppEncData, &mbuf1); } else { err = ddocReadFile(p_szInFile, &mbuf1); if(!err) err = ddocSaxReadSignedDocFromMemory(ppSigDoc, mbuf1.pMem, mbuf1.nLen, mbuf1.nLen + 1); } ddocMemBuf_free(&mbuf1); e = checkOldFormatVer(*ppSigDoc); printErrorsAndWarnings(*ppSigDoc); if(!err && e) err = e; return err; } //-------------------------------------------------- // writes a digidoc in file //-------------------------------------------------- int cmdWrite(SignedDoc* pSigDoc, DEncEncryptedData* pEncData) { int err = ERR_OK; FILE* hFile; #ifdef WIN32 wchar_t *convFileName = 0; int l1 = 0; #endif if(!p_szOutFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No output file specified"); return err; } if(pSigDoc) err = createSignedDoc(pSigDoc, p_szInFile, p_szOutFile); if(pEncData) { if(pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED || pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED) { err = dencGenEncryptedData_writeToFile(pEncData, p_szOutFile); } else { #ifdef WIN32 err = utf82unicode((const char*)p_szOutFile, (char**)&convFileName, &l1); ddocDebug(3, "cmdWrite", "Writing file: %s, conv-file: %s len: %d", p_szOutFile, convFileName, l1); if((hFile = _wfopen(convFileName, L"wb")) != NULL) { #else if((hFile = fopen(p_szOutFile, "wb")) != NULL) { #endif fwrite((pEncData)->mbufEncryptedData.pMem, 1, (pEncData)->mbufEncryptedData.nLen, hFile); fclose(hFile); } else err = ERR_FILE_WRITE; } } if (err) addError(err, __FILE__, __LINE__, "Error writing file\n"); return err; } //-------------------------------------------------- // writes a digidoc in file //-------------------------------------------------- int cmdWriteMem(SignedDoc* pSigDoc, DEncEncryptedData* pEncData) { int err = ERR_OK; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; if(!p_szOutFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No output file specified"); return err; } if(pSigDoc) { err = createSignedDocInMemory(pSigDoc, NULL, &mbuf1); if(!err) err = ddocWriteFile(p_szOutFile, &mbuf1); } if(pEncData) { if(pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED || pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED) { err = dencGenEncryptedData_toXML(pEncData, &mbuf1); if(!err) err = ddocWriteFile(p_szOutFile, &mbuf1); } else { err = ddocWriteFile(p_szOutFile, &(pEncData->mbufEncryptedData)); } } ddocMemBuf_free(&mbuf1); if (err) addError(err, __FILE__, __LINE__, "Error writing file\n"); return err; } //----------------------------------------- // prints certificate info //----------------------------------------- void printCertificateInfo(SignedDoc* pSigDoc, X509* pCert) { int err, p; char buf1[500]; PolicyIdentifier* pPolicies; DigiDocMemBuf mbuf; int nPols; mbuf.pMem = 0; mbuf.nLen = 0; // serial number err = ReadCertSerialNumber(buf1, sizeof(buf1), pCert); if(g_cgiMode) fprintf(stdout, "\nX509Certificate%s%s", g_szOutputSeparator, buf1); else fprintf(stdout, "\nX509Certificate nr: %s", buf1); // issuer err = ddocCertGetIssuerDN(pCert, &mbuf); if(g_cgiMode) fprintf(stdout, "%s%s", g_szOutputSeparator, (char*)mbuf.pMem); else fprintf(stdout, "\n\tIssuer: %s", (char*)mbuf.pMem); ddocMemBuf_free(&mbuf); // subject err = ddocCertGetSubjectDN(pCert, &mbuf); if(g_cgiMode) fprintf(stdout, "%s%s", g_szOutputSeparator, (char*)mbuf.pMem); else fprintf(stdout, "\n\tSubject: %s", (char*)mbuf.pMem); ddocMemBuf_free(&mbuf); // ValidFrom memset(buf1, 0, sizeof(buf1)); err = getCertNotBefore(pSigDoc, pCert, buf1, sizeof(buf1)); if(g_cgiMode) fprintf(stdout, "%s%s", g_szOutputSeparator, buf1); else fprintf(stdout, "\n\tNotBefore: %s", buf1); // ValidTo memset(buf1, 0, sizeof(buf1)); err = getCertNotAfter(pSigDoc, pCert, buf1, sizeof(buf1)); if(g_cgiMode) fprintf(stdout, "%s%s", g_szOutputSeparator, buf1); else fprintf(stdout, "\n\tNotAfter: %s", buf1); // policy URL err = readCertPolicies(pCert, &pPolicies, &nPols); if(nPols) { for(p = 0; p < nPols; p++) { if(g_cgiMode) fprintf(stdout, "\nSignaturePolicy%s%s%s%s%s%s", g_szOutputSeparator, pPolicies[p].szOID, g_szOutputSeparator, pPolicies[p].szCPS, g_szOutputSeparator, pPolicies[p].szUserNotice); else fprintf(stdout, "\n\tnSignaturePolicy oid: %s cps: %s desc: %s", pPolicies[p].szOID, pPolicies[p].szCPS, pPolicies[p].szUserNotice); } // for p < nPols } PolicyIdentifiers_free(pPolicies, nPols); } char* TEST_OIDS_PREFS[] = { "1.3.6.1.4.1.10015.3.7", "1.3.6.1.4.1.10015.7", // tempel test "1.3.6.1.4.1.10015.3.3", "1.3.6.1.4.1.10015.3.11", // mid test "1.3.6.1.4.1.10015.3.2", // digi-id test "1.3.6.1.4.1.10015.3.1" // est-eid test }; int checkTestCert(X509* pCert) { int err = ERR_OK, i, p; PolicyIdentifier* pPolicies = NULL; DigiDocMemBuf mbuf; int nPols = 0; mbuf.pMem = 0; mbuf.nLen = 0; ddocCertGetSubjectCN(pCert, &mbuf); /*if(mbuf.pMem && strstr(mbuf.pMem, "TEST")) { printf("\n Test CN: %s", (char*)(mbuf.pMem)); err = ERR_TEST_SIGNATURE; }*/ err = readCertPolicies(pCert, &pPolicies, &nPols); if(!err && nPols && !err) { for(p = 0; p < nPols; p++) { //printf("\nOID: %s", pPolicies[p].szOID); for(i = 0; i < 6 && !err; i++) { if(i == 1 && // tempel - test strstr(pPolicies[p].szOID, TEST_OIDS_PREFS[1]) && strstr(mbuf.pMem, "TEST")) { //printf("\nTempel-Test OID: %s", TEST_OIDS_PREFS[i]); err = ERR_TEST_SIGNATURE; } else if(i != 1) { if(strstr(pPolicies[p].szOID, TEST_OIDS_PREFS[i])) { //printf("\nTest OID: %s", TEST_OIDS_PREFS[i]); err = ERR_TEST_SIGNATURE; } } } } } ddocMemBuf_free(&mbuf); PolicyIdentifiers_free(pPolicies, nPols); if(err == ERR_TEST_SIGNATURE) SET_LAST_ERROR(ERR_TEST_SIGNATURE); return err; } int isError(SignedDoc* pSigDoc, int nErrCd) { return (nErrCd != ERR_OK && !isWarning(pSigDoc, nErrCd)); } int isWarning(SignedDoc* pSigDoc, int nErrCd) { if(pSigDoc && pSigDoc->szFormat && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { // currently no warnings for ddoc 1.0 return (nErrCd == ERR_OLD_VERSION) || (nErrCd == ERR_TEST_SIGNATURE); } else { return ((nErrCd == ERR_ISSUER_XMLNS) || (nErrCd == ERR_OLD_VERSION) || (nErrCd == ERR_TEST_SIGNATURE) || (nErrCd == ERR_DF_WRONG_DIG) ); } } int isLibraryError(int nErrCd) { return (nErrCd != ERR_OK && nErrCd != ERR_OLD_VERSION && nErrCd != ERR_TEST_SIGNATURE && nErrCd != ERR_UNSUPPORTED_FORMAT); } int hasWarnings(SignedDoc* pSigDoc) { int n; ErrorInfo* pErr; for(n = getLastErrorsIdx(); n >= 0; n--) { pErr = getErrorsInfo(n); if(isWarning(pSigDoc, pErr->code)) return pErr->code; } return ERR_OK; } int hasErrors(SignedDoc* pSigDoc) { int n; ErrorInfo* pErr; for(n = getLastErrorsIdx(); n >= 0; n--) { pErr = getErrorsInfo(n); if(isError(pSigDoc, pErr->code)) return pErr->code; } return ERR_OK; } void printErrorsAndWarnings(SignedDoc* pSigDoc) { int n, m = getLastErrorsIdx(); ErrorInfo* pErr; char* pErrStr; // list all errors if(g_cgiMode) { /*for(n = 0; n < m; n++) { pErr = getErrorsInfo(n); pErrStr = getErrorString(pErr->code); printf("\nErr: %d cd: %d msg: %s", n, pErr->code, pErrStr); }*/ for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); pErrStr = getErrorString(pErr->code); if(isError(pSigDoc, pErr->code)) fprintf(stdout, "\nERROR%s%d%s%s%s%s%s%d%s%s%s%s", g_szOutputSeparator, pErr->code, g_szOutputSeparator, pErrStr, g_szOutputSeparator, pErr->fileName, g_szOutputSeparator, pErr->line, g_szOutputSeparator, pErr->assertion, g_szOutputSeparator, errorClass[getErrorClass(pErr->code)]); } for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); pErrStr = getErrorString(pErr->code); if(isWarning(pSigDoc, pErr->code)) fprintf(stdout, "\nWARNING%s%d%s%s%s%s%s%d%s%s%s%s", g_szOutputSeparator, pErr->code, g_szOutputSeparator, pErrStr, g_szOutputSeparator, pErr->fileName, g_szOutputSeparator, pErr->line, g_szOutputSeparator, pErr->assertion, g_szOutputSeparator, errorClass[getErrorClass(pErr->code)]); } if(g_nLibErrors) { for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); if(isLibraryError(pErr->code)) { pErrStr = getErrorString(pErr->code); fprintf(stdout, "\nLIBRARY-ERROR%s%d%s%s%s%s%s%d%s%s%s%s", g_szOutputSeparator, pErr->code, g_szOutputSeparator, pErrStr, g_szOutputSeparator, pErr->fileName, g_szOutputSeparator, pErr->line, g_szOutputSeparator, pErr->assertion, g_szOutputSeparator, errorClass[getErrorClass(pErr->code)]); } } } } else { for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); pErrStr = getErrorString(pErr->code); if(isError(pSigDoc, pErr->code)) fprintf(stdout, "\nERROR: %d - %s - %s", pErr->code, pErrStr, pErr->assertion); if(isWarning(pSigDoc, pErr->code)) fprintf(stdout, "\nWARNING: %d - %s - %s", pErr->code, pErrStr, pErr->assertion); } } } //-------------------------------------------------- // Verifys sigantures and notaries //-------------------------------------------------- int cmdVerify(SignedDoc* pSigDoc) { int err = ERR_OK, s, d, l, m, l1, e, e2, n1, e3; SignatureInfo* pSigInfo = 0; NotaryInfo* pNot; DataFile *pDf = 0; DigiDocMemBuf mbuf; X509* pRcert = 0; const DigiDocMemBuf* pMBuf = 0; char buf1[100], *p1 = 0; mbuf.pMem = 0; mbuf.nLen = 0; if(!pSigDoc) { SET_LAST_ERROR(ERR_UNSUPPORTED_FORMAT); return ERR_UNSUPPORTED_FORMAT; } // print signed doc format and version if(g_cgiMode) { fprintf(stdout, "\nSignedDoc%s%s%s%s", g_szOutputSeparator, pSigDoc->szFormat, g_szOutputSeparator, pSigDoc->szFormatVer); } else { fprintf(stdout, "\nSignedDoc format: %s version: %s\n", pSigDoc->szFormat, pSigDoc->szFormatVer); } // display DataFile-s d = getCountOfDataFiles(pSigDoc); for(l = 0; l < d; l++) { pDf = getDataFile(pSigDoc, l); ddocGetDataFileFilename(pSigDoc, pDf->szId, (void**)&p1, &n1); if(g_cgiMode) fprintf(stdout, "\n\nDataFile%s%s%s%s%s%ld%s%s%s%s", g_szOutputSeparator, pDf->szId, g_szOutputSeparator, p1, g_szOutputSeparator, pDf->nSize, g_szOutputSeparator, pDf->szMimeType, g_szOutputSeparator, pDf->szContentType); else fprintf(stdout, "\n\nDataFile: %s, file: %s, size: %ld, mime-type: %s content-type: %s", pDf->szId, p1, pDf->nSize, pDf->szMimeType, pDf->szContentType); if(p1) freeLibMem(p1); } // verify signatures d = getCountOfSignatures(pSigDoc); for(s = 0; s < d; s++) { pSigInfo = getSignature(pSigDoc, s); e = ddocCertGetSubjectCN(ddocSigInfo_GetSignersCert(pSigInfo), &mbuf); clearErrors(); e = verifySignatureAndNotary(pSigDoc, pSigInfo, p_szInFile); if(!e) e = hasErrors(pSigDoc); if(!err && e) err = e; e2 = checkTestCert(ddocSigInfo_GetSignersCert(pSigInfo)); if(!err && e2) err = e2; if(!e && e2) e = e2; if(g_cgiMode) { fprintf(stdout, "\n\nSignature%s%s%s%s%s%d%s%s", g_szOutputSeparator, pSigInfo->szId, g_szOutputSeparator, (const char*)mbuf.pMem, g_szOutputSeparator, e, g_szOutputSeparator, (e ? getErrorString(e) : "")); } else { fprintf(stdout, "\n\nSignature: %s - %s - %s", pSigInfo->szId, (const char*)mbuf.pMem, ((!e) ? "OK" : "ERROR")); } ddocMemBuf_free(&mbuf); // print signers roles / manifests m = getCountOfSignerRoles(pSigInfo, 0); for(l = 0; l < m; l++) { if(g_cgiMode) fprintf(stdout, "\nClaimedRole%s%s", g_szOutputSeparator, getSignerRole(pSigInfo, 0, l)); else fprintf(stdout, "\n\tClaimedRole: %s", getSignerRole(pSigInfo, 0, l)); } if(pSigInfo->sigProdPlace.szCity || pSigInfo->sigProdPlace.szStateOrProvince || pSigInfo->sigProdPlace.szPostalCode || pSigInfo->sigProdPlace.szCountryName) { if(g_cgiMode) { fprintf(stdout, "\nSignatureProductionPlace%s%s%s%s%s%s%s%s", g_szOutputSeparator, (pSigInfo->sigProdPlace.szCountryName ? pSigInfo->sigProdPlace.szCountryName : ""), g_szOutputSeparator, (pSigInfo->sigProdPlace.szStateOrProvince ? pSigInfo->sigProdPlace.szStateOrProvince : ""), g_szOutputSeparator, (pSigInfo->sigProdPlace.szCity ? pSigInfo->sigProdPlace.szCity : ""), g_szOutputSeparator, (pSigInfo->sigProdPlace.szPostalCode ? pSigInfo->sigProdPlace.szPostalCode : "")); } else { fprintf(stdout, "\n\tnSignatureProductionPlace - Country: %s, State: %s, City: %s, Postal code: %s", (pSigInfo->sigProdPlace.szCountryName ? pSigInfo->sigProdPlace.szCountryName : ""), (pSigInfo->sigProdPlace.szStateOrProvince ? pSigInfo->sigProdPlace.szStateOrProvince : ""), (pSigInfo->sigProdPlace.szCity ? pSigInfo->sigProdPlace.szCity : ""), (pSigInfo->sigProdPlace.szPostalCode ? pSigInfo->sigProdPlace.szPostalCode : "")); } } // signers certificate if(ddocSigInfo_GetSignersCert(pSigInfo)) printCertificateInfo(pSigDoc, ddocSigInfo_GetSignersCert(pSigInfo)); // confirmation if(pSigDoc && pSigInfo) { pNot = getNotaryWithSigId(pSigDoc, pSigInfo->szId); if(pNot) { pMBuf = ddocNotInfo_GetResponderId(pNot); buf1[0] = 0; l1 = sizeof(buf1); if(pNot->nRespIdType == RESPID_NAME_TYPE) { strncpy(buf1, (const char*)pMBuf->pMem, l1); } if(pNot->nRespIdType == RESPID_KEY_TYPE) { encode((const byte*)pMBuf->pMem, pMBuf->nLen, (byte*)buf1, &l1); } } if(pNot && pMBuf) { if(g_cgiMode) fprintf(stdout, "\nRevocationValues%s%s%s%s", g_szOutputSeparator, buf1, g_szOutputSeparator, pNot->timeProduced); else fprintf(stdout, "\n\tRevocationValues responder: %s produced-at: %s", buf1, pNot->timeProduced); // certificate pRcert = ddocSigInfo_GetOCSPRespondersCert(pSigInfo); e3 = checkTestCert(pRcert); if(!e2 && e3) { // live allkirjastaja sert aga test ocsp fprintf(stdout, "\n\tSigner from LIVE CA-chain but OCSP from TEST CA-chain!"); err = e3; SET_LAST_ERROR(e3); } printCertificateInfo(pSigDoc, pRcert); } } printErrorsAndWarnings(pSigDoc); } return err; } //-------------------------------------------------- // Signs the document and gets configrmation //-------------------------------------------------- int cmdSign(SignedDoc* pSigDoc, const char* pin, const char* manifest, const char* city, const char* state, const char* zip, const char* country, int nSlot, int nOcsp, int nSigner, const char* szPkcs12File) { int err = ERR_OK; SignatureInfo* pSigInfo = NULL; ddocDebug(3, "cmdSign", "Creating new digital signature"); err = signDocumentWithSlotAndSigner(pSigDoc, &pSigInfo, pin, manifest, city, state, zip, country, nSlot, nOcsp, nSigner, szPkcs12File); ddocDebug(3, "cmdSign", "End creating new digital signature"); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } //#ifdef WITH_DEPRECATED_FUNCTIONS //-------------------------------------------------- // Runs some test. This is used simply to test // new features of the library and the functionality // may change. //-------------------------------------------------- void cmdTest2(const char* infile) { X509* pCert = 0; //char buf1[X509_NAME_LEN + 10]; int err = ERR_OK, nPols = 0; PolicyIdentifier *pPolicies = 0; ddocDebug(3, "cmdTest2", "Reading cert: %s", infile); err = ReadCertificate(&pCert, infile); if(!err && pCert) { err = readCertPolicies(pCert, &pPolicies, &nPols); printf("Read pols rc: %d pols: %d\n", err, nPols); /* l1 = sizeof(buf1); memset(buf1, 0, sizeof(buf1)); err = getCertSubjectName(pCert, buf1, &l1); if(g_cgiMode) fprintf(stdout, "\nDN%s%s%s%d", g_szOutputSeparator, buf1, g_szOutputSeparator, l1); else fprintf(stdout, "\nDN: %s len: %d", buf1, l1); */ } if(pCert) X509_free(pCert); if(pPolicies) PolicyIdentifiers_free(pPolicies, nPols); } //#endif //-------------------------------------------------- // Encrypts a file //-------------------------------------------------- int cmdEncrypt(DEncEncryptedData** ppEncData, const char* szFileName) { FILE* hFile; SignedDoc *pSigDoc = 0; DEncEncryptionProperty* pEncProperty = 0; int len, err = ERR_OK, i = 0; long lFileLen; char buf[2048], *p = 0; #ifdef WIN32 wchar_t *convFileName = 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); #endif ddocDebug(3, "cmdEncrypt", "Encrypting %s rc: %d", szFileName, err); err = dencEncryptedData_new(ppEncData, DENC_XMLNS_XMLENC, DENC_ENC_METHOD_AES128, 0, 0, 0); if(!err) { err = dencMetaInfo_SetLibVersion(*ppEncData); if(!err) { err = dencMetaInfo_SetFormatVersion(*ppEncData); if(!err) { err = ddocConvertInput(szFileName, &p); if(!err) { err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_FILENAME, getSimpleFileName(p)); if(strstr(p, ".bdoc") || strstr(p, ".asice")) err = dencEncryptedData_SetMimeType(*ppEncData, "application/vnd.etsi.asic-e+zip"); err = calculateFileSize(szFileName, &lFileLen); sprintf(buf, "%ld", lFileLen); err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_ORIG_SIZE, buf); freeLibMem(p); if(!err) { ddocDebug(3, "cmdEncrypt", "Opening %s rc: %d", szFileName, err); #ifdef WIN32 if((hFile = _wfopen(convFileName, L"rb")) != NULL) { #else if((hFile = fopen(szFileName, "rb")) != NULL) { #endif do { memset(buf,0,sizeof(buf)); len = fread(buf, 1, sizeof(buf), hFile); if(len) err = dencEncryptedData_AppendData(*ppEncData, buf, len); } while(len && !err); fclose(hFile); } // if fopen/wfopen ddocDebug(3, "cmdEncrypt", "Enc data-len: %d rc: %d", (*ppEncData)->mbufEncryptedData.nLen, err); if(!err) err = dencEncryptedData_encryptData(*ppEncData, DENC_COMPRESS_NEVER); } // err - endProp_new } // err - conver filename } // err - serFormatVer } // err - setLibVer } // err - dencEncData_new return err; } //-------------------------------------------------- // Encrypts a file and uses SK specific method of // putting the file first in a ddoc container and then into // cdoc //-------------------------------------------------- int cmdEncryptSk(DEncEncryptedData** ppEncData, const char* szFileName) { SignedDoc *pSigDoc = 0; DEncEncryptionProperty* pEncProperty = 0; DataFile *pDf = 0; int err = ERR_OK; long lSize; char buf[256], *p = 0; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; err = dencEncryptedData_new(ppEncData, DENC_XMLNS_XMLENC, DENC_ENC_METHOD_AES128, 0, 0, 0); if(!err) { err = dencMetaInfo_SetLibVersion(*ppEncData); if(!err) { err = dencMetaInfo_SetFormatVersion(*ppEncData); if(!err) { err = ddocConvertInput(szFileName, &p); if(!err) { err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_FILENAME, getSimpleFileName(p)); if(!err) { err = SignedDoc_new(&pSigDoc, "DIGIDOC-XML", "1.3"); if(!err) { calculateFileSize(szFileName, &lSize); err = DataFile_new(&pDf, pSigDoc, NULL, szFileName, "EMBEDDED_BASE64", "application/file", lSize, NULL, 0, NULL, NULL); sprintf(buf, "%ld", lSize); err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_ORIG_SIZE, buf); if(!err) { err = dencOrigContent_registerDigiDoc(*ppEncData, pSigDoc); if(!err) { sprintf(buf, "%s.ddoc", szFileName); err = createSignedDoc(pSigDoc, NULL, buf); if(!err) { err = ddocReadFile(buf, &mbuf1); if(!err) { err = dencEncryptedData_AppendData(*ppEncData, mbuf1.pMem, mbuf1.nLen); //ddocDebug(3, "EncTest", "Enc data: \"%s\"", mbuf1.pMem); remove(buf); ddocMemBuf_free(&mbuf1); if(!err) err = dencEncryptedData_encryptData(*ppEncData, DENC_COMPRESS_NEVER); } // err - ddocReadFile } // err - createSignedDoc } // err - origContent_register } // err - sigDoc_new } // err - sigDoc_new SignedDoc_free(pSigDoc); } // err - encProp_new freeLibMem(p); } // err - convert filename } // err - setFormatVer } // err - setLibVer } // err - endData_new return err; } //-------------------------------------------------- // Runs various tests. Just for trying out new features //-------------------------------------------------- int runTestCmds(int argc, char** argv) { int err = ERR_OK, i; char* infile = NULL; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - if(!strcmp(argv[i], "-test")) { // add a recipients key } //#ifdef WITH_DEPRECATED_FUNCTIONS if(!strcmp(argv[i], "-test2")) { ddocConvertInput((const char*)argv[i+1], &infile); cmdTest2(argv[i+1]); } //#endif } } return err; } //-------------------------------------------------- // Encrypts whole files //-------------------------------------------------- int runEncryptFileCmds(int argc, char** argv, DEncEncryptedData* pEncData) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a recipients key if(!strcmp(argv[i], "-encrypt-file")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* infile = NULL; char* outfile = NULL; char* mime = NULL; ddocConvertInput((const char*)argv[i+1], &infile); ddocConvertInput((const char*)argv[i+2], &outfile); ddocConvertInput((const char*)argv[i+3], &mime); i += 3; // optional arguments checkArguments(argc, argv, &i, &mime); // encrypt the file err = dencEncryptFile(pEncData, infile, outfile, mime); if(infile) freeLibMem(infile); if(outfile) freeLibMem(outfile); if(mime) freeLibMem(mime); if(err) return err; } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing or argument of -encrypt-file command"); } } } } return err; } //-------------------------------------------------- // Decrypts whole files //-------------------------------------------------- int runDecryptFileCmds(int argc, char** argv) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // decrypt a file if(!strcmp(argv[i], "-decrypt-file")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-' && argv[i+3][0] != '-') { char* infile = NULL; char* outfile = NULL; char* pin = NULL; char* pkcs12file = NULL; ddocConvertInput((const char*)argv[i+1], &infile); ddocConvertInput((const char*)argv[i+2], &outfile); ddocConvertInput((const char*)argv[i+3], &pin); i += 3; // optional arguments checkArguments(argc, argv, &i, &pkcs12file); // decrypt the file err = dencSaxReadDecryptFile(infile, outfile, pin, pkcs12file); if(infile) freeLibMem(infile); if(outfile) freeLibMem(outfile); if(pin) freeLibMem(pin); if(pkcs12file) freeLibMem(pkcs12file); if(err) return err; } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing , or argument of -decrypt-file command"); } } } } return err; } //-------------------------------------------------- // Generates and encrypts a block of data with specific // length //-------------------------------------------------- int cmdEncryptTestSet(DEncEncryptedData** ppEncData, int nSize, char* dir, int nDdoc, int nDel) { DEncEncryptionProperty* pEncProperty = 0; int err = ERR_OK, i, nCompress, l2; char *p = 0, fname1[256], fname2[256], c, *p2; SignedDoc* pSigDoc = 0; DataFile *pDf = 0; FILE* hFile; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; nCompress = ConfigItem_lookup_int("DENC_COMPRESS_MODE", DENC_COMPRESS_ALLWAYS); ddocDebug(3, "EncTest", "Test: %d", nSize); err = dencEncryptedData_new(ppEncData, DENC_XMLNS_XMLENC, DENC_ENC_METHOD_AES128, 0, 0, 0); if(err) return err; err = dencMetaInfo_SetLibVersion(*ppEncData); if(err) return err; err = dencMetaInfo_SetFormatVersion(*ppEncData); if(err) return err; sprintf(fname1, "%stest-%d.dat", dir, nSize); err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_FILENAME, fname1); if(err) return err; p = (char*)malloc(nSize+1); if(!p) return ERR_BAD_ALLOC; memset(p, 0, nSize+1); for(i = 0, c = 'A'; i < nSize; i++, c++) { p[i] = c; if(c >= 'z') c = 'A'; } // append x.923 padding if last block is full if(nSize % 16 == 0) { ddocDebug(3, "EncTest", "Full size: %d. Change last 8 bytes to X.923 padding", nSize); p[nSize-1] = 8; for(i = nSize -2; i > nSize - 9; i--) p[i] = 0; } l2 = nSize * 2 + 1; p2 = (char*)malloc(l2); if(!p2) return ERR_BAD_ALLOC; memset(p2, 0, l2); bin2hex((const byte*)p, nSize, (byte*)p2, &l2); ddocDebug(3, "EncTest", "Fil data hex: \"%s\" len: %d", p2, l2); if((hFile = fopen(fname1, "w")) != NULL) { fwrite(p, nSize, 1, hFile); fclose(hFile); } free(p); p = 0; fname2[0] = 0; if(nDdoc) { err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_ORIG_MIME, DENC_ENCDATA_TYPE_DDOC); err = SignedDoc_new(&pSigDoc, "DIGIDOC-XML", "1.3"); if(!err) { err = DataFile_new(&pDf, pSigDoc, NULL, fname1, "EMBEDDED_BASE64", "text/txt", nSize, NULL, 0, NULL, NULL); if(!err) { err = dencOrigContent_registerDigiDoc(*ppEncData, pSigDoc); if(!err) { sprintf(fname2, "%stest-%d.ddoc", dir, nSize); err = createSignedDoc(pSigDoc, NULL, fname2); if(!err) { err = ddocReadFile(fname2, &mbuf1); if(!err) err = dencEncryptedData_AppendData(*ppEncData, mbuf1.pMem, mbuf1.nLen); } } } } //ddocDebug(3, "EncTest", "Enc data: \"%s\"", mbuf1.pMem); if(nDel && fname2[0]) remove(fname2); ddocMemBuf_free(&mbuf1); } else { err = dencEncryptedData_AppendData(*ppEncData, p, nSize); } if(nDel && fname1[0]) remove(fname1); if(!err) err = dencEncryptedData_encryptData(*ppEncData, nCompress); if(pSigDoc) SignedDoc_free(pSigDoc); return err; } //-------------------------------------------------- // Encrypts generated test files //-------------------------------------------------- int runEncryptTestSetCmds(int argc, char** argv) { int err = ERR_OK, i, j; DEncEncryptedData* pEncData = 0; DEncEncryptedKey* pEncKey = 0; X509* pCert = 0; char fname[128]; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a recipients key if(!strcmp(argv[i], "-encrypt-test-set")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* certfile = argv[i+1]; char* recipient = argv[i+2]; char* outdir = argv[i+3]; int nStart = atoi(argv[i+4]); int nEnd = atoi(argv[i+5]); int nDdoc = atoi(argv[i+6]); int nDel = atoi(argv[i+7]); for(j = nStart; j < nEnd; j++) { err = ReadCertificate(&pCert, certfile); if(err) return err; pEncData = 0; err = cmdEncryptTestSet(&pEncData, j, outdir, nDdoc, nDel); if(err) return err; err = dencEncryptedKey_new(pEncData, &pEncKey, pCert, DENC_ENC_METHOD_RSA1_5, NULL, recipient, NULL, NULL); sprintf(fname, "%stest-%d.cdoc", outdir, j); err = dencGenEncryptedData_writeToFile(pEncData, fname); dencEncryptedData_free(pEncData); pEncKey = 0; pEncData = 0; } } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Invalid parameters for -encrypt-test-set command"); } } } } return err; } //-------------------------------------------------- // Lists EncryptedData objects //-------------------------------------------------- int cmdListEncryptedData(DEncEncryptedData* pEncData) { int err = ERR_OK, k; char buf1[50], buf2[50]; if(g_cgiMode) { fprintf(stdout, "\nEncryptedData%s%s%s%s%s%s%s%s", g_szOutputSeparator, (pEncData->szId ? pEncData->szId : ""), g_szOutputSeparator, (pEncData->szType ? pEncData->szType : ""), g_szOutputSeparator, (pEncData->szMimeType ? pEncData->szMimeType : ""), g_szOutputSeparator, (pEncData->szEncryptionMethod ? pEncData->szEncryptionMethod : "")); err = dencMetaInfo_GetLibVersion(pEncData, buf1, sizeof(buf1), buf2, sizeof(buf2)); fprintf(stdout, "\nLIBRARY%s%s%s%s", g_szOutputSeparator, buf1, g_szOutputSeparator, buf2); err = dencMetaInfo_GetFormatVersion(pEncData, buf1, sizeof(buf1), buf2, sizeof(buf2)); fprintf(stdout, "\nFORMAT%s%s%s%s", g_szOutputSeparator, buf1, g_szOutputSeparator, buf2); } else { fprintf(stdout, "\nEncryptedData - Id=%s Type=%s MimeType=%s EncryptionMethod=%s", (pEncData->szId ? pEncData->szId : ""), (pEncData->szType ? pEncData->szType : ""), (pEncData->szMimeType ? pEncData->szMimeType : ""), (pEncData->szEncryptionMethod ? pEncData->szEncryptionMethod : "")); err = dencMetaInfo_GetLibVersion(pEncData, buf1, sizeof(buf1), buf2, sizeof(buf2)); fprintf(stdout, "\n\tLIBRARY: %s VERSION: %s", buf1, buf2); err = dencMetaInfo_GetFormatVersion(pEncData, buf1, sizeof(buf1), buf2, sizeof(buf2)); fprintf(stdout, "\n\tFORMAT: %s VERSION: %s", buf1, buf2); } for(k = 0; k < pEncData->nEncryptedKeys; k++) { DEncEncryptedKey *pEncKey = pEncData->arrEncryptedKeys[k]; if(g_cgiMode) fprintf(stdout, "\nEncryptedKey%s%s%s%s%s%s%s%s%s%s%s%s", g_szOutputSeparator, (pEncKey->szId ? pEncKey->szId : ""), g_szOutputSeparator, (pEncKey->szRecipient ? pEncKey->szRecipient : ""), g_szOutputSeparator, (pEncKey->szKeyName ? pEncKey->szKeyName : ""), g_szOutputSeparator, (pEncKey->szCarriedKeyName ? pEncKey->szCarriedKeyName : ""), g_szOutputSeparator, (pEncKey->szEncryptionMethod ? pEncKey->szEncryptionMethod : ""), g_szOutputSeparator, (pEncKey->pCert ? "OK" : "NULL")); else fprintf(stdout, "\nEncryptedKey: Id=%s Recipient=%s KeyName=%s CarriedKeyName=%s EncryptionMethod=%s Cert: %s", (pEncKey->szId ? pEncKey->szId : ""), (pEncKey->szRecipient ? pEncKey->szRecipient : ""), (pEncKey->szKeyName ? pEncKey->szKeyName : ""), (pEncKey->szCarriedKeyName ? pEncKey->szCarriedKeyName : ""), (pEncKey->szEncryptionMethod ? pEncKey->szEncryptionMethod : ""), (pEncKey->pCert ? "OK" : "NULL")); } if(pEncData->encProperties.nEncryptionProperties > 0) { if(g_cgiMode) fprintf(stdout, "\nEncryptionProperties%s%s", g_szOutputSeparator, (pEncData->encProperties.szId ? pEncData->encProperties.szId : "")); else fprintf(stdout, "\nEncryptionProperties: %s", (pEncData->encProperties.szId ? pEncData->encProperties.szId : "")); for(k = 0; k < pEncData->encProperties.nEncryptionProperties; k++) { DEncEncryptionProperty *pEncProp = pEncData->encProperties.arrEncryptionProperties[k]; if(g_cgiMode) fprintf(stdout, "\nEncryptionProperty%s%s%s%s%s%s%s%s\n", g_szOutputSeparator, (pEncProp->szId ? pEncProp->szId : ""), g_szOutputSeparator, (pEncProp->szTarget ? pEncProp->szTarget : ""), g_szOutputSeparator, (pEncProp->szName ? pEncProp->szName : ""), g_szOutputSeparator, (pEncProp->szContent ? pEncProp->szContent : "")); else fprintf(stdout, "\nEncryptionProperty Id=%s Target=%s Name=%s Content=%s\n", (pEncProp->szId ? pEncProp->szId : ""), (pEncProp->szTarget ? pEncProp->szTarget : ""), (pEncProp->szName ? pEncProp->szName : ""), (pEncProp->szContent ? pEncProp->szContent : "")); } } return err; } //-------------------------------------------------- // Add ecryption recipients //-------------------------------------------------- int runDEncListCmds(int argc, char** argv) { int err = ERR_OK, i; DEncEncryptedData* pEncData = 0; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a recipients key if(!strcmp(argv[i], "-denc-list")) { if(argc > i+1 && argv[i+1][0] != '-') { char* file = argv[i+1]; err = dencSaxReadEncryptedData(&pEncData, file); if(!err) err = cmdListEncryptedData(pEncData); if(pEncData && !err) dencEncryptedData_free(pEncData); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -denc-list command"); } } } } return err; } //-------------------------------------------------- // decryption file //-------------------------------------------------- int runDecryptCmds(int argc, char** argv, DEncEncryptedData** ppEncData) { int err = ERR_OK, i, bDecSk = 0, nSlot = 0, nKey = 0; DEncEncryptedKey* pEncKey = 0; FILE *hFile = 0; SignedDoc *pSigDoc = 0; DataFile *pDf = 0; char fname1[256], *pkcs12file = 0, *infile = 0, *pin = 0, key[300]; EVP_PKEY *pkey; #ifdef WIN32 wchar_t *convFileName = 0; int l1 = 0; #endif for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // decrypt file if(!strcmp(argv[i], "-decrypt") || !strcmp(argv[i], "-decrypt-hex") || !strcmp(argv[i], "-decrypt-sk")) { if(!strcmp(argv[i], "-decrypt-sk")) bDecSk = 1; if(argc > i+3 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { ddocConvertInput(argv[i+1], &infile); ddocConvertInput(argv[i+2], &pin); nKey = 0; memset(key, 0, sizeof(key)); if(!strcmp(argv[i], "-decrypt-hex")) { nKey = sizeof(key); hex2bin(pin, (byte*)key, &nKey); } i += 2; if(argc > i+1 && argv[i+1][0] != '-') { ddocConvertInput(argv[i+1], &pkcs12file); i++; } if(argc > i+2 && argv[i+2][0] != '-') { nSlot = atoi(argv[i+2]); i++; } ddocDebug(3, "runDecryptCmds", "Decrypt file: %s pin: %s pkcs12: %s slot: %d", infile, pin, pkcs12file, nSlot); err = dencSaxReadEncryptedData(ppEncData, infile); if(err) return err; // if using hex key if(nKey > 0) { ddocDebug(3, "runDecryptCmds", "Decrypt with key: %s len: %d", pin, nKey); err = dencEncryptedData_decrypt_withKey(*ppEncData, key, nKey); } // if using pkcs12 else if(pkcs12file != NULL && strlen(pkcs12file) > 0) { ddocDebug(3, "runDecryptCmds", "Opening pkcs12 file: %s", pkcs12file); err = dencEncryptedData_findEncryptedKeyByPKCS12(*ppEncData, &pEncKey, &pkey, pkcs12file, pin); } else { ddocDebug(3, "runDecryptCmds", "Connecting to pkcs11, slot: %d", nSlot); err = dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot(*ppEncData, &pEncKey, nSlot); } if(!nKey) { if(pEncKey) { if(pkcs12file != NULL && strlen(pkcs12file) > 0) err = dencEncryptedData_decryptWithKey(*ppEncData, pEncKey, pkey); else err = dencEncryptedData_decryptUsingSlot(*ppEncData, pEncKey, pin, nSlot); if(err) return err; } else { err = ERR_DENC_DECRYPT; addError(err, __FILE__, __LINE__, "No transport key found for your smartcard"); } } // read in ddoc if necessary if(bDecSk && p_szOutFile) { sprintf(fname1, "%s.ddoc", p_szOutFile); ddocDebug(3, "runDecryptCmds", "writing ddoc to: %s", fname1); #ifdef WIN32 err = utf82unicode((const char*)fname1, (char**)&convFileName, &l1); ddocDebug(3, "ddocReadFile", "file: %s, conv-file: %s len: %d", fname1, convFileName, i); if((hFile = _wfopen(convFileName, L"wb")) != NULL) { #else if((hFile = fopen(fname1, "wb")) != NULL) { #endif fwrite((*ppEncData)->mbufEncryptedData.pMem, (*ppEncData)->mbufEncryptedData.nLen, 1, hFile); fclose(hFile); ddocDebug(3, "runDecryptCmds", "Reading ddoc: %s", fname1); err = ddocSaxReadSignedDocFromFile(&pSigDoc, fname1, 0, 0); if(!err && getCountOfDataFiles(pSigDoc) > 0) { pDf = getDataFile(pSigDoc, 0); ddocDebug(3, "runDecryptCmds", "writing DF: %s to: %s", pDf->szId, p_szOutFile); err = ddocExtractDataFile(pSigDoc, fname1, p_szOutFile, pDf->szId, "UTF-8"); dencEncryptedData_free(*ppEncData); *ppEncData = NULL; p_szOutFile = NULL; } SignedDoc_free(pSigDoc); if(fname1[0] && !remove(fname1)) ddocDebug(3, "runDecryptCmds", "error deleting file: %", fname1); } } // p_szOutFile } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing or argument of -decrypt command"); } } } } return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- int runExtractCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a DataFile if(!strcmp(argv[i], "-extract")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* id = NULL; char* file = NULL; char* charset = CHARSET_UTF_8; checkArguments(argc, argv, &i, &id); checkArguments(argc, argv, &i, &file); // optional charset & filenamecharset //checkArguments(argc, argv, &i, &charset); err = ddocExtractDataFile(*ppSigDoc, (const char*)p_szInFile, (const char*)file, (const char*)id, (const char*)charset); // report success if(g_cgiMode) fprintf(stdout, "\nDataFile%s%s%s%s%s%d", g_szOutputSeparator, id, g_szOutputSeparator, file, g_szOutputSeparator, err); else fprintf(stdout, "\nDataFile id: %s path: %s rc: %d", id, file, err); if(id) freeLibMem(id); if(file) freeLibMem(file); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -extract command"); } } } } return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- int runExtractMemCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; char* pBuf = 0; long nLen = 0; FILE* hFile = 0; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // extract DataFile if(!strcmp(argv[i], "-extract-mem")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* id = NULL; char* file = NULL; checkArguments(argc, argv, &i, &id); checkArguments(argc, argv, &i, &file); err = ddocGetDataFileCachedData(*ppSigDoc, id, (void**)&pBuf, &nLen); printf("\nExtract DF: %s, err: %d data: %ld", id, err, nLen); if(file && (hFile = fopen(file, "wb")) != NULL && pBuf && nLen) fwrite(pBuf, nLen, 1, hFile); if(id) freeLibMem(id); if(file) freeLibMem(file); if(hFile) fclose(hFile); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -extract command"); } } } } if(pBuf) freeLibMem(pBuf); if(hFile) fclose(hFile); return err; } //-------------------------------------------------- // Verfys sigantures and notaries //-------------------------------------------------- int runVerifyCmds(int argc, char** argv, SignedDoc* pSigDoc, DEncEncryptedData* pEncData) { int err = ERR_OK, i; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-verify")) { if(pSigDoc) { err = cmdVerify(pSigDoc); } if(pEncData) err = dencValidate(pEncData); } } } return err; } //-------------------------------------------------- // Handles signature commands //-------------------------------------------------- int runSignCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i, nManif, nSlot = 0, nOcsp = 1, nSigner = 1; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-sign")) { char* pin = NULL; char* manifest = NULL; char* city = NULL; char* state = NULL; char* zip = NULL; char* country = NULL; char* sSlot = NULL; char* sOcsp = NULL; char* sSigner = NULL; char* szPkcs12File = NULL; checkArguments(argc, argv, &i, &pin); // if pin is NULL check for autosign pin if(!pin) pin = (char*)ConfigItem_lookup("AUTOSIGN_PIN"); if(!pin) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -sign command"); return err; } // check config file nManif = ConfigItem_lookup_int("MANIFEST_MODE", 0); if(nManif == 2) { manifest = (char*)ConfigItem_lookup("DIGIDOC_ROLE_MANIFEST"); country = (char*)ConfigItem_lookup("DIGIDOC_ADR_COUNTRY"); state = (char*)ConfigItem_lookup("DIGIDOC_ADR_STATE"); city = (char*)ConfigItem_lookup("DIGIDOC_ADR_CITY"); zip = (char*)ConfigItem_lookup("DIGIDOC_ADR_ZIP"); } // optional mainfest argument checkArguments(argc, argv, &i, &manifest); // optional address checkArguments(argc, argv, &i, &city); checkArguments(argc, argv, &i, &state); checkArguments(argc, argv, &i, &zip); checkArguments(argc, argv, &i, &country); checkArguments(argc, argv, &i, &sSlot); checkArguments(argc, argv, &i, &sOcsp); checkArguments(argc, argv, &i, &sSigner); if(sSlot) nSlot = atoi(sSlot); if(sOcsp) nOcsp = atoi(sOcsp); if(sSigner) { if(!strcmp(sSigner, "PKCS11")) nSigner = 1; if(!strcmp(sSigner, "PKCS12")) nSigner = 3; #ifdef WIN32 if(!strcmp(sSigner, "CNG")) nSigner = 2; #endif } checkArguments(argc, argv, &i, &szPkcs12File); err = cmdSign(*ppSigDoc, (const char*)pin, (const char*)manifest, (const char*)city, (const char*)state, (const char*)zip, (const char*)country, nSlot, nOcsp, nSigner, szPkcs12File); if(manifest) freeLibMem(manifest); if(city) freeLibMem(city); if(state) freeLibMem(state); if(zip) freeLibMem(zip); if(country) freeLibMem(country); if(sSlot) freeLibMem(sSlot); if(sOcsp) freeLibMem(sOcsp); if(sSigner) freeLibMem(sSigner); if(szPkcs12File) freeLibMem(szPkcs12File); } } } return err; } //-------------------------------------------------- // Handles commands related to checking certificates //-------------------------------------------------- int runCheckCertCmds(int argc, char** argv) { int err = ERR_OK, i; char* szCertFile = 0; X509* pCert = 0; DigiDocMemBuf mbuf; mbuf.pMem = 0; mbuf.nLen = 0; for(i = 1; !err && (i < argc); i++) { if(!strcmp(argv[i], "-check-cert") && argv[i+1][0] != '-') { szCertFile = argv[i+1]; i++; if(szCertFile) { err = ReadCertificate(&pCert, szCertFile); if(!err && pCert) { err = ddocVerifyCertByOCSP(pCert, NULL); err = ddocCertGetSubjectCN(pCert, &mbuf); printf("Verifying cert: %s --> RC :%d\n", (const char*)mbuf.pMem, err); ddocMemBuf_free(&mbuf); } if(pCert) { X509_free(pCert); pCert = 0; } } } } return err; } //-------------------------------------------------- // Handles commands related to adding signature value // from a file containging base64 encoded RSA-SHA1 signature value //-------------------------------------------------- int runAddSignValueCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i; char *szSignFile = 0, *szSignId = 0; SignatureInfo* pSignInfo = 0; for(i = 1; !err && (i < argc); i++) { if(!strcmp(argv[i], "-add-sign-value") && i < argc - 2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { checkArguments(argc, argv, &i, &szSignFile); checkArguments(argc, argv, &i, &szSignId); if(!pSigDoc) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No digidoc document read in yet!"); return err; } if(szSignFile && szSignId) { pSignInfo = getSignatureWithId(pSigDoc, szSignId); if(pSignInfo) { // read the file err = setSignatureValueFromFile(pSignInfo, szSignFile); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Wrong signature id"); } // report on success if(g_cgiMode) fprintf(stdout, "\nAddSignValue%s%s%s%s%s%d", g_szOutputSeparator, szSignId, g_szOutputSeparator, szSignFile, g_szOutputSeparator, err); else fprintf(stdout, "\nAddSignValue id: %s path: %s rc: %d", szSignId, szSignFile, err); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing or argument of -add-sign-value command"); } } } if(szSignFile) freeLibMem(szSignFile); if(szSignId) freeLibMem(szSignId); return err; } //-------------------------------------------------- // Handles commands related to deleting signatures //-------------------------------------------------- int runDelSignCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i; char *szSignId = 0; SignatureInfo* pSignInfo = 0; for(i = 1; !err && (i < argc); i++) { if(!strcmp(argv[i], "-del-sign") && i < argc - 1 && argv[i+1][0] != '-') { checkArguments(argc, argv, &i, &szSignId); if(!pSigDoc) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No digidoc document read in yet!"); return err; } if(szSignId) { pSignInfo = getSignatureWithId(pSigDoc, szSignId); if(pSignInfo) { err = SignatureInfo_delete(pSigDoc, szSignId); // report on success if(g_cgiMode) fprintf(stdout, "\nDelSign%s%s%s%d", g_szOutputSeparator, szSignId, g_szOutputSeparator, err); else fprintf(stdout, "\nDelSign id: %s rc: %d", szSignId, err); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "wrong signature id!"); } } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -del-sign command"); } } } if(szSignId) freeLibMem(szSignId); return err; } //-------------------------------------------------- // Handles commands related to notarizing signatures //-------------------------------------------------- int runGetConfirmationCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i; char *szSignId = 0; SignatureInfo* pSignInfo = 0; for(i = 1; !err && (i < argc); i++) { if(!strcmp(argv[i], "-get-confirmation") && i < argc - 1 && argv[i+1][0] != '-') { checkArguments(argc, argv, &i, &szSignId); if(!pSigDoc) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No digidoc document read in yet!"); return err; } if(szSignId) { pSignInfo = getSignatureWithId(pSigDoc, szSignId); if(pSignInfo) { err = notarizeSignature(pSigDoc, pSignInfo); // report on success if(g_cgiMode) fprintf(stdout, "\nNotarizeSignature%s%s%s%d", g_szOutputSeparator, szSignId, g_szOutputSeparator, err); else fprintf(stdout, "\nNotarizeSignature id: %s rc: %d", szSignId, err); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "wrong signature id!"); } if(szSignId) freeLibMem(szSignId); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -get-confirmation command"); } } } return err; } //-------------------------------------------------- // Signs the document and gets configrmation //-------------------------------------------------- int cmdCalcSign(SignedDoc* pSigDoc, const char* manifest, const char* city, const char* state, const char* zip, const char* country, const char* certFile) { int err = ERR_OK, l1; SignatureInfo* pSigInfo = NULL; X509* pCert = NULL; char buf1[50]; ddocDebug(3, "cmdCalcSign", "Creating new digital signature"); RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(certFile); // read certificate // this certificate will nto be released since new signature takes ownership! err = ReadCertificate(&pCert, certFile); RETURN_IF_NOT(err == ERR_OK, err); // prepare signature err = ddocPrepareSignature(pSigDoc, &pSigInfo, manifest, city, state, zip, country, pCert, NULL); // base64 encode final hash l1 = sizeof(buf1); err = ddocGetSignedHash(pSigInfo, buf1, &l1, 2, 0); RETURN_IF_NOT(err == ERR_OK, err); // report on success if(g_cgiMode) fprintf(stdout, "\nSignatureHash%s%s%s%s%s%d", g_szOutputSeparator, pSigInfo->szId, g_szOutputSeparator, buf1, g_szOutputSeparator, err); else fprintf(stdout, "\nSignatureHash id: %s hash: %s rc: %d", pSigInfo->szId, buf1, err); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } //-------------------------------------------------- // Handles signature commands //-------------------------------------------------- int runCalcSignCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i, nManif; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-calc-sign")) { char* certFile = NULL; char* manifest = NULL; char* city = NULL; char* state = NULL; char* zip = NULL; char* country = NULL; checkArguments(argc, argv, &i, &certFile); // check config file nManif = ConfigItem_lookup_int("MANIFEST_MODE", 0); if(nManif == 2) { manifest = (char*)ConfigItem_lookup("DIGIDOC_ROLE_MANIFEST"); country = (char*)ConfigItem_lookup("DIGIDOC_ADR_COUNTRY"); state = (char*)ConfigItem_lookup("DIGIDOC_ADR_STATE"); city = (char*)ConfigItem_lookup("DIGIDOC_ADR_CITY"); zip = (char*)ConfigItem_lookup("DIGIDOC_ADR_ZIP"); } // optional mainfest argument checkArguments(argc, argv, &i, &manifest); // optional address checkArguments(argc, argv, &i, &city); checkArguments(argc, argv, &i, &state); checkArguments(argc, argv, &i, &zip); checkArguments(argc, argv, &i, &country); if(!certFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -calc-sign command"); } else err = cmdCalcSign(pSigDoc, (const char*)manifest, (const char*)city, (const char*)state, (const char*)zip, (const char*)country, (const char*)certFile); if(manifest) freeLibMem(manifest); if(city) freeLibMem(city); if(state) freeLibMem(state); if(zip) freeLibMem(zip); if(country) freeLibMem(country); if(certFile) freeLibMem(certFile); } } } return err; } //-------------------------------------------------- // Signs the document and gets configrmation //-------------------------------------------------- int cmdMidSign(SignedDoc* pSigDoc, const char* szPhoneNo, const char* szIdCode, const char* szLang, const char* szService, const char* manifest, const char* city, const char* state, const char* zip, const char* country) { int err = ERR_OK, nPollFreq = 0, l1, nStatus = 0; char* szUrl = 0, *szProxyHost = 0, *szProxyPort = 0; long lSesscode = 0; char buf1[10]; DigiDocMemBuf mbuf1; #ifdef WIN32 time_t tNew, tOld; #endif mbuf1.pMem = 0; mbuf1.nLen = 0; nPollFreq = ConfigItem_lookup_int("DDS_POLLFREQ", 0); szUrl = (char*)ConfigItem_lookup("DDS_URL"); szProxyHost = (char*)ConfigItem_lookup("DDS_PROXY_HOST"); szProxyPort = (char*)ConfigItem_lookup("DDS_PROXY_PORT"); ddocDebug(3, "cmdMidSign", "Creating MID signature using: %s poll freq: %d", szPhoneNo, nPollFreq); // send signature req l1 = sizeof(buf1); ddsSign(pSigDoc, szIdCode, szPhoneNo, szLang, szService, manifest, city, state, zip, country, szUrl, szProxyHost, szProxyPort, &lSesscode, buf1, l1); // report on success if(g_cgiMode) fprintf(stdout, "\nMIDSinatureReq%s%ld%s%d", g_szOutputSeparator, lSesscode, g_szOutputSeparator, err); else fprintf(stdout, "\nMIDSignatureReq session: %ld rc: %d", lSesscode, err); // if we should keep on polling if(!err && nPollFreq) { // now check status do { #ifdef WIN32 time(&tOld); do { time(&tNew); } while(tNew - tOld < nPollFreq); #else ddocDebug(3, "cmdMidSign", "Sleep: %d", nPollFreq); sleep(nPollFreq); #endif err = ddsGetStatusWithFile(pSigDoc, lSesscode, szUrl, szProxyHost, szProxyPort, &nStatus, p_szInFile); ddocDebug(3, "cmdMidSign", "Txn: %ld status: %d err: %d", lSesscode, nStatus, err); } while(!err && nStatus == 1); } if(g_cgiMode) fprintf(stdout, "\nMID session %s%ld%s%d", g_szOutputSeparator, lSesscode, g_szOutputSeparator, nStatus); else fprintf(stdout, "\nMID session %ld complete status: %d", lSesscode, nStatus); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } //-------------------------------------------------- // Handles MID signature commands //-------------------------------------------------- int runMidSignCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i, nManif = 0; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-mid-sign")) { char* phoneNo = NULL; char* idcode = NULL; char* service = NULL; char* lang = NULL; char* manifest = NULL; char* city = NULL; char* state = NULL; char* zip = NULL; char* country = NULL; checkArguments(argc, argv, &i, &phoneNo); // check config file nManif = ConfigItem_lookup_int("MANIFEST_MODE", 0); if(nManif == 2) { manifest = (char*)ConfigItem_lookup("DIGIDOC_ROLE_MANIFEST"); country = (char*)ConfigItem_lookup("DIGIDOC_ADR_COUNTRY"); state = (char*)ConfigItem_lookup("DIGIDOC_ADR_STATE"); city = (char*)ConfigItem_lookup("DIGIDOC_ADR_CITY"); zip = (char*)ConfigItem_lookup("DIGIDOC_ADR_ZIP"); } // optional mainfest argument checkArguments(argc, argv, &i, &idcode); checkArguments(argc, argv, &i, &country); checkArguments(argc, argv, &i, &lang); checkArguments(argc, argv, &i, &service); checkArguments(argc, argv, &i, &manifest); checkArguments(argc, argv, &i, &city); checkArguments(argc, argv, &i, &state); checkArguments(argc, argv, &i, &zip); if(!phoneNo) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -mid-sign command"); } else cmdMidSign(pSigDoc, (const char*)phoneNo, (const char*)idcode, (const char*)(lang ? lang : "EST"), (const char*)(service ? service : "Testimine"), (const char*)manifest, (const char*)city, (const char*)state, (const char*)zip, (const char*)(country ? country : "EE")); if(manifest) freeLibMem(manifest); if(city) freeLibMem(city); if(state) freeLibMem(state); if(zip) freeLibMem(zip); if(country) freeLibMem(country); if(phoneNo) freeLibMem(phoneNo); } } } return err; } //-------------------------------------------------- // Handles MID signature commands //-------------------------------------------------- int runMidTestCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i, e1; SignedDoc *pSdoc = NULL; DataFile *pDf = NULL; long lSize1, lSize2, lSize3; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-mid-test")) { char* infile = NULL; char* inmime = NULL; char* outddoc = NULL; char* phoneNo = NULL; char* idcode = NULL; char* service = NULL; checkArguments(argc, argv, &i, &infile); checkArguments(argc, argv, &i, &inmime); checkArguments(argc, argv, &i, &outddoc); checkArguments(argc, argv, &i, &phoneNo); checkArguments(argc, argv, &i, &idcode); checkArguments(argc, argv, &i, &service); if(!phoneNo || !idcode || !infile || !inmime || !outddoc) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing or argument of -mid-test command"); } else { p_szInFile = outddoc; printf("Creating ddoc: %s of file: %s mime: %s\n", outddoc, infile, inmime); err = SignedDoc_new(&pSdoc, "DIGIDOC-XML", "1.3"); printf("Creating ddoc: %s rc: %d\n", outddoc, err); RETURN_IF_NOT(err == ERR_OK, err); err = calculateFileSize(infile, &lSize1); err = DataFile_new(&pDf, pSdoc, NULL, infile, "EMBEDDED_BASE64", inmime, 0, NULL, 0, NULL, NULL); err = createSignedDoc(pSdoc, NULL, outddoc); if(pDf->nSize == 0 && lSize1 > 0) pDf->nSize = lSize1; err = calculateFileSize(outddoc, &lSize2); printf("Add data-file: %s rc: %d d-size: %ld ddoc-size: %ld\n", infile, err, lSize1, lSize2); err = ddocExtractDataFile(pSdoc, outddoc, "D0.dat", "D0", "UTF-8"); err = calculateFileSize("D0.dat", &lSize3); printf("Extract before signing rc: %d size: %ld\n", err, lSize3); printf("MID signing phone: %s id-code: %s\n", phoneNo, idcode); err = cmdMidSign(pSdoc, (const char*)phoneNo, (const char*)idcode, "EST", (service ? service : "Testimine"), NULL, NULL, NULL, NULL, "EE"); err = calculateFileSize(outddoc, &lSize2); printf("MID signed phone: %s id-code: %s ddoc-size: %ld rc: %d\n", phoneNo, idcode, lSize2, err); err = cmdVerify(pSdoc); printf("\nVerify after signing rc: %d\n", err); lSize3 = 0; err = ddocExtractDataFile(pSdoc, outddoc, "D0.dat", "D0", "UTF-8"); err = calculateFileSize("D0.dat", &lSize3); printf("Extract after signing rc: %d size: %ld\n", err, lSize3); } SignedDoc_free(pSdoc); if(infile) freeLibMem(infile); if(inmime) freeLibMem(inmime); if(outddoc) freeLibMem(outddoc); if(phoneNo) freeLibMem(phoneNo); if(idcode) freeLibMem(idcode); if(service) freeLibMem(service); } } } return err; } //-------------------------------------------------- // Program main function //-------------------------------------------------- int main(int argc, char** argv) { int err = ERR_OK, e = 0; SignedDoc* pSigDoc = 0; DEncEncryptedData* pEncData = 0; time_t t1, t2; #ifdef WIN32 char buf1[250]; #endif if(argc <= 1) { printUsage(); exit(0); } // init DigiDoc library initDigiDocLib(); #ifdef WIN32 // find out program home if invoked with a long command line memset(buf1, 0, sizeof(buf1)); getFileNamePath(argv[0], buf1, sizeof(buf1)); if(strlen(buf1)) { strncat(buf1, "digidoc.ini", sizeof(buf1)); err = initConfigStore(buf1); } else err = initConfigStore(NULL); #else // read in config file err = initConfigStore(NULL); #endif // clear all errors that were encountered by not finding config files err = checkProgArguments(argc, argv); time(&t1); // register program name and version setGUIVersion(g_szProgNameVer); ddocDebugTruncateLog(); // use command line argument if required if(p_szConfigFile) err = readConfigFile(p_szConfigFile, ITEM_TYPE_PRIVATE); // read flags from config file readConfigParams(); // display programm name and version if(g_cgiMode) { if(ConfigItem_lookup_bool("DIGIDOC_CGI_PRINT_HEADER", 1)) fprintf(stdout, "%s%s%s", getLibName(), g_szOutputSeparator, getLibVersion()); } else { fprintf(stdout, "%s - %s", getLibName(), getLibVersion()); } // execute the commands now // check certificate status throught OCSP if(!err) err = runCheckCertCmds(argc, argv); // read input file if necessary if(p_szInFile && !err) { if(p_parseMode != 3) err = cmdReadDigiDoc(&pSigDoc, &pEncData, p_parseMode); else err = cmdReadDigiDocFromMem(&pSigDoc, &pEncData); // if read error was warning then continue if(pSigDoc && isWarning(pSigDoc, err)) err = ERR_OK; if(err && pSigDoc) printErrorsAndWarnings(pSigDoc); } // various tests if(!err) err = runTestCmds(argc, argv); if(p_szInEncFile && !err) { if(hasCmdLineArg(argc, argv, "-encrypt-sk")) err = cmdEncryptSk(&pEncData, p_szInEncFile); else err = cmdEncrypt(&pEncData, p_szInEncFile); } // list encrypted files if(!err) err = runDEncListCmds(argc, argv); // add data files if(!err) err = runAddCmds(argc, argv, &pSigDoc); // add data files from mem if(!err) err = runAddMemCmds(argc, argv, &pSigDoc); // add recipients if(!err) err = runRecipientCmds(argc, argv, &pEncData); // encrypt whole files if(!err) err = runEncryptFileCmds(argc, argv, pEncData); // decrypt whole files if(!err) err = runDecryptFileCmds(argc, argv); // run signature commands if(!err) err = runSignCmds(argc, argv, &pSigDoc); // calculate signature hash commands if(!err) err = runCalcSignCmds(argc, argv, pSigDoc); if(!err) err = runMidSignCmds(argc, argv, pSigDoc); if(!err) err = runMidTestCmds(argc, argv, pSigDoc); // verify signatures if(!err) { e = runVerifyCmds(argc, argv, pSigDoc, pEncData); if(!err && e) err = e; } // extract datafiles if(!err) err = runExtractCmds(argc, argv, &pSigDoc); if(!err) err = runExtractMemCmds(argc, argv, &pSigDoc); // decrypt files if(!err) err = runDecryptCmds(argc, argv, &pEncData); // add signature value from a file if(!err) err = runAddSignValueCmds(argc, argv, pSigDoc); // delete signatures if(!err) err = runDelSignCmds(argc, argv, pSigDoc); // notarize signatures if(!err) err = runGetConfirmationCmds(argc, argv, pSigDoc); if(!err) err = runEncryptTestSetCmds(argc, argv); // write output file if(p_szOutFile && !err) if(p_parseMode != 3) err = cmdWrite(pSigDoc, pEncData); else err = cmdWriteMem(pSigDoc, pEncData); time(&t2); printErrorsAndWarnings(pSigDoc); if(pSigDoc && !isError(pSigDoc, err)) { // find correct error from list e = hasErrors(pSigDoc); if((!err || !isError(pSigDoc,err)) && e) err = e; } // display programm error code and elapsed time if(g_cgiMode) { if(ConfigItem_lookup_bool("DIGIDOC_CGI_PRINT_TRAILER", 1)) fprintf(stdout, "\n%s%s%d%s%ld", getLibName(), g_szOutputSeparator, (isError(pSigDoc,err) ? err : 0), g_szOutputSeparator, (long)(t2-t1)); } else { fprintf(stdout, "\n%s - time: %ld sec result: %s", getLibName(), (long)(t2-t1), (isError(pSigDoc,err) ? "failure" : "success")); } fprintf(stdout, "\n"); // cleanup if(pSigDoc) SignedDoc_free(pSigDoc); if(pEncData) dencEncryptedData_free(pEncData); if(g_szOutputSeparator) free(g_szOutputSeparator); // cleanup #ifndef WIN32 // TODO: somehow this free gives invalid heap error on win32 cleanupConfigStore(NULL); #endif finalizeDigiDocLib(); return err; }