summaryrefslogtreecommitdiff
path: root/libdigidoc/DigiDocObj.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdigidoc/DigiDocObj.c')
-rw-r--r--libdigidoc/DigiDocObj.c4415
1 files changed, 4415 insertions, 0 deletions
diff --git a/libdigidoc/DigiDocObj.c b/libdigidoc/DigiDocObj.c
new file mode 100644
index 0000000..4845f3e
--- /dev/null
+++ b/libdigidoc/DigiDocObj.c
@@ -0,0 +1,4415 @@
+//==================================================
+// FILE: DigiDocObj.c
+// PROJECT: Digi Doc
+// DESCRIPTION: DigiDoc helper routines for accessing dogidoc data
+// 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 >=============================
+// 26.04.2006 Veiko Sinivee
+// Creation
+//==================================================
+
+#include "DigiDocObj.h"
+#include "DigiDocGen.h"
+#include "DigiDocError.h"
+#include "DigiDocConvert.h"
+#include "DigiDocDebug.h"
+#include "DigiDocCert.h"
+#include "DigiDocOCSP.h"
+#include "DigiDocConfig.h"
+#include "DigiDocError.h"
+#include <string.h>
+#include <ctype.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+//============================================================
+// Sets a string element of a struct to a new value
+// dest - element pointer
+// value - new value
+// valLen - value length (use -1 for null terminated strings)
+//============================================================
+EXP_OPTION int setString(char** dest, const char* value, int valLen)
+{
+ RETURN_IF_NULL_PARAM(dest);
+ RETURN_IF_NULL_PARAM(value);
+
+ if(*dest) {
+ free(*dest);
+ *dest = NULL;
+ }
+ if(valLen == -1) {
+ *dest = (char*)malloc(strlen(value)+1);
+ RETURN_IF_BAD_ALLOC(*dest);
+ strncpy(*dest, value, strlen(value)+1);
+ } else {
+ *dest = (char*)malloc(valLen);
+ RETURN_IF_BAD_ALLOC(*dest);
+ memcpy(*dest, value, valLen);
+ }
+ return ERR_OK;
+}
+
+//============================================================
+// Allocates a new SignedDoc element and initializes it
+// format - format name
+// version - format version
+//============================================================
+EXP_OPTION int SignedDoc_new(SignedDoc **pSignedDoc, const char* format, const char* version)
+{
+ SignedDoc* pSigDoc = NULL;
+
+ RETURN_IF_NULL_PARAM(format);
+ RETURN_IF_NULL_PARAM(version);
+ ddocDebug(3, "SignedDoc_new", "format: %s version: %s", (format ? format : "NULL"), (version ? version : "NULL"));
+ pSigDoc = (SignedDoc*)malloc(sizeof(SignedDoc));
+ RETURN_IF_BAD_ALLOC(pSigDoc);
+ memset(pSigDoc, 0, sizeof(SignedDoc));
+ if(!strcmp(format, DIGIDOC_XML_1_1_NAME) &&
+ !strcmp(version, DIGIDOC_XML_1_3_VER)) {
+ setString(&(pSigDoc->szFormat), format, -1);
+ setString(&(pSigDoc->szFormatVer), version, -1);
+ setString(&(pSigDoc->szFileName), "", -1);
+ } else {
+ ddocDebug(3, "SignedDoc_new", "unsupported version");
+ SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_FORMAT);
+ }
+ *pSignedDoc = pSigDoc;
+ return ERR_OK;
+}
+
+//============================================================
+// Frees the memory of SignedDoc element
+// pSigDoc - element to free
+//============================================================
+EXP_OPTION void SignedDoc_free(SignedDoc* pSigDoc)
+{
+ int i;
+
+ RETURN_VOID_IF_NULL(pSigDoc);
+ for(i = 0; (pSigDoc->pDataFiles != NULL) &&
+ (i < pSigDoc->nDataFiles); i++)
+ DataFile_free(pSigDoc->pDataFiles[i]);
+ if(pSigDoc->pDataFiles)
+ free(pSigDoc->pDataFiles);
+ for(i = 0; (pSigDoc->pSignatures != NULL) &&
+ (i < pSigDoc->nSignatures); i++)
+ SignatureInfo_free(pSigDoc->pSignatures[i]);
+ if(pSigDoc->pSignatures)
+ free(pSigDoc->pSignatures);
+ if(pSigDoc->szFormat)
+ free(pSigDoc->szFormat);
+ if(pSigDoc->szFormatVer)
+ free(pSigDoc->szFormatVer);
+ if(pSigDoc->szFileName)
+ free(pSigDoc->szFileName);
+ if(pSigDoc->szProfile)
+ free(pSigDoc->szProfile);
+ if(pSigDoc)
+ free(pSigDoc);
+}
+
+
+//============================================================
+// Returns the number of data files
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION int getCountOfDataFiles(const SignedDoc* pSigDoc)
+{
+ RETURN_OBJ_IF_NULL(pSigDoc, 0);
+ return pSigDoc->nDataFiles;
+}
+
+//============================================================
+// Returns the next free data file id
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION int getNextDataFileId(const SignedDoc* pSigDoc)
+{
+ int id = 0, n, i;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, 0);
+ for(i = 0; i < pSigDoc->nDataFiles; i++) {
+ DataFile* pDataFile = pSigDoc->pDataFiles[i];
+ RETURN_OBJ_IF_NULL(pDataFile, 0);
+ RETURN_OBJ_IF_NULL(pDataFile->szId, 0);
+ SET_LAST_ERROR_RETURN_IF_NOT(strlen(pDataFile->szId) > 1, ERR_EMPTY_STRING, 0);
+ n = atoi(pDataFile->szId+1);
+ if(id <= n)
+ id = n+1;
+ }
+ return id;
+}
+
+//============================================================
+// Returns the desired DataFile object
+// pSigDoc - signed doc pointer
+// nIdx - DataFile index (starting with 0)
+//============================================================
+EXP_OPTION DataFile* getDataFile(const SignedDoc* pSigDoc, int nIdx)
+{
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigDoc->nDataFiles, ERR_BAD_DATAFILE_INDEX, NULL);
+ RETURN_OBJ_IF_NULL(pSigDoc->pDataFiles[nIdx], 0);
+ return pSigDoc->pDataFiles[nIdx];
+}
+
+//============================================================
+// Returns the last DataFile object
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION DataFile* ddocGetLastDataFile(const SignedDoc* pSigDoc)
+{
+ int nIdx;
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ nIdx = pSigDoc->nDataFiles - 1;
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0, ERR_BAD_DATAFILE_INDEX, NULL);
+ RETURN_OBJ_IF_NULL(pSigDoc->pDataFiles[nIdx], 0);
+ return pSigDoc->pDataFiles[nIdx];
+}
+
+//============================================================
+// Returns the DataFile object with the given id
+// pSigDoc - signed doc pointer
+// id - DataFile id
+//============================================================
+EXP_OPTION DataFile* getDataFileWithId(const SignedDoc* pSigDoc, const char* id)
+{
+ DataFile* pDataFile = NULL;
+ int i;
+ //AA 12.11.2003
+ RETURN_OBJ_IF_NULL(id, NULL);
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ ddocDebug(4, "getDataFileWithId", "id: \'%s\', files: %d", id, pSigDoc->nDataFiles);
+ for(i = 0; i < pSigDoc->nDataFiles; i++) {
+ RETURN_OBJ_IF_NULL(pSigDoc->pDataFiles[i], NULL);
+ RETURN_OBJ_IF_NULL(pSigDoc->pDataFiles[i]->szId, NULL);
+ if(!strcmp(pSigDoc->pDataFiles[i]->szId, id)) {
+ pDataFile = pSigDoc->pDataFiles[i];
+ break;
+ }
+ }
+ return pDataFile;
+}
+
+
+//============================================================
+// Adds a new DataFile element to a SignedDoc element and initializes it
+// pSigDoc - signed document
+// id - data file id
+// filename - filename
+// contentType - EMBEDDED or EMBEDDED_BASE64
+// mime - mime type
+// size - file size
+// digType - digestType
+// digest - file digest (SHA1)
+// digLen - digest length
+//============================================================
+EXP_OPTION int DataFile_new(DataFile **newDataFile,
+ SignedDoc* pSigDoc, const char* id,
+ const char* filename, const char* contentType,
+ const char* mime, long size,
+ const byte* digest, int digLen,
+ const char* digType, const char* szCharset)
+{
+ char buf1[300];
+ int nId = 0, i, j, n;
+ DataFile **pDataFiles;
+ DataFile *pDataFile;
+ FILE* hFile;
+
+ RETURN_IF_NULL_PARAM(newDataFile);
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ ddocDebug(3, "DataFile_new", "SigDoc ver: %s, file: %s, contentType: %s, mimeType: %s",
+ (pSigDoc ? pSigDoc->szFormatVer : "NULL"), (filename ? filename : "NULL"), contentType, mime);
+ //clearErrors();
+ if(!id)
+ nId = getNextDataFileId(pSigDoc);
+ if(pSigDoc->nDataFiles == 0) {
+ SET_LAST_ERROR_RETURN_IF_NOT(!pSigDoc->pDataFiles, ERR_BAD_DATAFILE_COUNT, 0);
+ pSigDoc->nDataFiles = 1;
+ }
+ else
+ pSigDoc->nDataFiles++;
+ pDataFiles = (DataFile**)malloc((pSigDoc->nDataFiles) * sizeof(void *));
+
+ RETURN_IF_BAD_ALLOC(pDataFiles);
+ for(i = 0; i < pSigDoc->nDataFiles-1; i++)
+ pDataFiles[i] = pSigDoc->pDataFiles[i];
+ pDataFile = (DataFile*)malloc(sizeof(DataFile));
+ RETURN_IF_BAD_ALLOC(pDataFile);
+ memset(pDataFile, 0, sizeof(DataFile));
+ pDataFiles[pSigDoc->nDataFiles-1] = pDataFile;
+ if(pSigDoc->pDataFiles)
+ free(pSigDoc->pDataFiles);
+ pSigDoc->pDataFiles = pDataFiles;
+ if(id) {
+ j = 0; n = strlen(id);
+ if(n < 2 || id[0] != 'D') j = -1;
+ if(j == 0 && n >= 2 && !isdigit(id[1]) && id[1] != 'O') j = -1;
+ for(i = 2; j == 0 && i < n; i++)
+ if(!isdigit(id[i])) j = -1;
+ if(j == -1) {
+ ddocDebug(1, "DataFile_new", "Invalid DataFile id: %s", id);
+ SET_LAST_ERROR(ERR_BAD_PARAM);
+ }
+ setString(&(pDataFile->szId), id, -1);
+ } else {
+ snprintf(buf1, sizeof(buf1), "D%d", nId);
+ setString(&(pDataFile->szId), buf1, -1);
+ }
+ if(szCharset)
+ setString(&(pDataFile->szCharset), szCharset, -1);
+ else
+ setString(&(pDataFile->szCharset), CHARSET_ISO_8859_1, -1);
+ if(filename) {
+ // in versions 1.0, 1.1 and 1.2 we used wrong encoding for OEM windows charset
+ setString(&(pDataFile->szFileName), filename, -1);
+ if(!strcmp(contentType, CONTENT_EMBEDDED)) {
+ if((hFile = fopen(pDataFile->szFileName, "rt")) != NULL) {
+ fgets(buf1, sizeof(buf1), hFile);
+ if(strstr(buf1, "<?xml"))
+ SET_LAST_ERROR(ERR_BAD_DATAFILE_XML);
+ fclose(hFile);
+ }
+ }
+ }
+ if(mime)
+ setString(&(pDataFile->szMimeType), mime, -1);
+ if((!contentType || strcmp(contentType, CONTENT_EMBEDDED_BASE64))
+ && !ConfigItem_lookup_bool("EMBEDDED_XML_SUPPORT", 0)) {
+ SET_LAST_ERROR(ERR_BAD_DATAFILE_CONTENT_TYPE);
+ return ERR_BAD_DATAFILE_CONTENT_TYPE;
+ }
+ if(contentType)
+ setString(&(pDataFile->szContentType), contentType, -1);
+ pDataFile->nSize = size;
+ if(digType && strlen(digType))
+ setString(&(pDataFile->szDigestType), digType, -1);
+ if(digest && digLen)
+ ddocMemAssignData(&(pDataFile->mbufDigest), (const char*)digest, digLen);
+ *newDataFile = pDataFile;
+ return ERR_OK;
+}
+
+
+//============================================================
+// Removes this DataFile from signed doc and frees it's memory
+// pSigDoc - signed doc object
+// id - DataFile id to be removed
+//============================================================
+EXP_OPTION int DataFile_delete(SignedDoc* pSigDoc, const char* id)
+{
+ int err = ERR_OK, n, i, j;
+ DataFile* pDataFile = NULL;
+ DataFile** pDataFiles = NULL;
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ ddocDebug(3, "DataFile_delete", "id: %s", id);
+ if(pSigDoc->nSignatures > 0)
+ SET_LAST_ERROR_RETURN_CODE(ERR_MODIFY_SIGNED_DOC);
+ if((pDataFile = getDataFileWithId(pSigDoc, id)) != 0) {
+ n = pSigDoc->nDataFiles - 1;
+ if(n > 0) {
+ pDataFiles = (DataFile**)malloc(n * sizeof(void*));
+ RETURN_IF_BAD_ALLOC(pDataFiles);
+ for(i = j = 0; i < pSigDoc->nDataFiles; i++) {
+ if(strcmp(pSigDoc->pDataFiles[i]->szId, id))
+ pDataFiles[j++] = pSigDoc->pDataFiles[i];
+ else{
+ DataFile_free(pSigDoc->pDataFiles[i]);}
+ }
+ free(pSigDoc->pDataFiles);
+ pSigDoc->pDataFiles = pDataFiles;
+ pSigDoc->nDataFiles = n;
+ } else {
+ for(i = 0; i < pSigDoc->nDataFiles; i++){
+ DataFile_free(pSigDoc->pDataFiles[i]);}
+ free(pSigDoc->pDataFiles);
+ pSigDoc->pDataFiles = NULL;
+ pSigDoc->nDataFiles = 0;
+ }
+ }
+ else
+ err = ERR_BAD_DATAFILE_INDEX;
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+//============================================================
+// Retrieve and convert cached DataFile data if possible
+// pSigDoc - signed document object
+// szDocId - datafile id
+// ppBuf - address of buffer pointer
+// pLen - address of lenght of bytes
+//============================================================
+EXP_OPTION int ddocGetDataFileCachedData(SignedDoc* pSigDoc, const char* szDocId, void** ppBuf, long* pLen)
+{
+ DataFile* pDf;
+ DigiDocMemBuf mbuf1;
+ int err1 = 0;
+
+ mbuf1.pMem = 0; mbuf1.nLen = 0;
+
+ //RETURN_IF_NULL_PARAM(pSigDoc); // if null then don't check for cached data (old logic)
+ RETURN_IF_NULL_PARAM(szDocId);
+ RETURN_IF_NULL_PARAM(ppBuf);
+ RETURN_IF_NULL_PARAM(pLen);
+ *ppBuf = 0;
+ *pLen = 0;
+ if(pSigDoc) {
+ pDf = getDataFileWithId(pSigDoc, szDocId);
+ if(pDf && pDf->mbufContent.pMem) { // gotcha!
+ int len;
+ // base64 content, allocate exact length and initialize
+ if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64)) {
+ err1 = ddocMemSetLength(&mbuf1, pDf->mbufContent.nLen);
+ if(err1) {
+ ddocMemBuf_free(&mbuf1);
+ return err1;
+ }
+ *ppBuf = mbuf1.pMem;
+ *pLen = mbuf1.nLen;
+ err1 = ddocDecodeBase64(&(pDf->mbufContent), &mbuf1);
+ if(err1) {
+ ddocMemBuf_free(&mbuf1);
+ return err1;
+ }
+ mbuf1.pMem = 0; mbuf1.nLen = 0; // release ownership
+ }
+ // simple text content. Make it zero terminated string
+ else if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED)) {
+ *ppBuf = malloc(pDf->mbufContent.nLen+1);
+ RETURN_IF_BAD_ALLOC(*ppBuf);
+ *pLen = pDf->mbufContent.nLen;
+ memcpy(*ppBuf, pDf->mbufContent.pMem, pDf->mbufContent.nLen);
+ ((char*)(*ppBuf))[*pLen] = 0;
+ }
+ }
+ }
+ return ERR_OK;
+}
+
+//============================================================
+// Retrieve and convert DataFile Filename atribute and convert
+// to proper UTF-8 if necessary.
+// pSigDoc - signed document object
+// szDocId - datafile id
+// ppBuf - address of buffer pointer. Caller must free the buffer
+// pLen - address of lenght of bytes. Will be changed.
+//============================================================
+EXP_OPTION int ddocGetDataFileFilename(SignedDoc* pSigDoc, const char* szDocId, void** ppBuf, int* pLen)
+{
+ DataFile* pDf;
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ RETURN_IF_NULL_PARAM(szDocId);
+ RETURN_IF_NULL_PARAM(ppBuf);
+ RETURN_IF_NULL_PARAM(pLen);
+ *ppBuf = 0;
+ *pLen = 0;
+ if(pSigDoc) {
+ pDf = getDataFileWithId(pSigDoc, szDocId);
+ if(pDf && pDf->szFileName) { // gotcha!
+ *ppBuf = unescapeXmlsym((const char*)pDf->szFileName);
+ *pLen = strlen((const char*)*ppBuf);
+ // in version 1.2 and earlier we had bad UTF-8 for some chars
+ // check and fix it for newer clients
+ if((!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) ||
+ !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) ||
+ !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) {
+ convWinToFName(pDf->szFileName, (char*)*ppBuf, *pLen+1);
+ }
+ }
+ }
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Checks if the size of this DataFile is less than
+// max size for memory cache and if so caches the data.
+// pDf - DataFile object
+// maxLen - max cacheable DataFile size
+// value - character values read from file
+// len - length of chars ???
+// isBase64 - is allready in base64 form or not (1/0)
+//--------------------------------------------------
+EXP_OPTION void ddocAppendDataFileData(DataFile* pDf, int maxLen, void* data, int len, int isBase64)
+{
+ DigiDocMemBuf mbuf1, mbuf2;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ ddocDebug(5, "ddocAppendDataFileData", "append: %d, max: %d", len, maxLen);
+ if(pDf && pDf->nSize < maxLen) {
+ ddocDebug(6, "ddocAppendDataFileData", "DF: %s, size: %d, max: %d", pDf->szId, pDf->nSize, maxLen);
+ // original content must be kept in the form it will exist in file
+ if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64) && !isBase64) {
+ mbuf2.pMem = data;
+ mbuf2.nLen = len;
+ ddocEncodeBase64(&mbuf2, &mbuf1);
+ ddocMemAppendData(&(pDf->mbufContent), mbuf1.pMem, mbuf1.nLen);
+ ddocMemBuf_free(&mbuf1);
+ }
+ else
+ ddocMemAppendData(&(pDf->mbufContent), data, len);
+ }
+}
+
+//--------------------------------------------------
+// Creates new DataFile and assigns contet from memory
+// ppDataFile address of pointer to return new DataFile object
+// pSigDoc - SignedDoc object
+// id - new DataFile id. Use NULL for default
+// filename - filename
+// contentType - content type
+// mime - mime type
+// pData - address of DataFile content to be assigned
+// size - length of data in bytes
+// return error code
+//--------------------------------------------------
+EXP_OPTION int createDataFileInMemory(DataFile **ppDataFile, SignedDoc* pSigDoc, const char* id,
+ const char* filename, const char* contentType,
+ const char* mime, const char* pData, long size)
+{
+ int err = ERR_OK;
+ DigiDocMemBuf mbuf1;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ err = DataFile_new(ppDataFile, pSigDoc, id,
+ filename, contentType,
+ mime, size, NULL, 0, DIGEST_SHA1_NAME, NULL);
+ if(!err && pData) {
+ ddocAppendDataFileData(*ppDataFile, size+1, (void*)pData, size, 0);
+ // calculate hash so it can be used in signing
+ err = generateDataFileXML(pSigDoc, *ppDataFile, NULL, NULL, &mbuf1);
+ ddocMemBuf_free(&mbuf1);
+ }
+ return err;
+}
+
+//============================================================
+// cleanup DataFile memory
+// pDataFile - data file object to be cleaned up
+//============================================================
+EXP_OPTION void DataFile_free(DataFile* pDataFile)
+{
+ int i=0;
+
+ RETURN_VOID_IF_NULL(pDataFile);
+ if(pDataFile->szId)
+ free(pDataFile->szId);
+ if(pDataFile->szFileName)
+ free(pDataFile->szFileName);
+ if(pDataFile->szMimeType)
+ free(pDataFile->szMimeType);
+ if(pDataFile->szDigestType)
+ free(pDataFile->szDigestType);
+ ddocMemBuf_free(&(pDataFile->mbufDigest));
+ ddocMemBuf_free(&(pDataFile->mbufWrongDigest));
+ ddocMemBuf_free(&(pDataFile->mbufDetachedDigest));
+ if(pDataFile->szContentType)
+ free(pDataFile->szContentType);
+ for(i = 0; i < pDataFile->nAttributes; i++) {
+ free(pDataFile->pAttNames[i]);
+ free(pDataFile->pAttValues[i]);
+ }
+ if(pDataFile->szCharset)
+ free(pDataFile->szCharset);
+ if(pDataFile->pAttNames)
+ free(pDataFile->pAttNames);
+ if(pDataFile->pAttValues)
+ free(pDataFile->pAttValues);
+ ddocMemBuf_free(&(pDataFile->mbufContent));
+ free(pDataFile);
+}
+
+//--------------------------------------------------
+// Accessor for Digest atribute of DataFile object.
+// pDataFile - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION DigiDocMemBuf* ddocDataFile_GetDigestValue(DataFile* pDataFile)
+{
+ RETURN_OBJ_IF_NULL(pDataFile, NULL)
+ return &(pDataFile->mbufDigest);
+}
+
+//--------------------------------------------------
+// Mutatoror for Digest atribute of DataFile object.
+// pDataFile - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// len - length of value in bytes [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocDataFile_SetDigestValue(DataFile* pDataFile,
+ const char* value, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pDataFile)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignData(&(pDataFile->mbufDigest), value, len);
+ return err;
+}
+
+
+//--------------------------------------------------
+// Accessor for DetachedDigest atribute of DataFile object.
+// pDataFile - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION DigiDocMemBuf* ddocDataFile_GetDetachedDigestValue(DataFile* pDataFile)
+{
+ RETURN_OBJ_IF_NULL(pDataFile, NULL)
+ return &(pDataFile->mbufDetachedDigest);
+}
+
+//--------------------------------------------------
+// Mutatoror for DetachedDigest atribute of DataFile object.
+// pDataFile - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// len - length of value in bytes [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocDataFile_SetDetachedDigestValue(DataFile* pDataFile,
+ const char* value, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pDataFile)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignData(&(pDataFile->mbufDetachedDigest), value, len);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for WrongDigest atribute of DataFile object.
+// pDataFile - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION DigiDocMemBuf* ddocDataFile_GetWrongDigestValue(DataFile* pDataFile)
+{
+ RETURN_OBJ_IF_NULL(pDataFile, NULL)
+ return &(pDataFile->mbufWrongDigest);
+}
+
+//--------------------------------------------------
+// Mutatoror for WrongDigest atribute of DataFile object.
+// pDataFile - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// len - length of value in bytes [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocDataFile_SetWrongDigestValue(DataFile* pDataFile,
+ const char* value, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pDataFile)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignData(&(pDataFile->mbufWrongDigest), value, len);
+ return err;
+}
+
+//============================================================
+// Removes this NotaryInfo from signed doc and frees it's memory
+// pSigInfo - signature object
+// id - notary id to be removed
+//============================================================
+EXP_OPTION int NotaryInfo_delete(SignatureInfo* pSigInfo)
+{
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ if(pSigInfo->pNotary) {
+ NotaryInfo_free(pSigInfo->pNotary);
+ pSigInfo->pNotary = 0;
+ }
+ return ERR_OK;
+}
+
+//============================================================
+// Returns number of DataFile attributes
+// pDataFile - data file
+//============================================================
+EXP_OPTION int getCountOfDataFileAttributes(const DataFile* pDataFile)
+{
+ RETURN_OBJ_IF_NULL(pDataFile, -1);
+ return pDataFile->nAttributes;
+}
+
+//============================================================
+// Adds an attribute to data file
+// pDataFile - data file
+// name - attribute name
+// value - attribute value
+//============================================================
+// FIXME : Badly in need for a rewrite - memory leaks, when something fails.
+int addDataFileAttribute(DataFile* pDataFile, const char* name, const char* value)
+{
+ char **pp;
+ int i;
+
+ RETURN_IF_NULL_PARAM(pDataFile);
+ RETURN_IF_NULL_PARAM(name);
+ RETURN_IF_NULL_PARAM(value);
+ if(pDataFile->nAttributes == 0) {
+ RETURN_IF_NOT(!pDataFile->pAttNames, ERR_BAD_ATTR_COUNT);
+ RETURN_IF_NOT(!pDataFile->pAttValues, ERR_BAD_ATTR_COUNT);
+ pDataFile->nAttributes = 1;
+ }
+ else
+ pDataFile->nAttributes++;
+ // set name
+ pp = (char**)malloc((pDataFile->nAttributes) * sizeof(char *));
+ RETURN_IF_BAD_ALLOC(pp);
+ for(i = 0; i < pDataFile->nAttributes-1; i++)
+ pp[i] = pDataFile->pAttNames[i];
+ if(pDataFile->pAttNames)
+ free(pDataFile->pAttNames);
+ pDataFile->pAttNames = pp;
+ pp[pDataFile->nAttributes-1] = NULL;
+ setString(&(pp[pDataFile->nAttributes-1]), name, -1);
+ // set value
+ pp = (char**)malloc((pDataFile->nAttributes) * sizeof(char *));
+ RETURN_IF_BAD_ALLOC(pp);
+ for(i = 0; i < pDataFile->nAttributes-1; i++)
+ pp[i] = pDataFile->pAttValues[i];
+ if(pDataFile->pAttValues)
+ free(pDataFile->pAttValues);
+ pDataFile->pAttValues = pp;
+ pp[pDataFile->nAttributes-1] = NULL;
+ setString(&(pp[pDataFile->nAttributes-1]), value, -1);
+ return ERR_OK;
+}
+
+
+//============================================================
+// Gets an attribute of a data file
+// pDataFile - data file
+// name - buffer for attribute name pointer
+// value - buffer for attribute value pointer
+//============================================================
+EXP_OPTION int getDataFileAttribute(DataFile* pDataFile, int idx, char** name, char** value)
+{
+
+ RETURN_IF_NULL_PARAM(pDataFile);
+ RETURN_IF_NOT(idx < pDataFile->nAttributes, ERR_BAD_ATTR_INDEX);
+ RETURN_IF_NULL_PARAM(name);
+ RETURN_IF_NULL_PARAM(value);
+ *name = pDataFile->pAttNames[idx];
+ *value = pDataFile->pAttValues[idx];
+ return ERR_OK;
+}
+
+//============================================================
+// Calculates the file size and digest
+// pSigDoc - signed document
+// id - data file id
+// filename - filename
+// digType - digestType (code)
+//============================================================
+EXP_OPTION int calculateDataFileSizeAndDigest(SignedDoc* pSigDoc, const char* id,
+ const char* filename, int digType)
+{
+ int err = ERR_OK, len1 = 0;
+ char buf1[DIGEST_LEN+2];
+ long len2 = 0;
+ DataFile* pDataFile;
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ ddocDebug(3, "calculateDataFileSizeAndDigest", "File: %s id: %s", filename, id);
+ pDataFile = getDataFileWithId(pSigDoc, id);
+ RETURN_IF_NOT(pDataFile, ERR_FILE_READ);
+ if(digType == DIGEST_SHA1) {
+ // in version 1.0 we use DigestType and DigestValue
+ // attrributes of DataFile element and calculate the digest
+ // over the original content
+ if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) {
+ len1 = sizeof(buf1);
+ err = calculateFileDigest(filename, digType,
+ (byte*)buf1, &len1, &len2);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ ddocDataFile_SetDigestValue(pDataFile, buf1, len1);
+ pDataFile->nSize = len2;
+ }
+ // in version 1.1 we don't use those attributes
+ // and we calculate the digest over the whole
+ // DataFile element including the tags
+ else {
+ err = calculateFileSize(filename, &pDataFile->nSize);
+ ddocDebug(4, "calculateDataFileSizeAndDigest", "File: %s size: %d", filename, pDataFile->nSize);
+ err = generateDataFileXML(pSigDoc, pDataFile, filename, NULL, NULL);
+ }
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_DIGEST);
+ return err;
+}
+
+
+//=======================< DigestValue >=====================================
+
+//--------------------------------------------------
+// "Constructor" of DigestValue object
+// ppDigestValue - address of buffer for newly allocated object [REQUIRED]
+// szDigestMethod - digest method [OPTIONAL]
+// szDigVal/lDigLen - digest value and length [OPTIONAL]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocDigestValue_new(DigestValue** ppDigestValue,
+ const char* szDigestMethod,
+ void* szDigVal, long lDigLen)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(4, "ddocDigestValue_new", "DigestMethod: %s, dig-len: %ld",
+ (szDigestMethod ? szDigestMethod : "NULL"), lDigLen);
+ RETURN_IF_NULL_PARAM(ppDigestValue);
+ *ppDigestValue = 0; // mark as not yet allocated
+ // allocate memory for new DigestValue
+ *ppDigestValue = (DigestValue*)malloc(sizeof(DigestValue));
+ if(!(*ppDigestValue))
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ memset(*ppDigestValue, 0, sizeof(DigestValue));
+ // set optional fields
+ if(szDigestMethod) {
+ err = ddocMemAssignString((char**)&((*ppDigestValue)->szDigestMethod), szDigestMethod);
+ if(err) return err;
+ } else { // default is sha1
+ err = ddocMemAssignString((char**)&((*ppDigestValue)->szDigestMethod), DIGEST_METHOD_SHA1);
+ }
+ if(szDigVal && lDigLen)
+ err = ddocMemAssignData(&((*ppDigestValue)->mbufDigestValue), szDigVal, lDigLen);
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" of DigestValue object
+// pDigestValue - address of object to be deleted [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocDigestValue_free(DigestValue* pDigestValue)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pDigestValue)
+ // cleanup this object
+ if(pDigestValue->szDigestMethod)
+ free(pDigestValue->szDigestMethod);
+ ddocMemBuf_free(&(pDigestValue->mbufDigestValue));
+ free(pDigestValue);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for DigestMethod atribute of DigestValue object.
+// pDigestValue - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* ddocDigestValue_GetDigestMethod(DigestValue* pDigestValue)
+{
+ RETURN_OBJ_IF_NULL(pDigestValue, NULL)
+ return pDigestValue->szDigestMethod;
+}
+
+//--------------------------------------------------
+// Mutatoror for DigestMethod atribute of DigestValue object.
+// pDigestValue - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocDigestValue_SetDigestMethod(DigestValue* pDigestValue, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pDigestValue)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pDigestValue->szDigestMethod), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for DigestValue atribute of DigestValue object.
+// pDigestValue - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION DigiDocMemBuf* ddocDigestValue_GetDigestValue(DigestValue* pDigestValue)
+{
+ RETURN_OBJ_IF_NULL(pDigestValue, NULL)
+ return &(pDigestValue->mbufDigestValue);
+}
+
+//--------------------------------------------------
+// Mutatoror for DigestValue atribute of DigestValue object.
+// pDigestValue - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// len - length of value in bytes [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocDigestValue_SetDigestValue(DigestValue* pDigestValue,
+ const char* value, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pDigestValue)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignData(&(pDigestValue->mbufDigestValue), value, len);
+ return err;
+}
+
+//--------------------------------------------------
+// Compares two DigestValue structure on equality
+// pDigest1 - address of first digest [REQUIRED]
+// pDigest2 - address of second digest [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCompareDigestValues(DigestValue* pDigest1, DigestValue* pDigest2)
+{
+ RETURN_IF_NULL_PARAM(pDigest1)
+ RETURN_IF_NULL_PARAM(pDigest2)
+ return compareByteArrays((const byte*)pDigest1->mbufDigestValue.pMem,
+ pDigest1->mbufDigestValue.nLen,
+ (const byte*)pDigest2->mbufDigestValue.pMem,
+ pDigest2->mbufDigestValue.nLen);
+}
+
+//--------------------------------------------------
+// Generates XML for <DigestValue> element
+// pSigDoc - signed doc object [REQUIRED]
+// pDigestValue - DigestValue object [REQUIRED]
+// pBuf - memory buffer for storing xml [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocDigestValue_toXML(const DigestValue* pDigestValue, DigiDocMemBuf* pBuf)
+{
+ int err = ERR_OK;
+ DigiDocMemBuf mbuf1;
+
+ RETURN_IF_NULL_PARAM(pBuf)
+ RETURN_IF_NULL_PARAM(pDigestValue)
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ // DigestMethod
+ if(pDigestValue->szDigestMethod) {
+ err = ddocGen_startElemBegin(pBuf, "DigestMethod");
+ if(err) return err;
+ // Algorithm atribute
+ err = ddocGen_addAtribute(pBuf, "Algorithm", pDigestValue->szDigestMethod);
+ if(err) return err;
+ //err = ddocGen_startElemEnd(pBuf);
+ //err = ddocGen_endElem(pBuf, "DigestMethod");
+ // end of element start tag
+ err = ddocMemAppendData(pBuf, "/>\n", -1);
+ }
+ if(pDigestValue->mbufDigestValue.pMem) {
+ err = ddocGen_startElem(pBuf, "DigestValue");
+ }
+
+ if(err) return err;
+ // digest value
+ ddocEncodeBase64(&(pDigestValue->mbufDigestValue), &mbuf1);
+ //AM 17.11.08 to remove newline after base64
+ if(mbuf1.pMem && ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] == '\n')
+ ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] = 0;
+ err = ddocMemAppendData(pBuf, (char*)mbuf1.pMem, -1);
+ ddocMemBuf_free(&mbuf1);
+ if(err) return err;
+ err = ddocGen_endElem(pBuf, "DigestValue");
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ return err;
+}
+
+//======================< SignatureValue >====================================
+
+//--------------------------------------------------
+// "Constructor" of SignatureValue object
+// ppSignatureValue - address of buffer for newly allocated object [REQUIRED]
+// szId - Id atribute value [OPTIONAL]
+// szType - signature type [OPTIONAL]
+// szDigVal/lDigLen - digest value and length [OPTIONAL]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocSignatureValue_new(SignatureValue** ppSignatureValue,
+ const char* szId, const char* szType,
+ void* szSigVal, long lSigLen)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(4, "ddocSignatureValue_new", "id: %s, type: %s, dig-len: %ld",
+ (szId ? szId : "NULL"), (szType ? szType : "NULL"), lSigLen);
+ RETURN_IF_NULL_PARAM(ppSignatureValue);
+ *ppSignatureValue = 0; // mark as not yet allocated
+ // allocate memory for new DigestValue
+ *ppSignatureValue = (SignatureValue*)malloc(sizeof(SignatureValue));
+ if(!(*ppSignatureValue))
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ memset(*ppSignatureValue, 0, sizeof(SignatureValue));
+ // set optional fields
+ if(szId) {
+ err = ddocMemAssignString((char**)&((*ppSignatureValue)->szId), szId);
+ if(err) return err;
+ }
+ if(szType) {
+ err = ddocMemAssignString((char**)&((*ppSignatureValue)->szType), szType);
+ if(err) return err;
+ }
+ if(szSigVal && lSigLen)
+ err = ddocMemAssignData(&((*ppSignatureValue)->mbufSignatureValue), szSigVal, lSigLen);
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" of SignatureValue object
+// pSignatureValue - address of object to be deleted [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocSignatureValue_free(SignatureValue* pSignatureValue)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pSignatureValue)
+ // cleanup this object
+ if(pSignatureValue->szId)
+ free(pSignatureValue->szId);
+ if(pSignatureValue->szType)
+ free(pSignatureValue->szType);
+ ddocMemBuf_free(&(pSignatureValue->mbufSignatureValue));
+ free(pSignatureValue);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for Id atribute of SignatureValue object.
+// pSignatureValue - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* ddocSignatureValue_GetId(const SignatureValue* pSignatureValue)
+{
+ RETURN_OBJ_IF_NULL(pSignatureValue, NULL)
+ return pSignatureValue->szId;
+}
+
+//--------------------------------------------------
+// Mutatoror for Id atribute of SignatureValue object.
+// pSignatureValue - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocSignatureValue_SetId(SignatureValue* pSignatureValue, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pSignatureValue)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pSignatureValue->szId), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for Type atribute of SignatureValue object.
+// pSignatureValue - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* ddocSignatureValue_GetType(const SignatureValue* pSignatureValue)
+{
+ RETURN_OBJ_IF_NULL(pSignatureValue, NULL)
+ return pSignatureValue->szType;
+}
+
+//--------------------------------------------------
+// Mutatoror for Type atribute of SignatureValue object.
+// pSignatureValue - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocSignatureValue_SetType(SignatureValue* pSignatureValue, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pSignatureValue)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pSignatureValue->szType), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for SignatureValue atribute of SignatureValue object.
+// pSignatureValue - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION DigiDocMemBuf* ddocSignatureValue_GetSignatureValue(const SignatureValue* pSignatureValue)
+{
+ RETURN_OBJ_IF_NULL(pSignatureValue, NULL)
+ return &(((SignatureValue*)pSignatureValue)->mbufSignatureValue);
+}
+
+//--------------------------------------------------
+// Mutatoror for SignatureValue atribute of SignatureValue object.
+// pSignatureValue - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// len - length of value in bytes [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocSignatureValue_SetSignatureValue(SignatureValue* pSignatureValue,
+ const char* value, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pSignatureValue)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignData(&(pSignatureValue->mbufSignatureValue), value, len);
+ return err;
+}
+
+//--------------------------------------------------
+// Generates XML for <SignatureValue> element
+// pSignatureValue - SignatureValue object [REQUIRED]
+// pBuf - memory buffer for storing xml [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocSignatureValue_toXML(const SignatureValue* pSignatureValue, DigiDocMemBuf* pBuf)
+{
+ int err = ERR_OK;
+ char* p;
+ DigiDocMemBuf mbuf1;
+
+ RETURN_IF_NULL_PARAM(pBuf)
+ //RETURN_IF_NULL_PARAM(pSignatureValue)
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ // start of element
+ err = ddocGen_startElemBegin(pBuf, "SignatureValue");
+ if(err) return err;
+ // Id atribute
+ if(pSignatureValue) {
+ p = (char*)ddocSignatureValue_GetId(pSignatureValue);
+ if(p)
+ err = ddocGen_addAtribute(pBuf, "Id", p);
+ if(err) return err;
+ }
+ // end of element start tag
+ err = ddocGen_startElemEnd(pBuf);
+ //err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // signature value
+ if(pSignatureValue) {
+ ddocEncodeBase64(ddocSignatureValue_GetSignatureValue(pSignatureValue), &mbuf1);
+ //AM 17.11.08 to remove newline after base64
+ if(mbuf1.pMem && ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] == '\n')
+ ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] = 0;
+ err = ddocMemAppendData(pBuf, (char*)mbuf1.pMem, -1);
+ ddocMemBuf_free(&mbuf1);
+ }
+ err = ddocGen_endElem(pBuf, "SignatureValue");
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ return err;
+}
+
+//======================< CertID >====================================
+
+//--------------------------------------------------
+// "Constructor" of CertID object
+// ppCertID - address of buffer for newly allocated object [REQUIRED]
+// szId - Id atribute value [OPTIONAL]
+// nType - certid internal type (signers or responders cert) [REQUIRED]
+// szIssuerSerial - issuer serial number [OPTIONAL]
+// szIssuerName - issuer DN [OPTIONAL]
+// szDigVal/lDigLen - digest value and length [OPTIONAL]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertID_new(CertID** ppCertID,
+ int nType, const char* szId,
+ const char* szIssuerSerial, const char* szIssuerName,
+ void* szDigVal, long lDigLen)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(4, "ddocCertID_new", "id: %s, type: %d, issuer-serial: %s issuer-name: %s, dig-len: %ld",
+ (szId ? szId : "NULL"), nType,
+ (szIssuerSerial ? szIssuerSerial : "NULL"),
+ (szIssuerName ? szIssuerName : "NULL"), lDigLen);
+ RETURN_IF_NULL_PARAM(ppCertID);
+ *ppCertID = 0; // mark as not yet allocated
+ // allocate memory for new CertID
+ *ppCertID = (CertID*)malloc(sizeof(CertID));
+ if(!(*ppCertID))
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ memset(*ppCertID, 0, sizeof(CertID));
+ (*ppCertID)->nType = nType;
+ // set optional fields
+ if(szId) {
+ err = ddocMemAssignString((char**)&((*ppCertID)->szId), szId);
+ if(err) return err;
+ }
+ if(szIssuerSerial) {
+ err = ddocMemAssignString((char**)&((*ppCertID)->szIssuerSerial), szIssuerSerial);
+ if(err) return err;
+ }
+ if(szIssuerName) {
+ err = ddocMemAssignString((char**)&((*ppCertID)->szIssuerName), szIssuerName);
+ if(err) return err;
+ }
+ if(szDigVal && lDigLen) {
+ if(!(*ppCertID)->pDigestValue)
+ ddocDigestValue_new(&((*ppCertID)->pDigestValue), 0, szDigVal, lDigLen);
+ else
+ err = ddocDigestValue_SetDigestValue((*ppCertID)->pDigestValue, szDigVal, lDigLen);
+ }
+ return err;
+}
+EXP_OPTION int bdocCertID_new(CertID** ppCertID,
+ int nType, const char* szId,
+ const char* szIssuerSerial, const char* szIssuerName,
+ void* szDigVal, long lDigLen)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(4, "ddocCertID_new", "id: %s, type: %d, issuer-serial: %s issuer-name: %s, dig-len: %ld",
+ (szId ? szId : "NULL"), nType,
+ (szIssuerSerial ? szIssuerSerial : "NULL"),
+ (szIssuerName ? szIssuerName : "NULL"), lDigLen);
+ RETURN_IF_NULL_PARAM(ppCertID);
+ *ppCertID = 0; // mark as not yet allocated
+ // allocate memory for new CertID
+ *ppCertID = (CertID*)malloc(sizeof(CertID));
+ if(!(*ppCertID))
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ memset(*ppCertID, 0, sizeof(CertID));
+ (*ppCertID)->nType = nType;
+ // set optional fields
+ if(szId) {
+ err = ddocMemAssignString((char**)&((*ppCertID)->szId), szId);
+ if(err) return err;
+ }
+ if(szIssuerSerial) {
+ err = ddocMemAssignString((char**)&((*ppCertID)->szIssuerSerial), szIssuerSerial);
+ if(err) return err;
+ }
+ if(szIssuerName) {
+ err = ddocMemAssignString((char**)&((*ppCertID)->szIssuerName), szIssuerName);
+ if(err) return err;
+ }
+ if(szDigVal && lDigLen) {
+ if(!(*ppCertID)->pDigestValue){
+ ddocDigestValue_new(&((*ppCertID)->pDigestValue), 0, szDigVal, lDigLen);
+ }else
+ err = ddocDigestValue_SetDigestValue((*ppCertID)->pDigestValue, szDigVal, lDigLen);
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" of CertID object
+// pCertID - address of object to be deleted [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertID_free(CertID* pCertID)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertID)
+ // cleanup this object
+ if(pCertID->szId)
+ free(pCertID->szId);
+ if(pCertID->szIssuerSerial)
+ free(pCertID->szIssuerSerial);
+ if(pCertID->szIssuerName)
+ free(pCertID->szIssuerName);
+ if(pCertID->pDigestValue)
+ ddocDigestValue_free(pCertID->pDigestValue);
+ if(pCertID->szDigestType)
+ free(pCertID->szDigestType);
+ free(pCertID);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for IssuerSerial atribute of CertID object.
+// pCertID - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* ddocCertID_GetIssuerSerial(const CertID* pCertID)
+{
+ RETURN_OBJ_IF_NULL(pCertID, NULL)
+ return pCertID->szIssuerSerial;
+}
+
+//--------------------------------------------------
+// Mutatoror for IssuerSerial atribute of CertID object.
+// pCertID - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertID_SetIssuerSerial(CertID* pCertID, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertID)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pCertID->szIssuerSerial), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for Id atribute of CertID object.
+// pCertID - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* ddocCertID_GetId(const CertID* pCertID)
+{
+ RETURN_OBJ_IF_NULL(pCertID, NULL)
+ return pCertID->szId;
+}
+
+//--------------------------------------------------
+// Mutatoror for Id atribute of CertID object.
+// pCertID - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertID_SetId(CertID* pCertID, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertID)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pCertID->szId), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for IssuerName atribute of CertID object.
+// pCertID - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* ddocCertID_GetIssuerName(const CertID* pCertID)
+{
+ RETURN_OBJ_IF_NULL(pCertID, NULL)
+ return pCertID->szIssuerName;
+}
+
+//--------------------------------------------------
+// Mutatoror for IssuerName atribute of CertID object.
+// pCertID - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertID_SetIssuerName(CertID* pCertID, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertID)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pCertID->szIssuerName), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for DigestValue atribute of CertID object.
+// pCertID - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION DigiDocMemBuf* ddocCertID_GetDigestValue(const CertID* pCertID)
+{
+ RETURN_OBJ_IF_NULL(pCertID, NULL)
+ return ddocDigestValue_GetDigestValue(pCertID->pDigestValue);
+}
+
+//--------------------------------------------------
+// Mutatoror for DigestValue atribute of CertID object.
+// pCertID - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// len - length of value in bytes [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertID_SetDigestValue(CertID* pCertID,
+ const char* value, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertID)
+ RETURN_IF_NULL_PARAM(value)
+ if(!pCertID->pDigestValue)
+ err = ddocDigestValue_new(&(pCertID->pDigestValue), 0, (char*)value, len);
+ else
+ err = ddocDigestValue_SetDigestValue(pCertID->pDigestValue, value, len);
+ return err;
+}
+
+//--------------------------------------------------
+// Generates XML for <Cert> element
+// pSigDoc - SignedDoc object [REQUIRED]
+// pCertID - CertID object [REQUIRED]
+// pBuf - memory buffer for storing xml [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertID_toXML(const SignedDoc* pSigDoc, const CertID* pCertID, DigiDocMemBuf* pBuf)
+{
+ int err = ERR_OK;
+
+ RETURN_IF_NULL_PARAM(pBuf)
+ RETURN_IF_NULL_PARAM(pCertID)
+ RETURN_IF_NULL_PARAM(pSigDoc)
+ // start of element
+ err = ddocGen_startElemBegin(pBuf, "Cert");
+ if(err) return err;
+ // only formats 1.0, 1.1 and 1.2 we use the Id atribute
+ //AM 28.10.08 can also have 1.0 version
+ if((!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) ||
+ !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) ||
+ !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) {
+ // Id atribute
+ if(pCertID->szId)
+ err = ddocGen_addAtribute(pBuf, "Id", pCertID->szId);
+ if(err) return err;
+ }
+ // end of element start tag
+ err = ddocGen_startElemEnd(pBuf);
+ // <CertDigest>
+ err = ddocGen_startElem(pBuf, "CertDigest");
+ if(err) return err;
+ ddocDigestValue_toXML(pCertID->pDigestValue, pBuf);
+ err = ddocGen_endElem(pBuf, "CertDigest");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ // <IssuerSerial
+ err = ddocGen_startElem(pBuf, "IssuerSerial");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ // only formats 1.0, 1.1 and 1.2 we use the IssuerSerial element alone
+ //AM 29.10.08
+ if((!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME))||
+ !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) ||
+ !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) {
+ err = ddocMemAppendData(pBuf, ddocCertID_GetIssuerSerial(pCertID), -1);
+ } else { // in 1.3 and 1.4 we use all subelement of <IssuerSerial>
+ err = ddocGen_startElemBegin(pBuf, "X509IssuerName");
+ if(err) return err;
+ err = ddocGen_addAtribute(pBuf, "xmlns", NAMESPACE_XML_DSIG);
+ // end of element start tag
+ err = ddocGen_startElemEnd(pBuf);
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, ddocCertID_GetIssuerName(pCertID), -1);
+ if(err) return err;
+ err = ddocGen_endElem(pBuf, "X509IssuerName");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ err = ddocGen_startElemBegin(pBuf, "X509SerialNumber");
+ if(err) return err;
+ err = ddocGen_addAtribute(pBuf, "xmlns", NAMESPACE_XML_DSIG);
+ // end of element start tag
+ err = ddocGen_startElemEnd(pBuf);
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, ddocCertID_GetIssuerSerial(pCertID), -1);
+ if(err) return err;
+ err = ddocGen_endElem(pBuf, "X509SerialNumber");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ }
+ err = ddocGen_endElem(pBuf, "IssuerSerial");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ err = ddocGen_endElem(pBuf, "Cert");
+ return err;
+}
+
+
+//--------------------------------------------------
+// Generates XML for <CompleteCertificateRefs> element
+// pSigDoc - SignedDoc object [REQUIRED]
+// pBuf - memory buffer for storing xml [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCompleteCertificateRefs_toXML(const SignedDoc* pSigDoc,
+ const SignatureInfo* pSigInfo, DigiDocMemBuf* pBuf)
+{
+ int err = ERR_OK, i, n;
+ CertID* pCertID;
+
+ RETURN_IF_NULL_PARAM(pBuf)
+ RETURN_IF_NULL_PARAM(pSigDoc)
+ RETURN_IF_NULL_PARAM(pSigInfo)
+ RETURN_IF_NULL(pSigInfo->pCertIDs)
+ // <CompleteCertificateRefs>
+ err = ddocGen_startElemBegin(pBuf, "CompleteCertificateRefs");
+ if(err) return err;
+ // end of element start tag
+ err = ddocGen_startElemEnd(pBuf);
+ if(err) return err;
+ // <CertRefs> (not used in 1.0, 1.1 and 1.2
+ if((strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) &&
+ strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) &&
+ strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) {
+ err = ddocGen_startElem(pBuf, "CertRefs");
+ if(err) return err;
+ }
+ n = ddocCertIDList_GetCertIDsCount(pSigInfo->pCertIDs);
+ for(i = 0; i < n; i++) {
+ pCertID = ddocCertIDList_GetCertID(pSigInfo->pCertIDs, i);
+ if(pCertID && pCertID->nType != CERTID_TYPE_SIGNERS_CERTID)
+ ddocCertID_toXML(pSigDoc, pCertID, pBuf);
+ }
+ // </CertRefs> (not used in 1.0, 1.1 and 1.2
+ //AM 29.10.08
+ if((strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) &&
+ strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) &&
+ strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) {
+ err = ddocGen_endElem(pBuf, "CertRefs");
+ }
+ if(err) return err;
+ err = ddocGen_endElem(pBuf, "CompleteCertificateRefs");
+ return err;
+}
+
+//--------------------------------------------------
+// Generates XML for <CompleteRevocationRefs> element
+// pSigDoc - SignedDoc object [REQUIRED]
+// pBuf - memory buffer for storing xml [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCompleteRevocationRefs_toXML(const SignedDoc* pSigDoc,
+ const SignatureInfo* pSigInfo, DigiDocMemBuf* pBuf)
+{
+ int err = ERR_OK, l1, l2;
+ //AM 28.04.04 increased buffer for sha256
+ char buf1[80], buf2[80], *p1, *p2;
+ const DigiDocMemBuf *pMBuf = 0;
+
+ RETURN_IF_NULL_PARAM(pBuf)
+ RETURN_IF_NULL_PARAM(pSigDoc)
+ RETURN_IF_NULL_PARAM(pSigInfo)
+ RETURN_IF_NULL(pSigInfo->pNotary)
+ // <CompleteRevocationRefs>
+ err = ddocGen_startElemBegin(pBuf, "CompleteRevocationRefs");
+ if(err) return err;
+ // end of element start tag
+ err = ddocGen_startElemEnd(pBuf);
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // <OCSPRefs>
+ err = ddocGen_startElem(pBuf, "OCSPRefs");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // <OCSPRef>
+ err = ddocGen_startElem(pBuf, "OCSPRef");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // <OCSPIdentifier>
+ err = ddocGen_startElemBegin(pBuf, "OCSPIdentifier");
+ if(err) return err;
+ snprintf(buf1, sizeof(buf1), "#%s", pSigInfo->pNotary->szId);
+ err = ddocGen_addAtribute(pBuf, "URI", buf1);
+ err = ddocGen_startElemEnd(pBuf);
+ if(err) return err;
+ // <ResponderID>
+ err = ddocGen_startElem(pBuf, "ResponderID");
+ if(err) return err;
+ if(pSigInfo->pNotary->nRespIdType == RESPID_NAME_TYPE) {
+ p1 = (char*)ddocNotInfo_GetResponderId_Value(pSigInfo->pNotary);
+ RETURN_IF_NULL(p1);
+ err = ddocMemAppendData(pBuf, p1, -1);
+ if(err) return err;
+ } else if(pSigInfo->pNotary->nRespIdType == RESPID_KEY_TYPE) {
+ pMBuf = ddocNotInfo_GetResponderId(pSigInfo->pNotary);
+ RETURN_IF_NULL(pMBuf);
+ l2 = pMBuf->nLen * 2 + 10;
+ p2 = (char*)malloc(l2);
+ RETURN_IF_NULL(p2);
+ memset(p2, 0, l2);
+ encode((const byte*)pMBuf->pMem, pMBuf->nLen, (byte*)p2, &l2);
+ err = ddocMemAppendData(pBuf, p2, -1);
+ if(err) return err;
+ } else {
+ SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_WRONG_RESPID);
+ }
+ err = ddocGen_endElem(pBuf, "ResponderID");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // <ProducedAt>
+ err = ddocGen_startElem(pBuf, "ProducedAt");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, pSigInfo->pNotary->timeProduced, -1);
+ if(err) return err;
+ err = ddocGen_endElem(pBuf, "ProducedAt");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // </OCSPRef>
+ err = ddocGen_endElem(pBuf, "OCSPIdentifier");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // <DigestAlgAndValue>
+ err = ddocGen_startElem(pBuf, "DigestAlgAndValue");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // <DigestMethod>
+ err = ddocGen_startElemBegin(pBuf, "DigestMethod");
+ if(err) return err;
+ err = ddocGen_addAtribute(pBuf, "Algorithm", DIGEST_METHOD_SHA1);
+ err = ddocGen_startElemEnd(pBuf);
+ if(err) return err;
+ err = ddocGen_endElem(pBuf, "DigestMethod");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // <DigestValue>
+ err = ddocGen_startElem(pBuf, "DigestValue");
+ if(err) return err;
+ l2 = sizeof(buf2);
+ err = calculateNotaryInfoDigest(pSigDoc, pSigInfo->pNotary, (byte*)buf2, &l2);
+ l1 = sizeof(buf1);
+ encode((const byte*)buf2, l2, (byte*)buf1, &l1);
+ err = ddocMemAppendData(pBuf, buf1, -1);
+ err = ddocGen_endElem(pBuf, "DigestValue");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // </DigestAlgAndValue>
+ err = ddocGen_endElem(pBuf, "DigestAlgAndValue");
+ if(err) return err;
+ // </OCSPRef>
+ err = ddocGen_endElem(pBuf, "OCSPRef");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // </OCSPRefs>
+ err = ddocGen_endElem(pBuf, "OCSPRefs");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ if(err) return err;
+ // </CompleteRevocationRefs>
+ err = ddocGen_endElem(pBuf, "CompleteRevocationRefs");
+ if(err) return err;
+ err = ddocMemAppendData(pBuf, "\n", -1);
+ return err;
+}
+
+
+//==========< CertIDList >====================
+
+//--------------------------------------------------
+// "Constructor" of CertIDList object
+// ppCertIDList - address of buffer for newly allocated object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertIDList_new(CertIDList** ppCertIDList)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(3, "ddocCertIDList_new", "Create new certid list");
+ RETURN_IF_NULL_PARAM(ppCertIDList);
+ *ppCertIDList = (CertIDList*)malloc(sizeof(CertIDList));
+ // allocate new object
+ RETURN_IF_BAD_ALLOC(*ppCertIDList);
+ memset(*ppCertIDList, 0, sizeof(CertIDList));
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" of CertIDList object
+// pCertIDList - address of object to be deleted [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertIDList_free(CertIDList* pCertIDList)
+{
+ int i, err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertIDList)
+ // free timestamp-infos
+ for(i = 0; i < pCertIDList->nCertIDs; i++) {
+ if(pCertIDList->pCertIDs[i]) {
+ err = ddocCertID_free(pCertIDList->pCertIDs[i]);
+ if(err) return err;
+ }
+ }
+ free(pCertIDList->pCertIDs);
+ free(pCertIDList);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for count of CertIDs subelement of CertIDList object.
+// pCertIDList - pointer to CertIDList object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertIDList_addCertID(CertIDList* pCertIDList, CertID* pCertID)
+{
+ CertID** pCertIDs = 0;
+
+ RETURN_IF_NULL_PARAM(pCertIDList)
+ RETURN_IF_NULL_PARAM(pCertID)
+ pCertIDs = (CertID**)realloc(pCertIDList->pCertIDs, sizeof(CertID*) * (pCertIDList->nCertIDs + 1));
+ RETURN_IF_BAD_ALLOC(pCertIDs);
+ pCertIDList->pCertIDs = pCertIDs;
+ pCertIDList->pCertIDs[pCertIDList->nCertIDs] = pCertID;
+ pCertIDList->nCertIDs++;
+ ddocDebug(3, "ddocCertIDList_addCertID", "added certid: %s type: %d", pCertID->szId, pCertID->nType);
+ return ERR_OK;
+}
+
+
+//--------------------------------------------------
+// Accessor for count of CertIDs subelement of CertIDList object.
+// pCertIDList - pointer to CertIDList object [REQUIRED]
+// returns count or -1 for error. Then use error API to check errors
+//--------------------------------------------------
+EXP_OPTION int ddocCertIDList_GetCertIDsCount(CertIDList* pCertIDList)
+{
+ SET_LAST_ERROR_RETURN_IF_NOT(pCertIDList, ERR_NULL_POINTER, -1)
+ return pCertIDList->nCertIDs;
+}
+
+//--------------------------------------------------
+// Accessor for CertIDs subelement of CertIDList object.
+// pCertIDList - pointer to CertIDList object [REQUIRED]
+// nIdx - index of CertID object [REQUIRED]
+// returns CertID pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertID* ddocCertIDList_GetCertID(CertIDList* pCertIDList, int nIdx)
+{
+ RETURN_OBJ_IF_NULL(pCertIDList, NULL)
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pCertIDList->nCertIDs, ERR_BAD_CERTID_IDX, NULL);
+ RETURN_OBJ_IF_NULL(pCertIDList->pCertIDs[nIdx], 0);
+ return pCertIDList->pCertIDs[nIdx];
+}
+
+
+//--------------------------------------------------
+// Accessor for last CertIDs subelement of CertIDList object.
+// pCertIDList - pointer to CertIDList object [REQUIRED]
+// returns CertID pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertID* ddocCertIDList_GetLastCertID(CertIDList* pCertIDList)
+{
+ RETURN_OBJ_IF_NULL(pCertIDList, NULL)
+ SET_LAST_ERROR_RETURN_IF_NOT(pCertIDList->nCertIDs > 0, ERR_BAD_CERTID_IDX, NULL);
+ RETURN_OBJ_IF_NULL(pCertIDList->pCertIDs[pCertIDList->nCertIDs-1], 0);
+ return pCertIDList->pCertIDs[pCertIDList->nCertIDs-1];
+}
+
+
+//--------------------------------------------------
+// Deletes CertID subelement of CertIDList object.
+// pCertIDList - pointer to CertIDList object [REQUIRED]
+// nIdx - index of CertID object to be removed [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertIDList_DeleteCertID(CertIDList* pCertIDList, int nIdx)
+{
+ int err = ERR_OK, i;
+
+ RETURN_IF_NULL_PARAM(pCertIDList)
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pCertIDList->nCertIDs, ERR_BAD_CERTID_IDX, ERR_BAD_CERTID_IDX);
+ RETURN_IF_NULL_PARAM(pCertIDList->pCertIDs[nIdx]);
+ // delete the given object
+ err = ddocCertID_free(pCertIDList->pCertIDs[nIdx]);
+ if(err) return err;
+ pCertIDList->pCertIDs[nIdx] = 0;
+ // move other objects 1 step close to array start
+ for(i = nIdx; i < pCertIDList->nCertIDs; i++)
+ pCertIDList->pCertIDs[i] = pCertIDList->pCertIDs[i+1];
+ pCertIDList->pCertIDs[pCertIDList->nCertIDs - 1] = 0;
+ pCertIDList->nCertIDs--;
+ return err;
+}
+
+//--------------------------------------------------
+// Finds a CertID object with required type
+// pCertIDList - pointer to CertIDList object [REQUIRED]
+// nType - type of CertID object [REQUIRED]
+// returns CertID pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertID* ddocCertIDList_GetCertIDOfType(CertIDList* pCertIDList, int nType)
+{
+ int i;
+
+ RETURN_OBJ_IF_NULL(pCertIDList, NULL)
+ ddocDebug(4, "ddocCertIDList_GetCertIDOfType", "find type: %d", nType);
+ for(i = 0; i < pCertIDList->nCertIDs; i++) {
+ ddocDebug(4, "ddocCertIDList_GetCertIDOfType", "idx: %d type: %d", i, pCertIDList->pCertIDs[i]->nType);
+ if(pCertIDList->pCertIDs[i]->nType == nType)
+ return pCertIDList->pCertIDs[i];
+ }
+ return NULL;
+}
+
+//--------------------------------------------------
+// Finds a CertID object with serial nr
+// pCertIDList - pointer to CertIDList object [REQUIRED]
+// nType - type of CertID object [REQUIRED]
+// returns CertID pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertID* ddocCertIDList_GetCertIDOfSerial(CertIDList* pCertIDList, const char* szSerial)
+{
+ int i;
+
+ RETURN_OBJ_IF_NULL(pCertIDList, NULL)
+ RETURN_OBJ_IF_NULL(szSerial, NULL)
+ ddocDebug(4, "ddocCertIDList_GetCertIDOfSerial", "find serial: %s", szSerial);
+ for(i = 0; i < pCertIDList->nCertIDs; i++) {
+ //AM 19.09.08
+ if(pCertIDList->pCertIDs[i]->szIssuerSerial){
+ if(!strcmp(pCertIDList->pCertIDs[i]->szIssuerSerial, szSerial))
+ return pCertIDList->pCertIDs[i];
+ }
+ }
+ return NULL;
+}
+
+//--------------------------------------------------
+// Finds a CertID object with required type or creates a new one
+// pCertIDList - pointer to CertIDList object [REQUIRED]
+// nType - type of CertID object [REQUIRED]
+// returns CertID pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertID* ddocCertIDList_GetOrCreateCertIDOfType(CertIDList* pCertIDList, int nType)
+{
+ CertID* pCertID = ddocCertIDList_GetCertIDOfType(pCertIDList, nType);
+ if(!pCertID) {
+ ddocCertID_new(&pCertID, nType, 0, 0, 0, 0, 0);
+ if(pCertID)
+ ddocCertIDList_addCertID(pCertIDList, pCertID);
+ }
+ return pCertID;
+}
+
+//======================< CertValue >====================================
+
+//--------------------------------------------------
+// "Constructor" of CertValue object
+// ppCertValue - address of buffer for newly allocated object [REQUIRED]
+// szId - Id atribute value [OPTIONAL]
+// nType - certid internal type (signers or responders cert) [REQUIRED]
+// pCert - certificate itself [OPTIONAL]. Must fill in later. Do not X509_free() param!
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertValue_new(CertValue** ppCertValue,
+ int nType, const char* szId,
+ X509* pCert)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(4, "ddocCertValue_new", "id: %s, type: %d, cert: %s",
+ (szId ? szId : "NULL"), nType, (pCert ? "OK" : "NULL"));
+ RETURN_IF_NULL_PARAM(ppCertValue);
+ //RETURN_IF_NULL_PARAM(pCert);
+ *ppCertValue = 0; // mark as not yet allocated
+ // allocate memory for new CertValue
+ *ppCertValue = (CertValue*)malloc(sizeof(CertValue));
+ if(!(*ppCertValue))
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ memset(*ppCertValue, 0, sizeof(CertValue));
+ (*ppCertValue)->nType = nType;
+ if(pCert)
+ (*ppCertValue)->pCert = pCert;
+ // set optional fields
+ if(szId) {
+ err = ddocMemAssignString((char**)&((*ppCertValue)->szId), szId);
+ if(err) return err;
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" of CertValue object
+// pCertValue - address of object to be deleted [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertValue_free(CertValue* pCertValue)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertValue)
+ // cleanup this object
+ if(pCertValue->szId)
+ free(pCertValue->szId);
+ if(pCertValue->pCert)
+ X509_free(pCertValue->pCert);
+ free(pCertValue);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for Id atribute of CertValue object.
+// pCertValue - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* ddocCertValue_GetId(CertValue* pCertValue)
+{
+ RETURN_OBJ_IF_NULL(pCertValue, NULL)
+ return pCertValue->szId;
+}
+
+//--------------------------------------------------
+// Mutatoror for Id atribute of CertValue object.
+// pCertValue - address of object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertValue_SetId(CertValue* pCertValue, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertValue)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pCertValue->szId), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Accessor for Cert atribute of CertValue object.
+// pCertValue - address of object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION X509* ddocCertValue_GetCert(CertValue* pCertValue)
+{
+ RETURN_OBJ_IF_NULL(pCertValue, NULL)
+ return pCertValue->pCert;
+}
+
+//--------------------------------------------------
+// Mutatoror for Cert atribute of CertValue object.
+// pCertValue - address of object [REQUIRED]
+// pCert - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertValue_SetCert(CertValue* pCertValue, X509* pCert)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertValue)
+ RETURN_IF_NULL_PARAM(pCert)
+ if(pCertValue->pCert && pCertValue->pCert != pCert) // free old cert
+ X509_free(pCertValue->pCert);
+ else
+ ddocDebug(3, "ddocCertValue_SetCert", "Not freeing old cert");
+ pCertValue->pCert = pCert;
+ ddocDebug(3, "ddocCertValue_SetCert", "id: %s type: %d cert: %s", pCertValue->szId, pCertValue->nType, (pCert ? "OK" : "NULL"));
+ return err;
+}
+
+//--------------------------------------------------
+// Generates XML for <EncapsulatedX509Certificate> element
+// pCertID - CertID object [REQUIRED]
+// pBuf - memory buffer for storing xml [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertValue_toXML(const CertValue* pCertValue, DigiDocMemBuf* pBuf)
+{
+ int err = ERR_OK;
+ char *p1 = 0;
+
+ RETURN_IF_NULL_PARAM(pBuf)
+ RETURN_IF_NULL_PARAM(pCertValue)
+ // start of element
+ err = ddocGen_startElemBegin(pBuf, "EncapsulatedX509Certificate");
+ if(err) return err;
+ if(pCertValue->szId)
+ err = ddocGen_addAtribute(pBuf, "Id", pCertValue->szId);
+ if(err) return err;
+ err = ddocGen_startElemEnd(pBuf);
+ if(err) return err;
+ //err = ddocMemAppendData(pBuf, "\n", -1);
+ if(pCertValue->pCert) {
+ err = getCertPEM(pCertValue->pCert, 0, &p1);
+ if(p1) {
+ err = ddocMemAppendData(pBuf, p1, -1);
+ free(p1);
+ }
+ }
+ if(err) return err;
+ err = ddocGen_endElem(pBuf, "EncapsulatedX509Certificate");
+ return err;
+}
+
+//==========< CertValueList >====================
+
+//--------------------------------------------------
+// "Constructor" of CertValueList object
+// ppCertValueList - address of buffer for newly allocated object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertValueList_new(CertValueList** ppCertValueList)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(3, "ddocCertValueList_new", "Create new cerValue list");
+ RETURN_IF_NULL_PARAM(ppCertValueList);
+ *ppCertValueList = (CertValueList*)malloc(sizeof(CertValueList));
+ // allocate new object
+ RETURN_IF_BAD_ALLOC(*ppCertValueList);
+ memset(*ppCertValueList, 0, sizeof(CertValueList));
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" of CertValueList object
+// pCertValueList - address of object to be deleted [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertValueList_free(CertValueList* pCertValueList)
+{
+ int i, err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pCertValueList)
+ // free timestamp-infos
+ for(i = 0; i < pCertValueList->nCertValues; i++) {
+ if(pCertValueList->pCertValues[i]) {
+ err = ddocCertValue_free(pCertValueList->pCertValues[i]);
+ if(err) return err;
+ }
+ }
+ free(pCertValueList->pCertValues);
+ free(pCertValueList);
+ return err;
+}
+
+//--------------------------------------------------
+// Adds a CertValue element to CertValueList object.
+// pCertValueList - pointer to CertValueList object [REQUIRED]
+// pCertValue - new object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertValueList_addCertValue(CertValueList* pCertValueList, CertValue* pCertValue)
+{
+ CertValue** pCertValues = 0;
+
+ RETURN_IF_NULL_PARAM(pCertValueList)
+ RETURN_IF_NULL_PARAM(pCertValue)
+ pCertValues = (CertValue**)realloc(pCertValueList->pCertValues, sizeof(CertValue*) * (pCertValueList->nCertValues + 1));
+ RETURN_IF_BAD_ALLOC(pCertValues);
+ pCertValueList->pCertValues = pCertValues;
+ pCertValueList->pCertValues[pCertValueList->nCertValues] = pCertValue;
+ pCertValueList->nCertValues++;
+ ddocDebug(4, "ddocCertValueList_addCertValue", "added cert: %s type: %d", pCertValue->szId, pCertValue->nType);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Accessor for count of CertValues subelement of CertValueList object.
+// pCertValueList - pointer to CertValueList object [REQUIRED]
+// returns count or -1 for error. Then use error API to check errors
+//--------------------------------------------------
+EXP_OPTION int ddocCertValueList_GetCertValuesCount(CertValueList* pCertValueList)
+{
+ SET_LAST_ERROR_RETURN_IF_NOT(pCertValueList, ERR_NULL_POINTER, -1)
+ return pCertValueList->nCertValues;
+}
+
+//--------------------------------------------------
+// Accessor for CertValues subelement of CertValueList object.
+// pCertValueList - pointer to CertValueList object [REQUIRED]
+// nIdx - index of CertValue object [REQUIRED]
+// returns CertValue pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertValue* ddocCertValueList_GetCertValue(CertValueList* pCertValueList, int nIdx)
+{
+ RETURN_OBJ_IF_NULL(pCertValueList, NULL)
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pCertValueList->nCertValues, ERR_BAD_CERTVALUE_IDX, NULL);
+ RETURN_OBJ_IF_NULL(pCertValueList->pCertValues[nIdx], 0);
+ return pCertValueList->pCertValues[nIdx];
+}
+
+//--------------------------------------------------
+// Deletes CertValue subelement of CertValueList object.
+// pCertValueList - pointer to CertValueList object [REQUIRED]
+// nIdx - index of CertValue object to be removed [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertValueList_DeleteCertValue(CertValueList* pCertValueList, int nIdx)
+{
+ int err = ERR_OK, i;
+
+ RETURN_IF_NULL_PARAM(pCertValueList)
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pCertValueList->nCertValues, ERR_BAD_CERTVALUE_IDX, ERR_BAD_CERTVALUE_IDX);
+ RETURN_IF_NULL_PARAM(pCertValueList->pCertValues[nIdx]);
+ // delete the given object
+ err = ddocCertValue_free(pCertValueList->pCertValues[nIdx]);
+ if(err) return err;
+ pCertValueList->pCertValues[nIdx] = 0;
+ // move other objects 1 step close to array start
+ for(i = nIdx; i < pCertValueList->nCertValues; i++)
+ pCertValueList->pCertValues[i] = pCertValueList->pCertValues[i+1];
+ pCertValueList->pCertValues[pCertValueList->nCertValues - 1] = 0;
+ pCertValueList->nCertValues--;
+ return err;
+}
+
+//--------------------------------------------------
+// Finds a CertValue object with required type
+// pCertValueList - pointer to CertValueList object [REQUIRED]
+// nType - type of CertValue object [REQUIRED]
+// returns CertValue pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertValue* ddocCertValueList_GetCertValueOfType(CertValueList* pCertValueList, int nType)
+{
+ int i;
+
+ RETURN_OBJ_IF_NULL(pCertValueList, NULL)
+ ddocDebug(4, "ddocCertValueList_GetCertValueOfType", "find type: %d", nType);
+ for(i = 0; i < pCertValueList->nCertValues; i++) {
+ ddocDebug(4, "ddocCertValueList_GetCertValueOfType", "idx: %d", i);
+ ddocDebug(4, "ddocCertValueList_GetCertValueOfType", "idx: %d type: %d", i, pCertValueList->pCertValues[i]->nType);
+ if(pCertValueList->pCertValues[i]->nType == nType){
+ ddocDebug(4, "ddocCertValueList_GetCertValueOfType", "found");
+ return pCertValueList->pCertValues[i];}
+ }
+ return NULL;
+}
+
+//--------------------------------------------------
+// Finds a CertValue object with required type or creates a new one
+// pCertValueList - pointer to CertValueList object [REQUIRED]
+// nType - type of CertValue object [REQUIRED]
+// returns CertValue pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertValue* ddocCertValueList_GetOrCreateCertValueOfType(CertValueList* pCertValueList, int nType)
+{
+
+ CertValue* pCertValue = ddocCertValueList_GetCertValueOfType(pCertValueList, nType);
+ if(!pCertValue) {
+ ddocCertValue_new(&pCertValue, nType, 0, 0);
+ if(pCertValue)
+ ddocCertValueList_addCertValue(pCertValueList, pCertValue);
+ }
+ return pCertValue;
+}
+
+
+//======================< SignatureInfo >====================================
+
+//============================================================
+// Returns the number of signatures
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION int getCountOfSignatures(const SignedDoc* pSigDoc)
+{
+ RETURN_OBJ_IF_NULL(pSigDoc, -1);
+ return pSigDoc->nSignatures;
+}
+
+//============================================================
+// Returns the next free signature id
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION int getNextSignatureId(const SignedDoc* pSigDoc)
+{
+ int id = 0, n, i;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, -1);
+ for(i = 0; i < pSigDoc->nSignatures; i++) {
+ SignatureInfo* pSignature = pSigDoc->pSignatures[i];
+ RETURN_OBJ_IF_NULL(pSignature, -1);
+ RETURN_OBJ_IF_NULL(pSignature->szId, -1);
+ SET_LAST_ERROR_RETURN_IF_NOT(strlen(pSignature->szId) > 1, ERR_EMPTY_STRING, -1);
+ n = atoi(pSignature->szId+1);
+ if(id <= n)
+ id = n+1;
+ }
+ return id;
+}
+
+//============================================================
+// Returns the signature object for the given Notary
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION SignatureInfo* ddocGetSignatureForNotary(const SignedDoc* pSigDoc,
+ const NotaryInfo* pNotInfo)
+{
+ int i;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ for(i = 0; i < pSigDoc->nSignatures; i++) {
+ SignatureInfo* pSignature = pSigDoc->pSignatures[i];
+ RETURN_OBJ_IF_NULL(pSignature, NULL);
+ if(pSignature->pNotary == pNotInfo)
+ return pSignature;
+ }
+ return NULL;
+}
+
+//============================================================
+// Returns the desired SignatureInfo object
+// pSigDoc - signed doc pointer
+// nIdx - SignatureInfo index (starting with 0)
+//============================================================
+EXP_OPTION SignatureInfo* getSignature(const SignedDoc* pSigDoc, int nIdx)
+{
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigDoc->nSignatures, ERR_BAD_SIG_INDEX, NULL);
+ RETURN_OBJ_IF_NULL(pSigDoc->pSignatures[nIdx], NULL);
+ return pSigDoc->pSignatures[nIdx];
+}
+
+//============================================================
+// Returns the last SignatureInfo object
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION SignatureInfo* ddocGetLastSignature(const SignedDoc* pSigDoc)
+{
+ int nIdx;
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ nIdx = pSigDoc->nSignatures - 1;
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigDoc->nSignatures, ERR_BAD_SIG_INDEX, NULL);
+ RETURN_OBJ_IF_NULL(pSigDoc->pSignatures && pSigDoc->pSignatures[nIdx], NULL);
+ return pSigDoc->pSignatures[nIdx];
+}
+
+//============================================================
+// Returns the SignatureInfo object with the given id
+// pSigDoc - signed doc pointer
+// id - SignatureInfo id
+//============================================================
+EXP_OPTION SignatureInfo* getSignatureWithId(const SignedDoc* pSigDoc, const char* id)
+{
+ SignatureInfo* pSignature = NULL;
+ int i;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ RETURN_OBJ_IF_NULL(id, NULL);
+ for(i = 0; i < pSigDoc->nSignatures; i++) {
+ RETURN_OBJ_IF_NULL(pSigDoc->pSignatures[i], NULL);
+ RETURN_OBJ_IF_NULL(pSigDoc->pSignatures[i]->szId, NULL);
+ if(!strcmp(pSigDoc->pSignatures[i]->szId, id)) {
+ pSignature = pSigDoc->pSignatures[i];
+ break;
+ }
+ }
+ return pSignature;
+}
+
+
+//============================================================
+// Adds a new SignedInfo element to a SignedDoc element and initializes it
+// id - signature id (use NULL for default)
+// return the newly created structure
+//============================================================
+// FIXME : memory leaks possible..
+EXP_OPTION int SignatureInfo_new(SignatureInfo **newSignatureInfo,
+ SignedDoc* pSigDoc, const char* id)
+{
+ int i, nId = 0;
+ SignatureInfo** pSignatures = NULL;
+ SignatureInfo* pSigInfo = NULL;
+ char buf[100];
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ //clearErrors();
+ if(hasSignatureWithWrongDataFileHash(pSigDoc)) {
+ ddocDebug(1, "SignatureInfo_new", "Cannot add signature in ddoc with invalid DataFile hashes!");
+ return ERR_FILE_WRITE;
+ }
+ if(!id)
+ nId = getNextSignatureId(pSigDoc);
+ if(pSigDoc->nSignatures == 0) {
+ RETURN_IF_NOT(!pSigDoc->pSignatures, ERR_BAD_SIG_COUNT);
+ pSigDoc->nSignatures = 1;
+ }
+ else
+ pSigDoc->nSignatures++;
+ pSignatures = (SignatureInfo**)malloc((pSigDoc->nSignatures) * sizeof(void *));
+ RETURN_IF_BAD_ALLOC(pSignatures);
+ for(i = 0; i < pSigDoc->nSignatures-1; i++)
+ pSignatures[i] = pSigDoc->pSignatures[i];
+ pSigInfo = (SignatureInfo*)malloc(sizeof(SignatureInfo));
+ RETURN_IF_BAD_ALLOC(pSigInfo);
+ memset(pSigInfo, 0, sizeof(SignatureInfo));
+ pSignatures[pSigDoc->nSignatures-1] = pSigInfo;
+ if(pSigDoc->pSignatures)
+ free(pSigDoc->pSignatures);
+ pSigDoc->pSignatures = pSignatures;
+ if(id) {
+ setString(&(pSigInfo->szId), id, -1);
+ } else {
+ snprintf(buf, sizeof(buf), "S%d", nId);
+ setString(&(pSigInfo->szId), buf, -1);
+ }
+ // create timestamp
+ createTimestamp(pSigDoc, buf, sizeof(buf));
+ setString(&(pSigInfo->szTimeStamp), buf, -1);
+ *newSignatureInfo = pSigInfo;
+ return ERR_OK;
+}
+
+
+//============================================================
+// Sets the signature production place info
+// pSigInfo - signature info object
+// city - city name
+// state - state or province name
+// zip - postal code
+// country - country name
+//============================================================
+EXP_OPTION int setSignatureProductionPlace(SignatureInfo* pSigInfo,
+ const char* city, const char* state,
+ const char* zip, const char* country)
+{
+ char* p = 0;
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ if(city) {
+ p = (char*)escape2xmlsym(city);
+ if(p) {
+ setString(&(pSigInfo->sigProdPlace.szCity), p, -1);
+ free(p);
+ }
+ }
+ if(state) {
+ p = (char*)escape2xmlsym(state);
+ if(p) {
+ setString(&(pSigInfo->sigProdPlace.szStateOrProvince), p, -1);
+ free(p);
+ }
+ }
+ if(zip) {
+ p = (char*)escape2xmlsym(zip);
+ if(p) {
+ setString(&(pSigInfo->sigProdPlace.szPostalCode), p, -1);
+ free(p);
+ }
+ }
+ if(country) {
+ p = (char*)escape2xmlsym(country);
+ if(p) {
+ setString(&(pSigInfo->sigProdPlace.szCountryName), country, -1);
+ free(p);
+ }
+ }
+ return ERR_OK;
+}
+
+
+
+//============================================================
+// Adds a signer role
+// pSigInfo - signature info object
+// nCertified - certified role? (1/0)
+// role - role data
+// rLen - role data length
+// encode - 1=encode it with Base64, 0=use as is
+//============================================================
+// FIXME : memory leaks possible...
+EXP_OPTION int addSignerRole(SignatureInfo* pSigInfo, int nCertified,
+ const char* role, int rLen, int enc)
+{
+ int n, i;
+ char **p = NULL, *b = NULL, *p1;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ //if(!enc && role && (strchr(role, '<') || strchr(role, '>')))
+ // SET_LAST_ERROR_RETURN(ERR_INVALID_CONTENT, ERR_INVALID_CONTENT);
+
+ if(nCertified) {
+ n = pSigInfo->signerRole.nCertifiedRoles + 1;
+ p = (char**)malloc(n * sizeof(void*));
+ RETURN_IF_BAD_ALLOC(p);
+ if(pSigInfo->signerRole.nCertifiedRoles) {
+ RETURN_IF_NULL(pSigInfo->signerRole.pCertifiedRoles);
+ for(i = 0; i < pSigInfo->signerRole.nCertifiedRoles; i++)
+ p[i] = pSigInfo->signerRole.pCertifiedRoles[i];
+ free(pSigInfo->signerRole.pCertifiedRoles);
+ }
+ p[n-1] = 0;
+ if(enc) {
+ b = (char*)malloc(rLen * 2);
+ RETURN_IF_BAD_ALLOC(b);
+ i = sizeof(b);
+ encode((const byte*)role, rLen, (byte*)b, &i);
+ b[i] = 0;
+ setString(&(p[n-1]), b, i);
+ }
+ else
+ setString(&(p[n-1]), role, rLen);
+ pSigInfo->signerRole.pCertifiedRoles = p;
+ pSigInfo->signerRole.nCertifiedRoles = n;
+ } else {
+ n = pSigInfo->signerRole.nClaimedRoles + 1;
+ p = (char**)malloc(n * sizeof(void*));
+ RETURN_IF_BAD_ALLOC(p);
+ if(pSigInfo->signerRole.nClaimedRoles) {
+ RETURN_IF_NULL(pSigInfo->signerRole.pClaimedRoles);
+ for(i = 0; i < pSigInfo->signerRole.nClaimedRoles; i++)
+ p[i] = pSigInfo->signerRole.pClaimedRoles[i];
+ free(pSigInfo->signerRole.pClaimedRoles);
+ }
+ p[n-1] = 0;
+ if(enc) {
+ b = (char*)malloc(rLen * 2);
+ RETURN_IF_BAD_ALLOC(b);
+ i = sizeof(b);
+ encode((const byte*)role, rLen, (byte*)b, &i);
+ b[i] = 0;
+ setString(&(p[n-1]), b, i);
+ }
+ else {
+ p1 = (char*)escape2xmlsym(role);
+ if(p1) {
+ setString(&(p[n-1]), p1, -1);
+ free(p1);
+ }
+ }
+ pSigInfo->signerRole.pClaimedRoles = p;
+ pSigInfo->signerRole.nClaimedRoles = n;
+ }
+ return ERR_OK;
+}
+
+//============================================================
+// Returns the number of signer roles
+// pSigInfo - signature info object
+// nCertified - certified role? (1/0)
+//============================================================
+EXP_OPTION int getCountOfSignerRoles(SignatureInfo* pSigInfo, int nCertified)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, -1);
+ if(nCertified)
+ return pSigInfo->signerRole.nCertifiedRoles;
+ else
+ return pSigInfo->signerRole.nClaimedRoles;
+}
+
+
+//============================================================
+// Returns the desired signer role
+// pSigInfo - signature info object
+// nCertified - certified role? (1/0)
+//============================================================
+EXP_OPTION const char* getSignerRole(SignatureInfo* pSigInfo, int nCertified, int nIdx)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, 0);
+ if(nCertified) {
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigInfo->signerRole.nCertifiedRoles, ERR_BAD_ROLE_INDEX, 0);
+ RETURN_OBJ_IF_NULL(pSigInfo->signerRole.pCertifiedRoles[nIdx], 0);
+ return pSigInfo->signerRole.pCertifiedRoles[nIdx];
+ } else {
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigInfo->signerRole.nClaimedRoles, ERR_BAD_ROLE_INDEX, 0);
+ RETURN_OBJ_IF_NULL(pSigInfo->signerRole.pClaimedRoles[nIdx], 0);
+ return pSigInfo->signerRole.pClaimedRoles[nIdx];
+ }
+}
+
+
+//============================================================
+// Removes this SignatureInfo from signed doc and frees it's memory
+// pSigDoc - signed doc object
+// id - signature id to be removed
+//============================================================
+EXP_OPTION int SignatureInfo_delete(SignedDoc* pSigDoc, const char* id)
+{
+ int n, i, j, err = ERR_OK;
+ SignatureInfo* pSignature;
+ SignatureInfo** pSignatures;
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ ddocDebug(3, "SignatureInfo_delete", "id: %s", id);
+ if(hasSignatureWithWrongDataFileHash(pSigDoc)) {
+ ddocDebug(1, "SignatureInfo_delete", "Cannot delete signature in ddoc with invalid DataFile hashes!");
+ return ERR_FILE_WRITE;
+ }
+ if((pSignature = getSignatureWithId(pSigDoc, id)) != NULL) {
+ n = pSigDoc->nSignatures - 1;
+ if(n > 0) {
+ pSignatures = (SignatureInfo**)malloc(n * sizeof(void*));
+ RETURN_IF_BAD_ALLOC(pSignatures);
+ for(i = j = 0; i < pSigDoc->nSignatures; i++) {
+ if(strcmp(pSigDoc->pSignatures[i]->szId, id)) {
+ pSignatures[j++] = pSigDoc->pSignatures[i];
+ } else {
+ SignatureInfo_free(pSigDoc->pSignatures[i]);
+ }
+ }
+ free(pSigDoc->pSignatures);
+ pSigDoc->pSignatures = pSignatures;
+ pSigDoc->nSignatures = j;
+ } else {
+ for(i = 0; i < pSigDoc->nSignatures; i++){
+ SignatureInfo_free(pSigDoc->pSignatures[i]);
+ free(pSigDoc->pSignatures);
+ pSigDoc->pSignatures = NULL;
+ pSigDoc->nSignatures = 0;}
+ }
+ }
+ else
+ err = ERR_BAD_SIG_INDEX;
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+
+//============================================================
+// cleanup SignatureInfo memory
+// pSigInfo - object to be cleaned up
+//============================================================
+EXP_OPTION void SignatureInfo_free(SignatureInfo* pSigInfo)
+{
+ int i;
+
+ RETURN_VOID_IF_NULL(pSigInfo);
+ if(pSigInfo->szId)
+ free(pSigInfo->szId);
+ if(pSigInfo->szTimeStamp)
+ free(pSigInfo->szTimeStamp);
+ if(pSigInfo->pSigPropDigest)
+ ddocDigestValue_free(pSigInfo->pSigPropDigest);
+ if(pSigInfo->pSigPropRealDigest)
+ ddocDigestValue_free(pSigInfo->pSigPropRealDigest);
+ if(pSigInfo->pSigInfoRealDigest)
+ ddocDigestValue_free(pSigInfo->pSigInfoRealDigest);
+ if(pSigInfo->pSigValue)
+ ddocSignatureValue_free(pSigInfo->pSigValue);
+ for(i = 0; i < pSigInfo->nDocs; i++) {
+ DocInfo_free(pSigInfo->pDocs[i]);
+ }
+ if(pSigInfo->pDocs)
+ free(pSigInfo->pDocs);
+ // signature production place
+ if(pSigInfo->sigProdPlace.szCity)
+ free(pSigInfo->sigProdPlace.szCity);
+ if(pSigInfo->sigProdPlace.szStateOrProvince)
+ free(pSigInfo->sigProdPlace.szStateOrProvince);
+ if(pSigInfo->sigProdPlace.szPostalCode)
+ free(pSigInfo->sigProdPlace.szPostalCode);
+ if(pSigInfo->sigProdPlace.szCountryName)
+ free(pSigInfo->sigProdPlace.szCountryName);
+ // signer role
+ for(i = 0; i < pSigInfo->signerRole.nClaimedRoles; i++) {
+ if(pSigInfo->signerRole.pClaimedRoles[i])
+ free(pSigInfo->signerRole.pClaimedRoles[i]);
+ }
+ if(pSigInfo->signerRole.pClaimedRoles)
+ free(pSigInfo->signerRole.pClaimedRoles);
+ for(i = 0; i < pSigInfo->signerRole.nCertifiedRoles; i++) {
+ if (pSigInfo->signerRole.pCertifiedRoles[i])
+ free(pSigInfo->signerRole.pCertifiedRoles[i]);
+ }
+ if(pSigInfo->signerRole.pCertifiedRoles)
+ free(pSigInfo->signerRole.pCertifiedRoles);
+ ddocMemBuf_free(&(pSigInfo->mbufOrigContent));
+ if(pSigInfo->pNotary)
+ NotaryInfo_free(pSigInfo->pNotary);
+ if(pSigInfo->pCertIDs)
+ ddocCertIDList_free(pSigInfo->pCertIDs);
+ if(pSigInfo->pCertValues)
+ ddocCertValueList_free(pSigInfo->pCertValues);
+ //AM 23.05.08
+ if(pSigInfo->szDigestType)
+ free(pSigInfo->szDigestType);
+ free(pSigInfo);
+}
+
+//============================================================
+// Sets signatures signed properties digest
+// pSigInfo - signature info object
+// value - new binary digest value
+// len - length of the value
+//============================================================
+EXP_OPTION int ddocSigInfo_SetSigPropDigest(SignatureInfo* pSigInfo, const char* value, long len)
+{
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(value);
+ if(!pSigInfo->pSigPropDigest)
+ ddocDigestValue_new(&(pSigInfo->pSigPropDigest), 0, 0, 0);
+ return ddocDigestValue_SetDigestValue(pSigInfo->pSigPropDigest, value, len);
+}
+
+//============================================================
+// Sets signatures signed properties real digest as read from file
+// pSigInfo - signature info object
+// value - new binary digest value
+// len - length of the value
+//============================================================
+EXP_OPTION int ddocSigInfo_SetSigPropRealDigest(SignatureInfo* pSigInfo, const char* value, long len)
+{
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(value);
+ if(!pSigInfo->pSigPropRealDigest)
+ ddocDigestValue_new(&(pSigInfo->pSigPropRealDigest), 0, 0, 0);
+ return ddocDigestValue_SetDigestValue(pSigInfo->pSigPropRealDigest, value, len);
+}
+
+//============================================================
+// Sets signatures signed info real digest as read from file
+// pSigInfo - signature info object
+// value - new binary digest value
+// len - length of the value
+//============================================================
+EXP_OPTION int ddocSigInfo_SetSigInfoRealDigest(SignatureInfo* pSigInfo, const char* value, long len)
+{
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(value);
+ if(!pSigInfo->pSigInfoRealDigest)
+ ddocDigestValue_new(&(pSigInfo->pSigInfoRealDigest), 0, 0, 0);
+ return ddocDigestValue_SetDigestValue(pSigInfo->pSigInfoRealDigest, value, len);
+}
+
+//============================================================
+// Returns signatures signed properties digest
+// pSigInfo - signature info object
+// return digest value as DigiDocMemBuf pointer or NULL
+//============================================================
+EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigPropDigest(SignatureInfo* pSigInfo)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ return ddocDigestValue_GetDigestValue(pSigInfo->pSigPropDigest);
+}
+
+//============================================================
+// Returns signatures signed properties digest as read from file
+// pSigInfo - signature info object
+// return digest value as DigiDocMemBuf pointer or NULL
+//============================================================
+EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigPropRealDigest(SignatureInfo* pSigInfo)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ return ddocDigestValue_GetDigestValue(pSigInfo->pSigPropRealDigest);
+}
+
+//============================================================
+// Returns signatures signed info digest as read from file
+// pSigInfo - signature info object
+// return digest value as DigiDocMemBuf pointer or NULL
+//============================================================
+EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigInfoRealDigest(SignatureInfo* pSigInfo)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ return ddocDigestValue_GetDigestValue(pSigInfo->pSigInfoRealDigest);
+}
+
+//============================================================
+// Returns signatures signature-value
+// pSigInfo - signature info object
+// return signature-value as SignatureValue pointer or NULL
+//============================================================
+EXP_OPTION SignatureValue* ddocSigInfo_GetSignatureValue(SignatureInfo* pSigInfo)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ return pSigInfo->pSigValue;
+}
+
+//============================================================
+// Returns signatures signature-value
+// pSigInfo - signature info object
+// return signature-value as DigiDocMemBuf pointer or NULL
+//============================================================
+EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSignatureValue_Value(SignatureInfo* pSigInfo)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ return ddocSignatureValue_GetSignatureValue(pSigInfo->pSigValue);
+}
+
+//============================================================
+// Sets signatures signature-value
+// pSigInfo - signature info object
+// value - new binary signature value
+// len - length of the value
+//============================================================
+EXP_OPTION int ddocSigInfo_SetSignatureValue(SignatureInfo* pSigInfo, const char* value, long len)
+{
+ char buf1[30];
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(value);
+ snprintf(buf1, sizeof(buf1), "%s-SIG", pSigInfo->szId);
+ if(!pSigInfo->pSigValue)
+ ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, 0, 0, 0);
+ ddocSignatureValue_SetId(pSigInfo->pSigValue, buf1);
+ return ddocSignatureValue_SetSignatureValue(pSigInfo->pSigValue, value, len);
+}
+
+//============================================================
+// Returns signaers certs - issuer-serial
+// pSigInfo - signature info object
+// return required atribute value
+//============================================================
+EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerSerial(const SignatureInfo* pSigInfo)
+{
+ CertID* pCertID = 0;
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID);
+ RETURN_OBJ_IF_NULL(pCertID, NULL);
+ return ddocCertID_GetIssuerSerial(pCertID);
+}
+
+//============================================================
+// Sets signers certs issuer serial
+// pSigInfo - signature info object
+// value - new value
+//============================================================
+EXP_OPTION int ddocSigInfo_SetSignersCert_IssuerSerial(SignatureInfo* pSigInfo, const char* value)
+{
+ CertID* pCertID = 0;
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(value);
+ pCertID = ddocCertIDList_GetOrCreateCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID);
+ return ddocCertID_SetIssuerSerial(pCertID, value);
+}
+
+//============================================================
+// Returns signaers certs - issuer-name
+// pSigInfo - signature info object
+// return required atribute value
+//============================================================
+EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerName(const SignatureInfo* pSigInfo)
+{
+ CertID* pCertID = 0;
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID);
+ RETURN_OBJ_IF_NULL(pCertID, NULL);
+ return ddocCertID_GetIssuerName(pCertID);
+}
+
+//============================================================
+// Returns signaers certs - issuer-name
+// pSigInfo - signature info object
+// pMbuf - memory buffer to return hash
+// return required atribute value
+//============================================================
+EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerNameAndHash(const SignatureInfo* pSigInfo, DigiDocMemBuf *pMbuf)
+{
+ CertID* pCertID = 0;
+ X509* pCert = 0;
+/* DigiDocMemBuf mbuf1, mbuf2, mbuf3;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ mbuf2.pMem = 0;
+ mbuf2.nLen = 0;
+ mbuf3.pMem = 0;
+ mbuf3.nLen = 0;
+*/
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ RETURN_OBJ_IF_NULL(pMbuf, NULL);
+ pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID);
+ RETURN_OBJ_IF_NULL(pCertID, NULL);
+ pCert = ddocSigInfo_GetSignersCert(pSigInfo);
+ RETURN_OBJ_IF_NULL(pCert, NULL);
+ /*ddocCertGetSubjectCN(pCert, &mbuf1);
+ readSubjectKeyIdentifier(pCert, &mbuf2);
+ ddocEncodeBase64(&mbuf2, &mbuf3);
+ ddocMemBuf_free(&mbuf2);
+ readAuthorityKeyIdentifier(pCert, pMbuf);
+ ddocEncodeBase64(pMbuf, &mbuf2);
+ ddocDebug(3, "ddocSigInfo_GetSignersCert_IssuerNameAndHash", "CN: %s subj-hash: %s issuer-hash: %s", (char*)mbuf1.pMem, (char*)mbuf3.pMem, (char*)mbuf2.pMem);
+ ddocMemBuf_free(&mbuf1);
+ ddocMemBuf_free(&mbuf2);
+ ddocMemBuf_free(&mbuf3);*/
+ readAuthorityKeyIdentifier(pCert, pMbuf);
+ return ddocCertID_GetIssuerName(pCertID);
+}
+
+//============================================================
+// Sets signers certs issuer name
+// pSigInfo - signature info object
+// value - new value
+//============================================================
+EXP_OPTION int ddocSigInfo_SetSignersCert_IssuerName(SignatureInfo* pSigInfo, const char* value)
+{
+ CertID* pCertID = 0;
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(value);
+ pCertID = ddocCertIDList_GetOrCreateCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID);
+ return ddocCertID_SetIssuerName(pCertID, value);
+}
+
+//============================================================
+// Returns signers certs digest as DigiDocMemBuf object
+// pSigInfo - signature info object
+// return signers certs digest as DigiDocMemBuf pointer or NULL
+//============================================================
+EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSignersCert_DigestValue(const SignatureInfo* pSigInfo)
+{
+ CertID* pCertID = 0;
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID);
+ RETURN_OBJ_IF_NULL(pCertID, NULL);
+ return ddocCertID_GetDigestValue(pCertID);
+}
+
+//============================================================
+// Sets signers certs digest
+// pSigInfo - signature info object
+// value - new binary signature value
+// len - length of the value
+//============================================================
+EXP_OPTION int ddocSigInfo_SetSignersCert_DigestValue(SignatureInfo* pSigInfo, const char* value, long len)
+{
+ CertID* pCertID = 0;
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(value);
+ pCertID = ddocCertIDList_GetOrCreateCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID);
+ return ddocCertID_SetDigestValue(pCertID, value, len);
+}
+
+//--------------------------------------------------
+// Finds a CertID object with required type
+// pSigInfo - signature info object [REQUIRED]
+// nType - type of CertID object [REQUIRED]
+// returns CertID pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertID* ddocSigInfo_GetCertIDOfType(const SignatureInfo* pSigInfo, int nType)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ if(pSigInfo->pCertIDs)
+ return ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, nType);
+ return NULL;
+}
+
+//--------------------------------------------------
+// Finds last CertID object of this signature
+// pSigInfo - signature info object [REQUIRED]
+// returns CertID pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertID* ddocSigInfo_GetLastCertID(const SignatureInfo* pSigInfo)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ if(pSigInfo->pCertIDs)
+ return ddocCertIDList_GetLastCertID(pSigInfo->pCertIDs);
+ return NULL;
+}
+
+
+//--------------------------------------------------
+// Finds a CertID object with required type or creates a new one
+// pSigInfo - signature info object [REQUIRED]
+// nType - type of CertID object [REQUIRED]
+// returns CertID pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertID* ddocSigInfo_GetOrCreateCertIDOfType(SignatureInfo* pSigInfo, int nType)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ if(!pSigInfo->pCertIDs)
+ ddocCertIDList_new(&(pSigInfo->pCertIDs));
+ RETURN_OBJ_IF_NULL(pSigInfo->pCertIDs, NULL);
+ return ddocCertIDList_GetOrCreateCertIDOfType(pSigInfo->pCertIDs, nType);
+}
+
+//--------------------------------------------------
+// Finds a CertValue object with required type
+// pSigInfo - signature info object [REQUIRED]
+// nType - type of CertValue object [REQUIRED]
+// returns CertValue pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertValue* ddocSigInfo_GetCertValueOfType(const SignatureInfo* pSigInfo, int nType)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ ddocDebug(9, "ddocSigInfo_GetCertValueOfType", "start");
+ if(pSigInfo->pCertValues)
+ return ddocCertValueList_GetCertValueOfType(pSigInfo->pCertValues, nType);
+ ddocDebug(9, "ddocSigInfo_GetCertValueOfType", "end");
+ return NULL;
+}
+
+//--------------------------------------------------
+// Finds a CertValue object with required type or creates a new one
+// pSigInfo - signature info object [REQUIRED]
+// nType - type of CertValue object [REQUIRED]
+// returns CertValue pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertValue* ddocSigInfo_GetOrCreateCertValueOfType(SignatureInfo* pSigInfo, int nType)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ if(!pSigInfo->pCertValues)
+ ddocCertValueList_new(&(pSigInfo->pCertValues));
+ RETURN_OBJ_IF_NULL(pSigInfo->pCertValues, NULL);
+ return ddocCertValueList_GetOrCreateCertValueOfType(pSigInfo->pCertValues, nType);
+}
+
+//--------------------------------------------------
+// Finds last CertValue
+// pSigInfo - signature info object [REQUIRED]
+// returns CertValue pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION CertValue* ddocSigInfo_GetLastCertValue(const SignatureInfo* pSigInfo)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ if(pSigInfo->pCertValues)
+ return ddocCertValueList_GetCertValue(pSigInfo->pCertValues,
+ ddocCertValueList_GetCertValuesCount(pSigInfo->pCertValues) - 1);
+ return NULL;
+}
+
+//--------------------------------------------------
+// Finds the signers certificate
+// pSigInfo - signature info object [REQUIRED]
+// returns certificate or NULL
+//--------------------------------------------------
+EXP_OPTION X509* ddocSigInfo_GetSignersCert(const SignatureInfo* pSigInfo)
+{
+ X509 *pCert = 0;
+ CertValue *pCertValue = 0;
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ if(pSigInfo->pCertValues) {
+ pCertValue = ddocSigInfo_GetCertValueOfType(pSigInfo, CERTID_VALUE_SIGNERS_CERT);
+ if(pCertValue)
+ pCert = pCertValue->pCert;
+ }
+ return pCert;
+}
+
+//--------------------------------------------------
+// Sets the signers certificate
+// pSigInfo - signature info object [REQUIRED]
+// pCert - certificate [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocSigInfo_SetSignersCert(SignatureInfo* pSigInfo, X509* pCert)
+{
+ int err = ERR_OK;
+ CertValue *pCertValue = 0;
+ char buf1[50];
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(pCert);
+ pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_SIGNERS_CERT);
+ if(pCertValue) {
+ snprintf(buf1, sizeof(buf1), "%s-SIGNER_CERT", pSigInfo->szId);
+ err = ddocCertValue_SetId(pCertValue, buf1);
+ if(!err && pCert)
+ err = ddocCertValue_SetCert(pCertValue, pCert);
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// Finds the OCSP responders certificate
+// pSigInfo - signature info object [REQUIRED]
+// returns certificate or NULL
+//--------------------------------------------------
+EXP_OPTION X509* ddocSigInfo_GetOCSPRespondersCert(const SignatureInfo* pSigInfo)
+{
+ X509 *pCert = 0;
+ CertValue *pCertValue = 0;
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ if(pSigInfo->pCertValues) {
+ ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "start");
+ pCertValue = ddocSigInfo_GetCertValueOfType(pSigInfo, CERTID_VALUE_RESPONDERS_CERT);
+ ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "end");
+ if(pCertValue){
+ pCert = pCertValue->pCert;
+ ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "test");}
+ }
+ ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "end2");
+ if(pCert) ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "pCert exists" );
+ return pCert;
+}
+
+//--------------------------------------------------
+// Sets the OCSP Responders certificate
+// pSigInfo - signature info object [REQUIRED]
+// pCert - certificate [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocSigInfo_SetOCSPRespondersCert(SignatureInfo* pSigInfo, X509* pCert)
+{
+ int err = ERR_OK;
+ CertValue *pCertValue = 0;
+ char buf1[50];
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(pCert);
+ pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_RESPONDERS_CERT);
+ if(pCertValue) {
+ snprintf(buf1, sizeof(buf1), "%s-RESPONDER_CERT", pSigInfo->szId);
+ err = ddocCertValue_SetId(pCertValue, buf1);
+ if(!err)
+ err = ddocCertValue_SetCert(pCertValue, pCert);
+ }
+ return err;
+}
+
+//============================================================
+// Adds a certificate and it's certid to this signature
+// pSigInfo - signature info object [REQUIRED]
+// pCert - vertificate [REQUIRED]
+// nCertIdType - type of cert [REQUIRED]
+// return error code or ERR_OK
+//============================================================
+EXP_OPTION int ddocSigInfo_addCert(SignatureInfo* pSigInfo, X509* pCert, int nCertIdType)
+{
+ int err = ERR_OK, l1;
+ char buf1[100], buf2[200], buf3[300], buf4[100];
+ CertID *pCertID = 0;
+ DigiDocMemBuf mbuf1;
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(pCert);
+
+ RETURN_IF_NOT(err == ERR_OK, err);
+ l1 = sizeof(buf1);
+ RETURN_IF_NOT(X509_digest(pCert, EVP_sha1(), (unsigned char*)buf1,
+ (unsigned int*)&l1), ERR_X509_DIGEST);
+ if(err) return err;
+ err = ReadCertSerialNumber(buf2, sizeof(buf2), pCert);
+ memset(buf3, 0, sizeof(buf3));
+ err = ddocCertGetIssuerDN(pCert, &mbuf1);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ // now set all those atributes
+ switch(nCertIdType) {
+ case CERTID_TYPE_SIGNERS_CERTID:
+ err = ddocSigInfo_SetSignersCert(pSigInfo, pCert);
+ snprintf(buf4, sizeof(buf4), "%s-CERTINFO", pSigInfo->szId);
+ ddocCertID_new(&pCertID, CERTID_TYPE_SIGNERS_CERTID, buf4, buf2, (char*)mbuf1.pMem, buf1, l1);
+ break;
+ case CERTID_TYPE_RESPONDERS_CERTID:
+ err = ddocSigInfo_SetOCSPRespondersCert(pSigInfo, pCert);
+ snprintf(buf4, sizeof(buf4), "%s-OCSP_CERTINFO", pSigInfo->szId);
+ ddocCertID_new(&pCertID, CERTID_TYPE_RESPONDERS_CERTID, buf4, buf2, (char*)mbuf1.pMem, buf1, l1);
+ break;
+ }
+ RETURN_IF_NOT(pCertID, ERR_BAD_ALLOC);
+ if(!pSigInfo->pCertIDs) {
+ err = ddocCertIDList_new(&(pSigInfo->pCertIDs));
+ //ddocCertID_free(pCertID); // not owner any more!
+ SET_LAST_ERROR_IF_NOT(err == ERR_OK, err);
+ }
+ if(pCertID) {
+ ddocCertIDList_addCertID(pSigInfo->pCertIDs, pCertID);
+ ddocDebug(3, "ddocSigInfo_addCert", "Added signers cert-id: %s type: %d", pCertID->szId, pCertID->nType);
+ }
+ ddocMemBuf_free(&mbuf1);
+ return err;
+}
+
+
+
+//======================< DocInfo functions >=========================================
+
+
+//============================================================
+// Adds a new DocInfo element to a SignatureInfo element and initializes it
+// pSigInfo - signature info object
+// docId - document id (use NULL for default)
+// digType - digest type
+// digest - documents digest
+// digLen - digest length
+// mime - mime type
+// mimeDig - mime digest
+// mimeDigLen - mime digest length
+// return the newly created structure
+//============================================================
+EXP_OPTION int addDocInfo(DocInfo **newDocInfo, SignatureInfo* pSigInfo, const char* docId,
+ const char* digType, const byte* digest,
+ int digLen, const byte* mimeDig, int mimeDigLen)
+{
+ DocInfo** pDocInfos = NULL;
+ DocInfo* pDocInfo = NULL;
+ int i;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ if(pSigInfo->nDocs == 0) {
+ RETURN_IF_NOT(!pSigInfo->pDocs, ERR_BAD_DOCINFO_COUNT);
+ pSigInfo->nDocs = 1;
+ }
+ else
+ pSigInfo->nDocs++;
+ pDocInfos = (DocInfo**)malloc((pSigInfo->nDocs) * sizeof(void *));
+ RETURN_IF_BAD_ALLOC(pDocInfos);
+ for(i = 0; i < pSigInfo->nDocs-1; i++)
+ pDocInfos[i] = pSigInfo->pDocs[i];
+ pDocInfo = (DocInfo*)malloc(sizeof(DocInfo)); // MEMLEAK: ???
+ if (!pDocInfo) {
+ free(pDocInfos);
+ SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC);
+ }
+ memset(pDocInfo, 0, sizeof(DocInfo));
+ pDocInfos[pSigInfo->nDocs-1] = pDocInfo;
+ // PR. leak found
+ if(pSigInfo->pDocs)
+ free(pSigInfo->pDocs);
+ pSigInfo->pDocs = pDocInfos;
+ if(docId)
+ setString(&(pDocInfo->szDocId), docId, -1);
+ if(digType)
+ setString(&(pDocInfo->szDigestType), digType, -1);
+ if(digest) {
+ setString((char**)&(pDocInfo->szDigest), (const char*)digest, digLen);
+ pDocInfo->nDigestLen = digLen;
+ }
+ if(mimeDig && strlen((const char*)mimeDig)) {
+ setString((char**)&(pDocInfo->szMimeDigest), (const char*)mimeDig, mimeDigLen);
+ pDocInfo->nMimeDigestLen = mimeDigLen;
+ }
+ *newDocInfo = pDocInfo;
+ return ERR_OK;
+}
+
+//============================================================
+// cleanup DocInfo memory
+// pDocInfo - object to be cleaned up
+//============================================================
+EXP_OPTION void DocInfo_free(DocInfo* pDocInfo)
+{
+ RETURN_VOID_IF_NULL(pDocInfo);
+ //assert(pDocInfo);
+ if(pDocInfo->szDocId)
+ free(pDocInfo->szDocId);
+ if(pDocInfo->szDigestType)
+ free(pDocInfo->szDigestType);
+ if(pDocInfo->szDigest)
+ free(pDocInfo->szDigest);
+ if(pDocInfo->szMimeDigest)
+ free(pDocInfo->szMimeDigest);
+ // free the object itself
+ free(pDocInfo);
+}
+
+//============================================================
+// Returns number of DocInfos
+// pSigInfo - signature info pointer
+//============================================================
+EXP_OPTION int getCountOfDocInfos(const SignatureInfo* pSigInfo)
+{
+ RETURN_OBJ_IF_NULL(pSigInfo, -1);
+ return pSigInfo->nDocs;
+}
+
+//============================================================
+// Returns the desired DocInfo
+// pSigInfo - signature info pointer
+// idx - DocInfo index
+//============================================================
+EXP_OPTION DocInfo* getDocInfo(const SignatureInfo* pSigInfo, int idx)
+{
+ ddocDebug(3, "getDocInfo", "Idx: %d, Docs: %d", idx, pSigInfo->nDocs);
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ SET_LAST_ERROR_RETURN_IF_NOT(idx < pSigInfo->nDocs, ERR_BAD_DOCINFO_INDEX, NULL);
+ RETURN_OBJ_IF_NULL(pSigInfo->pDocs, NULL);
+ RETURN_OBJ_IF_NULL(pSigInfo->pDocs[idx], NULL);
+ return pSigInfo->pDocs[idx];
+}
+
+//============================================================
+// Returns the last DocInfo
+// pSigInfo - signature info pointer
+// idx - DocInfo index
+//============================================================
+EXP_OPTION DocInfo* ddocGetLastDocInfo(const SignatureInfo* pSigInfo)
+{
+ int idx;
+
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ idx = pSigInfo->nDocs - 1;
+ SET_LAST_ERROR_RETURN_IF_NOT(idx < pSigInfo->nDocs, ERR_BAD_DOCINFO_INDEX, NULL);
+ RETURN_OBJ_IF_NULL(pSigInfo->pDocs, NULL);
+ RETURN_OBJ_IF_NULL(pSigInfo->pDocs[idx], NULL);
+ return pSigInfo->pDocs[idx];
+}
+
+//============================================================
+// Returns the DocInfo object with the given id
+// pSigInfo - signature info pointer
+// id - SignatureInfo id
+//============================================================
+EXP_OPTION DocInfo* getDocInfoWithId(const SignatureInfo* pSigInfo, const char* id)
+{
+ DocInfo* pDocInfo = NULL;
+ int i;
+
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ //RETURN_OBJ_IF_NULL(id, NULL);
+ for(i = 0; i < pSigInfo->nDocs; i++) {
+ RETURN_OBJ_IF_NULL(pSigInfo->pDocs[i], NULL);
+ RETURN_OBJ_IF_NULL(pSigInfo->pDocs[i]->szDocId, NULL);
+ if((id && !strcmp(pSigInfo->pDocs[i]->szDocId, id)) || !id) {
+ pDocInfo = pSigInfo->pDocs[i];
+ break;
+ }
+ }
+ return pDocInfo;
+}
+
+//============================================================
+// Sets the DocInfo objects document digest and digest type
+// pDocInfo - document info pointer
+// digest - digest value
+// digLen - digest value length
+// digType - digest type
+//============================================================
+EXP_OPTION void setDocInfoDigest(DocInfo* pDocInfo, const byte* digest,
+ int digLen, const char* digType)
+{
+ RETURN_VOID_IF_NULL(pDocInfo);
+ if(digType)
+ setString(&(pDocInfo->szDigestType), digType, -1);
+ if(digest) {
+ setString((char**)&(pDocInfo->szDigest), (const char*)digest, digLen);
+ pDocInfo->nDigestLen = digLen;
+ }
+}
+
+//============================================================
+// Sets the DocInfo objects mime digest and mime type
+// pDocInfo - document info pointer
+// mimeDig - mime digest value
+// mimeDigLen - mime digest value length
+//============================================================
+EXP_OPTION void setDocInfoMimeDigest(DocInfo* pDocInfo, const byte* mimeDig,
+ int mimeDigLen)
+{
+ RETURN_VOID_IF_NULL(pDocInfo);
+ if(mimeDig) {
+ setString((char**)&(pDocInfo->szMimeDigest), (const char*)mimeDig, mimeDigLen);
+ pDocInfo->nMimeDigestLen = mimeDigLen;
+ }
+}
+
+//============================================================
+// Adds all DocInfo elements in this file to a SignatureInfo element
+// pSigInfo - signature info object
+// pSigDoc - signed document
+//============================================================
+EXP_OPTION int addAllDocInfos(SignedDoc* pSigDoc, SignatureInfo* pSigInfo)
+{
+ int i, c, l2;
+ int len = 0;
+ //Added by AA 28/10/2003 - not defined len value
+ DataFile *pDf = NULL;
+ DocInfo *pDocInfo = NULL;
+ byte buf[DIGEST_LEN+2], buf2[50];
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ c = getCountOfDataFiles(pSigDoc);
+ for(i = 0; i < c; i++ ) {
+ pDf = getDataFile(pSigDoc, i);
+ RETURN_IF_NULL(pDf);
+ buf[0] = 0;
+ // in version 1.0 we use mime digest
+ if(!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) {
+ len = sizeof(buf);
+ calculateDigest((const byte*)pDf->szMimeType, strlen(pDf->szMimeType),
+ DIGEST_SHA1, buf, &len);
+ }
+ // in 1.1 we don't use mime digest
+ memset(buf2, 0, sizeof(buf2));
+ l2 = 0;
+ encode((const byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, (byte*)buf2, &l2);
+ ddocDebug(3, "addAllDocInfos", "DF: %s digest \'%s\'", pDf->szId, buf2);
+ addDocInfo(&pDocInfo, pSigInfo, pDf->szId,
+ pDf->szDigestType, (byte*)pDf->mbufDigest.pMem,
+ pDf->mbufDigest.nLen, buf, len);
+ }
+ return ERR_OK;
+}
+
+//============================================================
+// Calculates and stores a signature for this SignatureInfo object
+// pSigInfo - signature info object
+// nSigType - signature type code
+// keyfile - RSA key file
+// passwd - key password
+// certfile - certificate file
+//============================================================
+EXP_OPTION int calculateSigInfoSignature(const SignedDoc* pSigDoc,
+ SignatureInfo* pSigInfo, int nSigType,
+ const char* keyfile, const char* passwd,
+ const char* certfile)
+{
+ int err = ERR_OK;
+ char buf2[SIGNATURE_LEN], *buf1 = NULL;
+ int l2, l1;
+ X509 *pCert = 0;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ clearErrors();
+ if(nSigType == SIGNATURE_RSA) {
+ err = ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, SIGN_RSA_NAME, 0, 0);
+ if(err) return err;
+
+ err = ReadCertificate(&pCert, certfile);
+ if(!err && pCert)
+ err = ddocSigInfo_SetSignersCert(pSigInfo, pCert);
+ RETURN_IF_NOT(err == ERR_OK, ERR_CERT_READ);
+ // Signed properties digest
+ buf1 = createXMLSignedProperties(pSigDoc, pSigInfo, 0);
+ RETURN_IF_NULL(buf1);
+ l1 = strlen(buf1);
+ l2 = sizeof(buf2);
+ calculateDigest((const byte*)buf1, l1, DIGEST_SHA1, (byte*)buf2, &l2);
+ free(buf1);
+ err = ddocSigInfo_SetSigPropDigest(pSigInfo, buf2, l2);
+ // SignedInfo digest
+ buf1 = createXMLSignedInfo(pSigDoc, pSigInfo);
+ RETURN_IF_NULL(buf1);
+ l2 = sizeof(buf2);
+ err = signData((const byte*)buf1, strlen(buf1), (byte*)buf2, &l2, DIGEST_SHA1,
+ keyfile, passwd);
+ free(buf1);
+ err = ddocSigInfo_SetSignatureValue(pSigInfo, buf2, l2);
+ } else
+ err = ERR_UNSUPPORTED_SIGNATURE;
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+//============================================================
+// Calculates <SignedProperties> digest
+// pSigInfo - signature info object
+//============================================================
+EXP_OPTION int calculateSignedPropertiesDigest(SignedDoc* pSigDoc, SignatureInfo* pSigInfo)
+{
+ int err = ERR_OK, l1, l2;
+ byte buf1[DIGEST_LEN256+2], *buf2 = 0, *buf3 = 0;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ /* P.R 0->1 */
+ buf2 = (byte*)createXMLSignedProperties(pSigDoc, pSigInfo, 1);
+ RETURN_IF_NULL(buf2);
+ buf3 = canonicalizeXML((char*)buf2, strlen((const char*)buf2));
+ //dumpInFile("sigprop-sig1.txt", buf2);
+ l2 = (int)strlen((const char*)buf3);
+ l1 = (int)sizeof(buf1);
+ calculateDigest(buf3, l2, DIGEST_SHA1, buf1, &l1);
+ free(buf2);
+ free(buf3);
+ err = ddocSigInfo_SetSigPropDigest(pSigInfo, (char*)buf1, l1);
+ return err;
+}
+
+//============================================================
+// Returns 1 if this signature has 1 reference that was verified
+// by wrong DataFile hash calculated not using xmlns atribute
+// pSigInfo - signature info pointer
+//============================================================
+EXP_OPTION int verifiedByWrongDataFileHash(const SignatureInfo* pSigInfo)
+{
+ int i;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ for(i = 0; i < pSigInfo->nDocs; i++) {
+ RETURN_IF_NULL_PARAM(pSigInfo->pDocs[i]);
+ if(pSigInfo->pDocs[i] && pSigInfo->pDocs[i]->szDigestType &&
+ !strcmp(pSigInfo->pDocs[i]->szDigestType, DIGEST_SHA1_WRONG))
+ return 1;
+ }
+ return 0;
+}
+
+//============================================================
+// Returns 1 if one signature has 1 reference that was verified
+// by wrong DataFile hash calculated not using xmlns atribute
+// pSigDoc - signed doc container pointer
+//============================================================
+EXP_OPTION int hasSignatureWithWrongDataFileHash(const SignedDoc* pSigDoc)
+{
+ int i, d, j;
+ SignatureInfo *pSigInfo = 0;
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ d = getCountOfSignatures(pSigDoc);
+ for(i = 0; i < d; i++) {
+ pSigInfo = getSignature(pSigDoc, i);
+ j = verifiedByWrongDataFileHash(pSigInfo);
+ if(j) return j;
+ }
+ return 0;
+}
+
+//============================================================
+// Calculates <SignedInfo> digest
+// pSigInfo - signature info object
+// digBuf - buffer for digest value
+// digLen - address of buffer length. Must be initialized
+// with buf max len, will be changed to actual length
+//============================================================
+EXP_OPTION int calculateSignedInfoDigest(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, byte* digBuf, int* digLen)
+{
+ int err = ERR_OK, l2;
+ byte *buf2 = NULL;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(digBuf);
+ buf2 = (byte*)createXMLSignedInfo(pSigDoc, pSigInfo);
+ RETURN_IF_NULL(buf2);
+ l2 = strlen((const char*)buf2);
+ calculateDigest(buf2, l2, DIGEST_SHA1, digBuf, digLen);
+ free(buf2);
+ return err;
+}
+
+//============================================================
+// Sets the signature value from a file that contains
+// the base64 encoded signature value
+// pSigInfo - signature info object
+// szSigFile - filename
+//============================================================
+EXP_OPTION int setSignatureValueFromFile(SignatureInfo* pSigInfo, char* szSigFile)
+{
+ int err = ERR_OK, i, j, slen;
+ FILE* hFile = 0;
+ byte buf[FILE_BUFSIZE], sbuf[300], buf1[30];
+ DigiDocMemBuf mbuf1;
+ char *p1;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(szSigFile);
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ ddocDebug(3, "setSignatureValueFromFile", "reading: %s", szSigFile);
+ if((hFile = fopen(szSigFile, "rb")) != NULL) {
+ slen = 0;
+ memset(sbuf, 0, sizeof(sbuf));
+ // collect all hex chars to sbuf
+ while((i = fread(buf, sizeof(char), FILE_BUFSIZE, hFile)) > 0) {
+ ddocDebug(3, "setSignatureValueFromFile", "read: %d", i);
+ for(j = 0; j < i; j++) {
+ if(isxdigit(buf[j])) {
+ if(isdigit(buf[j])) {
+ sbuf[slen++] = buf[j];
+ } else {
+ sbuf[slen++] = toupper(buf[j]);
+ } // else
+ } // if
+ } // for
+ }
+ ddocDebug(3, "setSignatureValueFromFile", "input: %d - \'%s\'", slen, sbuf);
+ // decode hex
+ memset(buf, 0, sizeof(buf));
+ j = 0;
+ hex2bin((const char*)sbuf, (byte*)buf, &j);
+ ddocDebug(3, "setSignatureValueFromFile", "decoded: %d", j);
+ // encode in base64 again as we need it this way for signature value
+ memset(sbuf, 0, sizeof(sbuf));
+ slen = 0;
+ encode((const byte*)buf, j, (byte*)sbuf, &slen);
+ ddocDebug(3, "setSignatureValueFromFile", "encoded: %d - \'%s\'", slen, sbuf);
+ if(j == SIGNATURE_LEN) {
+ snprintf((char*)buf1, sizeof(buf1), "#%s-SIG", pSigInfo->szId);
+ ddocSignatureValue_new(&(pSigInfo->pSigValue), (char*)buf1, SIGN_RSA_NAME, (char*)buf, j);
+ //ddocMemBuf_free(&(pSigInfo->mbufOrigContent));
+ if(pSigInfo->mbufOrigContent.pMem) {
+ p1 = strstr((char*)pSigInfo->mbufOrigContent.pMem, "<SignatureValue");
+ if(p1) p1 = strchr(p1, '>');
+ if(p1) p1++;
+ if(p1) *p1 = 0;
+ if(p1) {
+ ddocMemAssignData(&mbuf1, (char*)pSigInfo->mbufOrigContent.pMem, -1);
+ ddocMemAppendData(&mbuf1, (char*)sbuf, -1);
+ p1++;
+ //ddocDebug(3, "setSignatureValueFromFile", "add: %s", p1);
+ ddocMemAppendData(&mbuf1, p1, -1);
+ }
+ ddocMemAssignData(&(pSigInfo->mbufOrigContent), (const char*)mbuf1.pMem, mbuf1.nLen);
+ ddocMemBuf_free(&mbuf1);
+ }
+ }
+ else
+ err = ERR_SIGNATURE;
+ fclose(hFile);
+ }
+ else
+ err = ERR_FILE_READ;
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+//============================================================
+// Sets the signature value
+// pSigInfo - signature info object
+// szSignature - signature value
+// sigLen - signature length
+//============================================================
+EXP_OPTION int setSignatureValue(SignatureInfo* pSigInfo, byte* szSignature, int sigLen)
+{
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(szSignature);
+
+ //clearErrors();
+ // VS: not quite sure if there's not a second constant to use instead of removing the check
+ //RETURN_IF_NOT(sigLen == SIGNATURE_LEN, ERR_SIGNATURE);
+ ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, SIGN_RSA_NAME, szSignature, sigLen);
+ ddocMemBuf_free(&(pSigInfo->mbufOrigContent));
+ return ERR_OK;
+}
+
+
+//=====================< NotaryInfo >======================================
+
+
+//============================================================
+// Returns the number of notary infos
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION int getCountOfNotaryInfos(const SignedDoc* pSigDoc)
+{
+ int n = 0, i = 0;
+ SignatureInfo* pSigInfo = 0;
+ RETURN_OBJ_IF_NULL(pSigDoc, -1);
+ for(i = 0; i < getCountOfSignatures(pSigDoc); i++) {
+ pSigInfo = getSignature(pSigDoc, i);
+ if(pSigInfo->pNotary)
+ n++;
+ }
+ return n;
+}
+
+//============================================================
+// Returns the next free notary id
+// pSigDoc - signed doc pointer
+//============================================================
+EXP_OPTION int getNextNotaryId(const SignedDoc* pSigDoc)
+{
+ int id = 0, n, i;
+ SignatureInfo* pSigInfo = 0;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, -1);
+ for(i = 0; i < getCountOfSignatures(pSigDoc); i++) {
+ pSigInfo = getSignature(pSigDoc, i);
+ if(pSigInfo->pNotary && pSigInfo->pNotary->szId) {
+ n = atoi(pSigInfo->pNotary->szId+1);
+ if(id <= n)
+ id = n+1;
+ }
+ }
+ return id;
+}
+
+//============================================================
+// Returns the desired NotaryInfo object
+// pSigDoc - signed doc pointer
+// nIdx - NotaryInfo index (starting with 0)
+//============================================================
+EXP_OPTION NotaryInfo* getNotaryInfo(const SignedDoc* pSigDoc, int nIdx)
+{
+ SignatureInfo* pSigInfo = 0;
+ NotaryInfo* pNotInfo = 0;
+ int n = 0, i = 0;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ for(i = 0; i < getCountOfSignatures(pSigDoc); i++) {
+ pSigInfo = getSignature(pSigDoc, i);
+ if(pSigInfo->pNotary) {
+ n++;
+ if(n == nIdx) {
+ pNotInfo = pSigInfo->pNotary;
+ break;
+ }
+ }
+ }
+ return pNotInfo;
+}
+
+//============================================================
+// Returns the last NotaryInfo object
+// pSigDoc - signed doc pointer
+// nIdx - NotaryInfo index (starting with 0)
+//============================================================
+EXP_OPTION NotaryInfo* ddocGetLastNotaryInfo(const SignedDoc* pSigDoc)
+{
+ SignatureInfo* pSigInfo;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ pSigInfo = ddocGetLastSignature(pSigDoc);
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ return pSigInfo->pNotary;
+}
+
+//============================================================
+// Returns the NotaryInfo object with the given id
+// pSigDoc - signed doc pointer
+// id - NotaryInfo id
+//============================================================
+EXP_OPTION NotaryInfo* getNotaryWithId(const SignedDoc* pSigDoc, const char* id)
+{
+ SignatureInfo* pSigInfo = 0;
+ int i = 0;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ for(i = 0; i < getCountOfSignatures(pSigDoc); i++) {
+ pSigInfo = getSignature(pSigDoc, i);
+ if(pSigInfo->pNotary && pSigInfo->pNotary->szId &&
+ !strcmp(pSigInfo->pNotary->szId, id)) {
+ return pSigInfo->pNotary;
+ }
+ }
+ return NULL;
+}
+
+//============================================================
+// Returns the NotaryInfo object that corresponds to the given signature
+// pSigDoc - signed doc pointer
+// id - NotaryInfo id
+//============================================================
+NotaryInfo* getNotaryWithSigId(const SignedDoc* pSigDoc, const char* sigId)
+{
+ SignatureInfo* pSigInfo = NULL;
+
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ RETURN_OBJ_IF_NULL(sigId, NULL);
+ pSigInfo = getSignatureWithId(pSigDoc, sigId);
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ return pSigInfo->pNotary;
+}
+
+//============================================================
+// Returns the NotaryInfo object that corresponds to the given signature
+// ore creates a new one
+// pSigDoc - signed doc pointer
+// id - SignatureInfo id
+//============================================================
+NotaryInfo* getOrCreateNotaryWithSigId(SignedDoc* pSigDoc, const char* sigId)
+{
+ NotaryInfo* pNotary = 0;
+ SignatureInfo* pSigInfo = 0;
+ RETURN_OBJ_IF_NULL(pSigDoc, NULL);
+ RETURN_OBJ_IF_NULL(sigId, NULL);
+ pNotary = getNotaryWithSigId(pSigDoc, sigId);
+ if(!pNotary) {
+ pSigInfo = getSignatureWithId(pSigDoc, sigId);
+ RETURN_OBJ_IF_NULL(pSigInfo, NULL);
+ NotaryInfo_new(&pNotary, pSigDoc, pSigInfo);
+ }
+ return pNotary;
+}
+
+
+//============================================================
+// Adds a new Notary element to a SignedDoc element and
+// initializes it partly
+// pSigInfo - signature object to be verified by this notary
+// return the newly created structure
+//============================================================
+EXP_OPTION int NotaryInfo_new(NotaryInfo **newNotaryInfo, SignedDoc* pSigDoc, SignatureInfo* pSigInfo)
+{
+ int n;
+ char buf[10];
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ // get next notary id
+ if (pSigInfo) {
+ strncpy(buf, pSigInfo->szId, sizeof(buf));
+ buf[0] = 'N';
+ // make sure we reset the szOrigContent on this signature
+ // otherwise the new confirmation will not be written to file!
+ ddocMemBuf_free(&(pSigInfo->mbufOrigContent));
+ } else {
+ n = getNextNotaryId(pSigDoc);
+ RETURN_IF_NOT(n >= 0, ERR_BAD_NOTARY_ID);
+ snprintf(buf, sizeof(buf), "N%d", n);
+ }
+ // memory management
+ pSigInfo->pNotary = (NotaryInfo*)malloc(sizeof(NotaryInfo)); // MEMLEAK: ???
+ if (!pSigInfo->pNotary)
+ RETURN_IF_BAD_ALLOC(pSigInfo->pNotary);
+ memset(pSigInfo->pNotary, 0, sizeof(NotaryInfo));
+ // set id
+ setString(&(pSigInfo->pNotary->szId), buf, -1);
+ // version
+ setString(&(pSigInfo->pNotary->szNotType), SK_NOT_VERSION, -1);
+
+ *newNotaryInfo = pSigInfo->pNotary;
+ return ERR_OK;
+}
+
+//============================================================
+// cleanup NotaryInfo memory
+// pNotary - object to be cleaned up
+//============================================================
+EXP_OPTION void NotaryInfo_free(NotaryInfo* pNotary)
+{
+ RETURN_VOID_IF_NULL(pNotary);
+ //assert(pNotary);
+ if(pNotary->szId)
+ free(pNotary->szId);
+ if(pNotary->szNotType)
+ free(pNotary->szNotType);
+ if(pNotary->timeProduced)
+ free(pNotary->timeProduced);
+ if(pNotary->szProducedAt)
+ free(pNotary->szProducedAt);
+ ddocMemBuf_free(&(pNotary->mbufRespId));
+ if(pNotary->szDigestType)
+ free(pNotary->szDigestType);
+ if(pNotary->szSigType)
+ free(pNotary->szSigType);
+ ddocMemBuf_free(&(pNotary->mbufOcspDigest));
+ ddocMemBuf_free(&(pNotary->mbufOcspResponse));
+ // free the object itself
+ free(pNotary);
+}
+
+//============================================================
+// Returns OCSP responders id as in XML document
+// pNotary - Notary info
+// return DigiDocMemBuf buffer pointer or NULL for error
+//============================================================
+EXP_OPTION const DigiDocMemBuf* ddocNotInfo_GetResponderId(const NotaryInfo* pNotary)
+{
+ RETURN_OBJ_IF_NULL(pNotary, NULL);
+ return &(pNotary->mbufRespId);
+}
+
+//============================================================
+// Returns OCSP responders id value as string
+// pNotary - Notary info
+// return responder id value or NULL
+//============================================================
+EXP_OPTION const char* ddocNotInfo_GetResponderId_Value(const NotaryInfo* pNotary)
+{
+ RETURN_OBJ_IF_NULL(pNotary, NULL);
+ return (const char*)pNotary->mbufRespId.pMem;
+}
+
+//============================================================
+// Sets OCSP responders id as in XML document
+// pNotary - Notary info
+// data - new responder id value
+// len - length of value
+// return DigiDocMemBuf buffer pointer or NULL for error
+//============================================================
+int ddocNotInfo_SetResponderId(NotaryInfo* pNotary, const char* data, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(data);
+ err = ddocMemAssignData(&(pNotary->mbufRespId), data, len);
+ return err;
+}
+
+//============================================================
+// Returns OCSP response as memory buffer
+// pNotary - Notary info
+// return DigiDocMemBuf buffer pointer or NULL for error
+//============================================================
+const DigiDocMemBuf* ddocNotInfo_GetOCSPResponse(const NotaryInfo* pNotary)
+{
+ RETURN_OBJ_IF_NULL(pNotary, NULL);
+ return &(pNotary->mbufOcspResponse);
+}
+
+//============================================================
+// Retrieves OCSP responses responder id type and value
+// pResp - OCSP response
+// pType - buffer for type
+// pMbufRespId - responder id
+// returns error code or ERR_OK
+//============================================================
+int ddocGetOcspRespIdTypeAndValue(OCSP_RESPONSE* pResp,
+ int *pType, DigiDocMemBuf* pMbufRespId)
+{
+ int err = ERR_OK;
+ OCSP_BASICRESP *br = NULL;
+
+ RETURN_IF_NULL_PARAM(pResp);
+ RETURN_IF_NULL_PARAM(pType);
+ RETURN_IF_NULL_PARAM(pMbufRespId);
+ if((br = OCSP_response_get1_basic(pResp)) == NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_BASIC_RESP);
+ if(!err && br) {
+ switch(br->tbsResponseData->responderId->type) {
+ case V_OCSP_RESPID_NAME:
+ *pType = RESPID_NAME_TYPE;
+ ddocMemSetLength(pMbufRespId, 300);
+ //X509_NAME_oneline(br->tbsResponseData->responderId->value.byName, (char*)pMbufRespId->pMem, pMbufRespId->nLen);
+ //AM 26.09.08
+ err = ddocCertGetDNFromName(br->tbsResponseData->responderId->value.byName, pMbufRespId);
+ //RETURN_IF_NOT(err == ERR_OK, err);
+ break;
+ case V_OCSP_RESPID_KEY:
+ *pType = RESPID_KEY_TYPE;
+ err = ddocMemAssignData(pMbufRespId,
+ (const char*)br->tbsResponseData->responderId->value.byKey->data,
+ br->tbsResponseData->responderId->value.byKey->length);
+ break;
+ default:
+ SET_LAST_ERROR(ERR_OCSP_WRONG_RESPID);
+ }
+ }
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return err;
+}
+
+//============================================================
+// Sets OCSP respondese value as in XML document. Must pass in
+// binary DER data!
+// pNotary - Notary info
+// data - new responder id value
+// len - length of value
+// return DigiDocMemBuf buffer pointer or NULL for error
+//============================================================
+int ddocNotInfo_SetOCSPResponse(NotaryInfo* pNotary, const char* data, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(data);
+ err = ddocMemAssignData(&(pNotary->mbufOcspResponse), data, len);
+ return err;
+}
+
+//============================================================
+// Returns OCSP response value
+// pNotary - Notary info
+// return OCSP_RESPONSE pointer or NULL for error. Caller must
+// use OCSP_RESPONSE_free() to release it.
+//============================================================
+OCSP_RESPONSE* ddocNotInfo_GetOCSPResponse_Value(const NotaryInfo* pNotary)
+{
+ OCSP_RESPONSE* pResp = NULL;
+
+ RETURN_OBJ_IF_NULL(pNotary, NULL);
+ RETURN_OBJ_IF_NULL(pNotary->mbufOcspResponse.pMem, NULL);
+ ddocOcspReadOcspResp(&pResp, (DigiDocMemBuf*)&(pNotary->mbufOcspResponse));
+ return pResp;
+}
+
+//============================================================
+// Sets OCSP respondese value. Must pass in real OCSP_RESPONSE
+// pNotary - Notary info
+// data - new responder id value
+// len - length of value
+// return DigiDocMemBuf buffer pointer or NULL for error
+//============================================================
+int ddocNotInfo_SetOCSPResponse_Value(NotaryInfo* pNotary, OCSP_RESPONSE* pResp)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pResp);
+ err = ddocOcspWriteOcspResp(pResp, (DigiDocMemBuf*)&(pNotary->mbufOcspResponse));
+ return err;
+}
+
+//============================================================
+// Helper function to get OCSP response parts
+// pNotary - notary object
+// ppResp - adr for OCSP_RESPONSE - must free!
+// ppBasResp - adr for OCSP_BASICRESP - don't free
+// ppSingle - optional adr for OCSP_SINGLERESP - don't free
+//============================================================
+int ddocNotInfo_GetBasicResp(const NotaryInfo* pNotary, OCSP_RESPONSE **ppResp,
+ OCSP_BASICRESP **ppBasResp, OCSP_SINGLERESP **ppSingle)
+{
+ int err = ERR_OK;
+
+ // check input
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(ppResp);
+ RETURN_IF_NULL_PARAM(ppBasResp);
+ // single response retrieval is optional - don't check it
+ *ppResp = ddocNotInfo_GetOCSPResponse_Value(pNotary);
+ if(*ppResp && ppBasResp) {
+ *ppBasResp = OCSP_response_get1_basic(*ppResp);
+ if(*ppBasResp) {
+ if(ppSingle)
+ *ppSingle = sk_OCSP_SINGLERESP_value((*ppBasResp)->tbsResponseData->responses, 0);
+ }
+ else
+ return ERR_OCSP_NO_BASIC_RESP;
+ }
+ return err;
+}
+
+//============================================================
+// Returns OCSP responders id type as string
+// pNotary - Notary info
+// return responder id type or NULL. DO NOT free() it!
+//============================================================
+EXP_OPTION const char* ddocNotInfo_GetResponderId_Type(const NotaryInfo* pNotary)
+{
+ int err = ERR_OK;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+ char *p1 = RESPID_NAME_VALUE; // default value is name - usefull in format 1.0 where we had no good OCSP response
+
+ RETURN_OBJ_IF_NULL(pNotary, NULL);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, NULL);
+ if(!err && br) {
+ switch(br->tbsResponseData->responderId->type) {
+ case V_OCSP_RESPID_NAME: p1 = RESPID_NAME_VALUE; break;
+ case V_OCSP_RESPID_KEY: p1 = RESPID_KEY_VALUE; break;
+ default:
+ SET_LAST_ERROR(ERR_OCSP_WRONG_RESPID);
+ }
+ }
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ // PR. leak found
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return p1;
+}
+
+//============================================================
+// Returns OCSP responses thisUpdate atribute as string
+// pNotary - Notary info
+// pMBuf - buffer for thisUpdate value
+// return error code OR ERR_OK.
+//============================================================
+EXP_OPTION int ddocNotInfo_GetThisUpdate(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf)
+{
+ int err = ERR_OK;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+ OCSP_SINGLERESP *single = NULL;
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pMBuf);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single);
+ if(!err && br && single) {
+ err = ddocMemSetLength(pMBuf, 50);
+ ddocDebug(3, "ddocNotInfo_GetThisUpdate", "This update: %s", single->thisUpdate);
+ if(!err && single->thisUpdate)
+ err = asn1time2str(NULL, single->thisUpdate, (char*)pMBuf->pMem, pMBuf->nLen);
+ }
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ // PR. leak found
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return err;
+}
+
+
+//============================================================
+// Returns OCSP responses thisUpdate atribute as time_t
+// pNotary - Notary info
+// pTime - address of time_t variable
+// return error code OR ERR_OK.
+//============================================================
+int ddocNotInfo_GetThisUpdate_timet(const NotaryInfo* pNotary, time_t* pTime)
+{
+ int err = ERR_OK;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+ OCSP_SINGLERESP *single = NULL;
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pTime);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single);
+ if(!err && br && single) {
+ if(!err && single->thisUpdate)
+ err = asn1time2time_t_local(single->thisUpdate, pTime);
+ }
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ // PR. leak found
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return err;
+}
+
+//============================================================
+// Returns OCSP responses producedAt atribute as time_t
+// pNotary - Notary info
+// pTime - address of time_t variable
+// return error code OR ERR_OK.
+//============================================================
+int ddocNotInfo_GetProducedAt_timet(const NotaryInfo* pNotary, time_t* pTime)
+{
+ int err = ERR_OK;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pTime);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, NULL);
+ if(!err && br && br->tbsResponseData && br->tbsResponseData->producedAt) {
+ err = asn1time2time_t_local(br->tbsResponseData->producedAt, pTime);
+ }
+ //AM 22.06.08 lets free br too
+ if(br)
+ OCSP_BASICRESP_free(br);
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ return err;
+}
+
+//============================================================
+// Returns OCSP responses producedAt from xml as time_t
+// pNotary - Notary info
+// pTime - address of time_t variable
+// return error code OR ERR_OK.
+//============================================================
+int ddocNotInfo_GetProducedAtXml_timet(const NotaryInfo* pNotary, time_t* pTime)
+{
+ int err = ERR_OK;
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pTime);
+ if(!err && pNotary->szProducedAt) {
+ err = str2time_t(pNotary->szProducedAt, pTime);
+ }
+ return err;
+}
+
+//============================================================
+// Returns OCSP responses nextUpdate atribute as string
+// pNotary - Notary info
+// pMBuf - buffer for nextUpdate value
+// return error code OR ERR_OK.
+//============================================================
+EXP_OPTION int ddocNotInfo_GetNextUpdate(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf)
+{
+ int err = ERR_OK;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+ OCSP_SINGLERESP *single = NULL;
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pMBuf);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single);
+ if(!err && br && single) {
+ err = ddocMemSetLength(pMBuf, 50);
+ if(!err && single->nextUpdate)
+ err = asn1time2str(NULL, single->nextUpdate, (char*)pMBuf->pMem, pMBuf->nLen);
+ }
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ // PR. leak found
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return err;
+}
+
+//============================================================
+// Returns OCSP responses IssuerNameHash atribute
+// pNotary - Notary info
+// pMBuf - buffer for IssuerNameHash value
+// return error code OR ERR_OK.
+//============================================================
+int ddocNotInfo_GetIssuerNameHash(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf)
+{
+ int err = ERR_OK;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+ OCSP_SINGLERESP *single = NULL;
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pMBuf);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single);
+ if(!err && br && single->certId) {
+ err = ddocMemAssignData(pMBuf, (const char*)single->certId->issuerNameHash->data,
+ single->certId->issuerNameHash->length);
+ }
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ // PR. leak found
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return err;
+}
+
+//============================================================
+// Returns OCSP responses IssuerKeyHash atribute
+// pNotary - Notary info
+// pMBuf - buffer for IssuerKeyHash value
+// return error code OR ERR_OK.
+//============================================================
+int ddocNotInfo_GetIssuerKeyHash(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf)
+{
+ int err = ERR_OK;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+ OCSP_SINGLERESP *single = NULL;
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pMBuf);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single);
+ if(!err && br && single->certId) {
+ err = ddocMemAssignData(pMBuf, (const char*)single->certId->issuerKeyHash->data,
+ single->certId->issuerKeyHash->length);
+ }
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ // PR. leak found
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return err;
+}
+
+//============================================================
+// Returns OCSP responses real digest from response data
+// pNotary - Notary info
+// pMBuf - buffer for digest value
+// return error code OR ERR_OK.
+//============================================================
+int ddocNotInfo_GetOcspRealDigest(const SignedDoc* pSigDoc, const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf)
+{
+ int err = ERR_OK, nIdx = 0, l1 = 0, l2 = 0, nCheckOcspLen = 0;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+ OCSP_SINGLERESP *single = NULL;
+ X509_EXTENSION *ext = NULL;
+ byte* p = 0, buf2[DIGEST_LEN256 * 2 + 2];
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pMBuf);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single);
+ nCheckOcspLen = ConfigItem_lookup_bool("CHECK_OCSP_NONCE", 0);
+ if(!err && br) {
+ nIdx = OCSP_BASICRESP_get_ext_by_NID(br, NID_id_pkix_OCSP_Nonce, -1);
+ if(nIdx >= 0) {
+ ext = OCSP_BASICRESP_get_ext(br, nIdx);
+ if(ext != NULL) {
+ int l1 = ASN1_STRING_length(ext->value);
+ p = ASN1_STRING_data(ext->value);
+ if(l1 > 20 && p[0] == V_ASN1_OCTET_STRING && p[1] == l1-2)
+ err = ddocMemAssignData(pMBuf, (const char*)p+2, l1-2);
+ else
+ err = ddocMemAssignData(pMBuf, (const char*)p, l1);
+ // debug
+ l2 = sizeof(buf2);
+ memset(buf2, 0, l2);
+ if(l1 <= DIGEST_LEN256) {
+ bin2hex((const byte*)p, l1, (byte*)buf2, &l2);
+ ddocDebug(3, "ddocNotInfo_GetOcspRealDigest", "Not: %s nonce: %s len: %d err: %d",
+ pNotary->szId, buf2, l1, err);
+ }
+ if(l1 != 22 && nCheckOcspLen && pSigDoc && strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) {
+ ddocDebug(1, "ddocNotInfo_GetOcspRealDigest", "Not: %s invalid nonce: %s len: %d err: %d",
+ pNotary->szId, buf2, l1, err);
+ err = ERR_OCSP_NONCE_INVALID;
+ }
+ }
+ }
+ else
+ err = ERR_OCSP_NO_NONCE;
+ }
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return err;
+}
+
+//============================================================
+// Returns OCSP responses signature value
+// pNotary - Notary info
+// pMBuf - buffer for signature value
+// return error code OR ERR_OK.
+//============================================================
+int ddocNotInfo_GetOcspSignatureValue(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf)
+{
+ int err = ERR_OK;
+ OCSP_RESPONSE *pResp = 0;
+ OCSP_BASICRESP *br = NULL;
+
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(pMBuf);
+ err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, NULL);
+ if(!err && br) {
+ err = ddocMemAssignData(pMBuf, (const char*)br->signature->data,
+ br->signature->length);
+ }
+ if(pResp)
+ OCSP_RESPONSE_free(pResp);
+ // PR. leak found
+ if(br)
+ OCSP_BASICRESP_free(br);
+ return err;
+}
+
+//============================================================
+// Returns OCSP response digest as in XML document
+// pNotary - Notary info
+// return DigiDocMemBuf buffer pointer or NULL for error
+//============================================================
+EXP_OPTION const DigiDocMemBuf* ddocNotInfo_GetOcspDigest(const NotaryInfo* pNotary)
+{
+ RETURN_OBJ_IF_NULL(pNotary, NULL);
+ return &(pNotary->mbufOcspDigest);
+}
+
+//============================================================
+// Sets OCSP response digest id as in XML document
+// pNotary - Notary info
+// data - new digest value
+// len - length of value
+// return DigiDocMemBuf buffer pointer or NULL for error
+//============================================================
+int ddocNotInfo_SetOcspDigest(NotaryInfo* pNotary, const char* data, long len)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pNotary);
+ RETURN_IF_NULL_PARAM(data);
+ err = ddocMemAssignData(&(pNotary->mbufOcspDigest), data, len);
+ return err;
+}
+
+
+
+//============================================================
+// Adds a certificate to Notary and initializes Notary
+// pNotary - Notary info
+// cert - responders certificate
+// return error code
+//============================================================
+int addNotaryInfoCert(SignedDoc *pSigDoc, NotaryInfo *pNotary, X509 *cert)
+{
+ int err = ERR_OK, n;
+ char buf[300];
+ CertID* pCertID = 0;
+ SignatureInfo* pSigInfo = 0;
+ DigiDocMemBuf mbuf1;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ ddocDebug(3, "addNotaryInfoCert", "adding cert: %s to notary: %s", (cert ? "OK" : "NULL"), pNotary->szId);
+ RETURN_IF_NULL_PARAM(pNotary);
+ pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotary);
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ if(!ddocSigInfo_GetOCSPRespondersCert(pSigInfo))
+ err = ddocSigInfo_SetOCSPRespondersCert(pSigInfo, cert);
+ buf[0] = 0;
+ err = ReadCertSerialNumber(buf, sizeof(buf), cert);
+ if(strlen(buf)){
+ pCertID = ddocCertIDList_GetCertIDOfSerial(pSigInfo->pCertIDs, buf);
+ }
+ if(!pCertID)
+ pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSigInfo, CERTID_TYPE_RESPONDERS_CERTID);
+ else //AM quick fix for smartlink bdoc
+ if(pCertID->nType==0)pCertID->nType = CERTID_TYPE_RESPONDERS_CERTID;
+ RETURN_IF_NULL(pCertID);
+ ddocCertID_SetIssuerSerial(pCertID, buf);
+ n = sizeof(buf);
+ memset(buf, 0, sizeof(buf));
+ n = 40;
+ RETURN_IF_NOT(X509_digest(cert, EVP_sha1(), (unsigned char*)buf, (unsigned int*)&n), ERR_X509_DIGEST);
+ if(!pCertID->pDigestValue)
+ ddocCertID_SetDigestValue(pCertID, (const char*)buf, n);
+ ddocCertGetSubjectDN(cert, &mbuf1);
+ ddocCertID_SetIssuerName(pCertID, (char*)mbuf1.pMem);
+ ddocMemBuf_free(&mbuf1);
+ snprintf(buf, sizeof(buf), "%s-RESPONDER_CERTINFO", pSigInfo->szId);
+ ddocCertID_SetId(pCertID, buf);
+ ddocDebug(4, "addNotaryInfoCert", "cert: %s to notary: %s", (cert ? "OK" : "NULL"), pNotary->szId, err);
+ return err;
+}
+
+
+//============================================================
+// Removes Notary cert value and id after unsucessful verification attempt
+// pSigInfo - signature info [REQUIRED]
+// return error code
+//============================================================
+int removeNotaryInfoCert(SignatureInfo* pSigInfo)
+{
+ CertID* pCertID;
+ CertValue* pCertVal;
+ int i;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ // remove cert values of type responder
+ for(i = 0; i < ddocCertValueList_GetCertValuesCount(pSigInfo->pCertValues); i++) {
+ pCertVal = ddocCertValueList_GetCertValue(pSigInfo->pCertValues, i);
+ if(pCertVal && pCertVal->nType == CERTID_VALUE_RESPONDERS_CERT)
+ ddocCertValueList_DeleteCertValue(pSigInfo->pCertValues, i);
+ }
+ // remove cert ids of type responder
+ for(i = 0; i < ddocCertIDList_GetCertIDsCount(pSigInfo->pCertIDs); i++) {
+ pCertID = ddocCertIDList_GetCertID(pSigInfo->pCertIDs, i);
+ if(pCertID && pCertID->nType == CERTID_TYPE_RESPONDERS_CERTID)
+ ddocCertIDList_DeleteCertID(pSigInfo->pCertIDs, i);
+ }
+ return ERR_OK;
+}
+
+//============================================================
+// Adds a new Notary SignedInfo element to a SignedDoc
+// element and initializes it
+// newNotaryInfo - newly created structure
+// pSigDoc - signed doc data
+// pSigInfo - signature object to be verified by this notary
+// ocspRespFile - OCSP response file name
+// notaryCertFile - Notary cert file name
+// returns error code or ERR_OK if no error.
+//============================================================
+// FIXME : What to do if initializeNotaryInfoWithOCSP fails?
+EXP_OPTION int NotaryInfo_new_file(NotaryInfo **newNotaryInfo, SignedDoc *pSigDoc,
+ const SignatureInfo *pSigInfo, const char *ocspRespFile,
+ const char *notaryCertFile)
+
+{
+ OCSP_RESPONSE* resp;
+ X509* notCert;
+ NotaryInfo* pNotInf = NULL;
+ int err = ERR_OK;
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(ocspRespFile);
+ RETURN_IF_NULL_PARAM(notaryCertFile);
+ err = ReadOCSPResponse(&resp, ocspRespFile);
+ RETURN_IF_NOT(err == ERR_OK, ERR_FILE_READ);
+ err = ReadCertificate(&notCert, notaryCertFile);
+ RETURN_IF_NOT(err == ERR_OK, ERR_CERT_READ);
+ err = NotaryInfo_new(&pNotInf, pSigDoc, (SignatureInfo*)pSigInfo);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ *newNotaryInfo = pNotInf;
+ err = initializeNotaryInfoWithOCSP(pSigDoc, pNotInf, resp, notCert, 1);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ return ERR_OK;
+}
+
+// forward deklaratsioon
+int notary2ocspBasResp(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo, X509* notCert, OCSP_BASICRESP** pBasResp);
+int calculateOcspBasicResponseDigest(OCSP_BASICRESP* pBsResp, byte* digBuf, int* digLen);
+
+//============================================================
+// Calculates the digest of NotaryInfo
+// pSigDoc - signed document pointer
+// pNotInfo - notary signature info
+// digBuf - signature buffer
+// digLen - signature buffer length
+// returns error code
+//============================================================
+EXP_OPTION int calculateNotaryInfoDigest(const SignedDoc* pSigDoc,
+ const NotaryInfo* pNotInfo, byte* digBuf, int* digLen)
+{
+ SignatureInfo* pSigInfo;
+ int err = ERR_OK;
+ const DigiDocMemBuf *pMBuf = 0;
+
+ pMBuf = ddocNotInfo_GetOCSPResponse(pNotInfo);
+ RETURN_IF_NULL(pMBuf);
+ pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotInfo);
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ if(!strcmp(pNotInfo->szDigestType,DIGEST_SHA256_NAME))
+ err = calculateDigest((const byte*)pMBuf->pMem, pMBuf->nLen, DIGEST_SHA256, digBuf, digLen);
+ else
+ err = calculateDigest((const byte*)pMBuf->pMem, pMBuf->nLen, DIGEST_SHA1, digBuf, digLen);
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+//AM 12.03.08
+//--------------------------------------------------
+// Sets the CA Responders certificate
+// pSigInfo - signature info object [REQUIRED]
+// pCert - certificate [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocSigInfo_SetCACert(SignatureInfo* pSigInfo, X509* pCert)
+{
+ int err = ERR_OK;
+ CertValue *pCertValue = 0;
+ char buf1[50];
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(pCert);
+ pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_CA_CERT);
+ if(pCertValue) {
+ snprintf(buf1, sizeof(buf1), "%s-CA_CERT", pSigInfo->szId);
+ err = ddocCertValue_SetId(pCertValue, buf1);
+ if(!err)
+ err = ddocCertValue_SetCert(pCertValue, pCert);
+ }
+ return err;
+}
+
+//============================================================
+// Calculates and stores a signature for this SignatureInfo object
+// Uses PKCS#12 file to sign the info
+// pSigInfo - signature info object
+// nSigType - signature type code
+// szPkcs12File - PKCS#12 file
+// passwd - key password
+//============================================================
+EXP_OPTION int calculateSignatureWithPkcs12(SignedDoc* pSigDoc, SignatureInfo* pSigInfo,
+ const char* szPkcs12File, const char* passwd)
+{
+ int err = ERR_OK;
+ int sigLen;
+ char sigDig[100];
+ char signature[256];
+ char* buf1;
+ int l2;
+ EVP_PKEY *pkey = 0;
+ X509* x509 = 0;
+ EVP_MD_CTX ctx;
+ DigiDocMemBuf mbuf1;
+
+ RETURN_IF_NULL_PARAM(pSigInfo);
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ RETURN_IF_NULL_PARAM(szPkcs12File);
+ ddocDebug(3, "calculateSignatureWithPkcs12", "Keystore: %s passwd-len: %d",
+ szPkcs12File, (passwd ? strlen(passwd) : 0));
+ // read pkcs12 file
+ err = ReadCertificateByPKCS12(&x509, szPkcs12File, passwd, &pkey);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ // try key-usage check
+ if(ConfigItem_lookup_int("KEY_USAGE_CHECK", 1) && x509) {
+ if(!ddocCertCheckKeyUsage(x509, KUIDX_NON_REPUDIATION)) {
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+ SET_LAST_ERROR(ERR_SIGNERS_CERT_NON_REPU);
+ return ERR_SIGNERS_CERT_NON_REPU;
+ }
+ }
+ // set signers cert
+ setSignatureCert(pSigInfo, x509);
+ // create signing timestamp
+ createTimestamp(pSigDoc, (char*)sigDig, sizeof(sigDig));
+ setString((char**)&(pSigInfo->szTimeStamp), (const char*)sigDig, -1);
+ // Signed properties digest
+ buf1 = createXMLSignedProperties(pSigDoc, pSigInfo, 0);
+ mbuf1.pMem = canonicalizeXML((char*)buf1, strlen(buf1));
+ mbuf1.nLen = strlen((const char*)mbuf1.pMem);
+ ddocDebugWriteFile(4, "sigprop-signed.txt", &mbuf1);
+ l2 = sizeof(sigDig);
+ err = calculateDigest((const byte*)mbuf1.pMem, mbuf1.nLen, DIGEST_SHA1, sigDig, &l2);
+ free(buf1);
+ ddocMemBuf_free(&mbuf1);
+ if (err != ERR_OK) {
+ SET_LAST_ERROR(err);
+ return err;
+ }
+ ddocSigInfo_SetSigPropDigest(pSigInfo, (const char*)sigDig, l2);
+ ddocSigInfo_SetSigPropRealDigest(pSigInfo, (const char*)sigDig, l2);
+ // create signed info
+ buf1 = createXMLSignedInfo(pSigDoc, pSigInfo);
+ if (!buf1) {
+ err = ERR_NULL_POINTER;
+ SET_LAST_ERROR(err);
+ return err ;
+ }
+ mbuf1.pMem = buf1; //canonicalizeXML((char*)buf1, strlen(buf1));
+ mbuf1.nLen = strlen((const char*)mbuf1.pMem);
+ //ddocDebugWriteFile(4, "siginf-signed.txt", &mbuf1);
+ // get digest
+ l2 = sizeof(sigDig);
+ err = calculateDigest((const byte*)buf1, strlen(buf1), DIGEST_SHA1, (byte*)sigDig, &l2);
+ // debug
+ sigLen = sizeof(signature);
+ bin2hex((const byte*)sigDig, l2, (char*)signature, &sigLen);
+ sigLen = sizeof(signature);
+ encode((const byte*)sigDig, l2, (char*)signature, &sigLen);
+ ddocDebug(3, "calculateSignatureWithPkcs12", "Sig-inf hash b64: %s", signature);
+ if (err != ERR_OK) {
+ err = ERR_NULL_POINTER;
+ SET_LAST_ERROR(err);
+ return err;
+ }
+ ddocSigInfo_SetSigInfoRealDigest(pSigInfo, (const char*)sigDig, l2);
+ // sign data
+ sigLen = sizeof(signature);
+ memset(signature, 0, sizeof(signature));
+ // sign data
+ EVP_SignInit(&ctx, EVP_sha1());
+ EVP_SignUpdate(&ctx, buf1, (unsigned long)strlen(buf1));
+ err = EVP_SignFinal(&ctx, signature, &sigLen, pkey);
+ free(buf1);
+ if(err == ERR_LIB_NONE)
+ err = ERR_OK;
+ // set signature value
+ ddocSigInfo_SetSignatureValue(pSigInfo, (const char*)signature, (int)sigLen);
+ ddocDebug(3, "calculateSignatureWithPkcs12", "Sig-len: %ld", sigLen);
+ //X509_free(x509);
+ EVP_PKEY_free(pkey);
+
+ return err;
+}
+
+