summaryrefslogtreecommitdiff
path: root/libdigidoc/DigiDocEnc.c
diff options
context:
space:
mode:
authorAndrew Shadura <andrewsh@debian.org>2015-11-01 19:41:28 +0100
committerAndrew Shadura <andrewsh@debian.org>2015-11-01 19:41:28 +0100
commit61c1a106bd81794f48e4cd85bae129f9270279e8 (patch)
tree29ecf644c4a13c2645bd8067e66ae8944dd2daf9 /libdigidoc/DigiDocEnc.c
libdigidoc (3.10.1.1208-1) unstable; urgency=medium
* Initial upload (Closes: #658300). # imported from the archive
Diffstat (limited to 'libdigidoc/DigiDocEnc.c')
-rw-r--r--libdigidoc/DigiDocEnc.c2743
1 files changed, 2743 insertions, 0 deletions
diff --git a/libdigidoc/DigiDocEnc.c b/libdigidoc/DigiDocEnc.c
new file mode 100644
index 0000000..60752aa
--- /dev/null
+++ b/libdigidoc/DigiDocEnc.c
@@ -0,0 +1,2743 @@
+//==================================================
+// FILE: DigiDocEnc.c
+// PROJECT: Digi Doc Encryption
+// DESCRIPTION: DigiDocEnc structure admin functions
+// 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 >=============================
+// 15.09.2004 Veiko Sinivee
+// Creation
+//==================================================
+
+// config data comes from there
+#ifndef WIN32
+ #if HAVE_CONFIG_H
+ #include <config.h>
+ #endif
+#endif // no win32
+
+#include <libdigidoc/DigiDocDefs.h>
+#include <libdigidoc/DigiDocEnc.h>
+#include <libdigidoc/DigiDocEncGen.h>
+#include <libdigidoc/DigiDocError.h>
+#include <libdigidoc/DigiDocDebug.h>
+#include <libdigidoc/DigiDocPKCS11.h>
+#include <libdigidoc/DigiDocConvert.h>
+#include <libdigidoc/DigiDocCert.h>
+#include <libdigidoc/DigiDocMem.h>
+
+#include <openssl/sha.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <zlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+
+//======================< DEncEncryptedData >==============================
+
+
+//--------------------------------------------------
+// Validates the <EncryptionMethod> parameter. We
+// currently support only AES-128-CBC.
+// szEncMethod - value to be checked
+// returns error code or ERR_OK
+//--------------------------------------------------
+int dencEncDataValidateEncMethod(const char* szEncMethod)
+{
+ if(szEncMethod && strcmp(szEncMethod, DENC_ENC_METHOD_AES128))
+ SET_LAST_ERROR_RETURN(ERR_DENC_ENC_METHOD, ERR_DENC_ENC_METHOD)
+ else
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Validates the XML namespace parameter. We
+// currently support only
+// szEncMethod - value to be checked
+// returns error code or ERR_OK
+//--------------------------------------------------
+int dencValidateEncXmlNs(const char* szXmlNs)
+{
+ if(szXmlNs && strcmp(szXmlNs, DENC_XMLNS_XMLENC))
+ SET_LAST_ERROR_RETURN(ERR_DENC_ENC_XMLNS, ERR_DENC_ENC_XMLNS)
+ else
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// "Constructor" of DEncEncryptedData object
+// pEncData - address of buffer for newly allocated object [REQUIRED]
+// szXmlNs - XML namespace uri
+// szEncMethod - encyrption method algorithm uri
+// szId - elements Id attribute [OPTIONAL]
+// szType - elements type atribute [OPTIONAL]
+// szMimeType - elements mime-type attribute [OPTIONAL]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_new(DEncEncryptedData** pEncData,
+ const char* szXmlNs, const char* szEncMethod,
+ const char* szId, const char* szType,
+ const char* szMimeType)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(3, "dencEncryptedData_new", "EncMethod: %s, Id: %s, type: %s, mime: %s",
+ szEncMethod, szId, szType, szMimeType);
+ RETURN_IF_NULL_PARAM(pEncData);
+ err = dencEncDataValidateEncMethod(szEncMethod);
+ if(err) return err;
+ err = dencValidateEncXmlNs(szXmlNs);
+ if(err) return err;
+ *pEncData = (DEncEncryptedData*)malloc(sizeof(DEncEncryptedData));
+ // allocate new object
+ RETURN_IF_BAD_ALLOC(*pEncData);
+ memset(*pEncData, 0, sizeof(DEncEncryptedData));
+ // set required fields
+ if(szXmlNs) {
+ err = ddocMemAssignString((char**)&((*pEncData)->szXmlNs), szXmlNs);
+ if(err) return err;
+ }
+ if(szEncMethod) {
+ err = ddocMemAssignString((char**)&((*pEncData)->szEncryptionMethod), szEncMethod);
+ if(err) return err;
+ }
+ // set optional fields
+ if(szId) {
+ err = ddocMemAssignString((char**)&((*pEncData)->szId), szId);
+ if(err) return err;
+ }
+ if(szType) {
+ err = ddocMemAssignString((char**)&((*pEncData)->szType), szType);
+ if(err) return err;
+ }
+ if(szMimeType) {
+ err = ddocMemAssignString((char**)&((*pEncData)->szMimeType), szMimeType);
+ if(err) return err;
+ }
+ // set meta info carrying lib & document format versions
+ dencMetaInfo_SetLibVersion(*pEncData);
+ dencMetaInfo_SetFormatVersion(*pEncData);
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" of DEncEncryptedData object
+// pEncData - address of object to be deleted [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_free(DEncEncryptedData* pEncData)
+{
+ int i, err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ // cleanup this object
+ if(pEncData->szId)
+ free(pEncData->szId);
+ if(pEncData->szType)
+ free(pEncData->szType);
+ if(pEncData->szMimeType)
+ free(pEncData->szMimeType);
+ if(pEncData->szEncryptionMethod)
+ free(pEncData->szEncryptionMethod);
+ if(pEncData->szXmlNs)
+ free(pEncData->szXmlNs);
+ // cleanup child objects
+ ddocMemBuf_free(&(pEncData->mbufEncryptedData));
+ if(pEncData->encProperties.szId)
+ free(pEncData->encProperties.szId);
+ for(i = 0; i < pEncData->encProperties.nEncryptionProperties; i++) {
+ if(pEncData->encProperties.arrEncryptionProperties[i]) {
+ err = dencEncryptionProperty_free(pEncData->encProperties.arrEncryptionProperties[i]);
+ if(err) return err;
+ }
+ }
+ if(pEncData->encProperties.arrEncryptionProperties)
+ free(pEncData->encProperties.arrEncryptionProperties);
+ ddocMemBuf_free(&(pEncData->mbufTransportKey));
+ for(i = 0; i < pEncData->nEncryptedKeys; i++) {
+ if(pEncData->arrEncryptedKeys[i]) {
+ err = dencEncryptedKey_free(pEncData->arrEncryptedKeys[i]);
+ if(err) return err;
+ }
+ }
+ free(pEncData->arrEncryptedKeys);
+ free(pEncData);
+ return err;
+}
+
+
+//======================< DEncEncryptedData - accessors >===================
+
+
+//--------------------------------------------------
+// Accessor for Id atribute of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedData_GetId(DEncEncryptedData* pEncData)
+{
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ return pEncData->szId;
+}
+
+//--------------------------------------------------
+// Accessor for Type atribute of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedData_GetType(DEncEncryptedData* pEncData)
+{
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ return pEncData->szType;
+}
+
+//--------------------------------------------------
+// Accessor for MimeType atribute of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedData_GetMimeType(DEncEncryptedData* pEncData)
+{
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ return pEncData->szMimeType;
+}
+
+//--------------------------------------------------
+// Accessor for xmlns atribute of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedData_GetXmlNs(DEncEncryptedData* pEncData)
+{
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ return pEncData->szXmlNs;
+}
+
+//--------------------------------------------------
+// Accessor for EncryptionMethod subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedData_GetEncryptionMethod(DEncEncryptedData* pEncData)
+{
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ return pEncData->szEncryptionMethod;
+}
+
+//--------------------------------------------------
+// Accessor for Id atribute of EncryptionProperties subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedData_GetEncryptionPropertiesId(DEncEncryptedData* pEncData)
+{
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ return pEncData->encProperties.szId;
+}
+
+//--------------------------------------------------
+// Accessor for count of EncryptionProperties subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns count or -1 for error. Then use error API to check errors
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_GetEncryptionPropertiesCount(DEncEncryptedData* pEncData)
+{
+ SET_LAST_ERROR_RETURN_IF_NOT(pEncData, ERR_NULL_POINTER, -1)
+ return pEncData->encProperties.nEncryptionProperties;
+}
+
+//--------------------------------------------------
+// Accessor for EncryptionProperties subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// nIdx - index of EncryptionProperty object [REQUIRED]
+// returns EncryptionProperty pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION DEncEncryptionProperty* dencEncryptedData_GetEncryptionProperty(DEncEncryptedData* pEncData, int nIdx)
+{
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->encProperties.nEncryptionProperties, ERR_DENC_BAD_PROP_IDX, NULL);
+ RETURN_OBJ_IF_NULL(pEncData->encProperties.arrEncryptionProperties[nIdx], 0);
+ return pEncData->encProperties.arrEncryptionProperties[nIdx];
+}
+
+//--------------------------------------------------
+// Finds EncryptionProperty by Name atribute
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// name - name of searched property
+// returns EncryptionProperty pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION DEncEncryptionProperty* dencEncryptedData_FindEncryptionPropertyByName(DEncEncryptedData* pEncData, const char* name)
+{
+ DEncEncryptionProperty* pEncProp = 0;
+ int i;
+
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ RETURN_OBJ_IF_NULL(name, NULL)
+ for(i = 0; i < pEncData->encProperties.nEncryptionProperties; i++) {
+ if(pEncData->encProperties.arrEncryptionProperties[i] &&
+ pEncData->encProperties.arrEncryptionProperties[i]->szName &&
+ !strcmp(pEncData->encProperties.arrEncryptionProperties[i]->szName, name)) {
+ pEncProp = pEncData->encProperties.arrEncryptionProperties[i];
+ break;
+ }
+ }
+ return pEncProp;
+}
+
+//--------------------------------------------------
+// Retrieves the last EncryptionProperty subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns EncryptionProperty pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION DEncEncryptionProperty* dencEncryptedData_GetLastEncryptionProperty(DEncEncryptedData* pEncData)
+{
+ int nIdx;
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ nIdx = pEncData->encProperties.nEncryptionProperties -1;
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->encProperties.nEncryptionProperties, ERR_DENC_BAD_PROP_IDX, NULL);
+ RETURN_OBJ_IF_NULL(pEncData->encProperties.arrEncryptionProperties[nIdx], 0);
+ return pEncData->encProperties.arrEncryptionProperties[nIdx];
+}
+
+//--------------------------------------------------
+// Accessor for count of EncryptedKey subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns count or -1 for error. Then use error API to check errors
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_GetEncryptedKeyCount(DEncEncryptedData* pEncData)
+{
+ SET_LAST_ERROR_RETURN_IF_NOT(pEncData, ERR_NULL_POINTER, -1)
+ return pEncData->nEncryptedKeys;
+}
+
+//--------------------------------------------------
+// Accessor for EncryptedKey subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// nIdx - index of EncryptedKey object [REQUIRED]
+// returns EncryptedKey pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION DEncEncryptedKey* dencEncryptedData_GetEncryptedKey(DEncEncryptedData* pEncData, int nIdx)
+{
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->nEncryptedKeys, ERR_DENC_BAD_KEY_IDX, NULL);
+ RETURN_OBJ_IF_NULL(pEncData->arrEncryptedKeys[nIdx], 0);
+ return pEncData->arrEncryptedKeys[nIdx];
+}
+
+
+//--------------------------------------------------
+// Searches an EncryptedKey by recipients name
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// recipient - recipient name used to search the key [REQUIRED]
+// returns EncryptedKey pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION DEncEncryptedKey* dencEncryptedData_FindEncryptedKeyByRecipient(DEncEncryptedData* pEncData, const char* recipient)
+{
+ int i;
+ DEncEncryptedKey *pKey;
+
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ RETURN_OBJ_IF_NULL(recipient, NULL)
+ for(i = 0; i < pEncData->nEncryptedKeys; i++) {
+ pKey = pEncData->arrEncryptedKeys[i];
+ if(pKey && pKey->szRecipient && !strcmp(pKey->szRecipient, recipient))
+ return pKey;
+ }
+ return NULL;
+}
+
+//--------------------------------------------------
+// Searches an EncryptedKey by certs CN field
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// cn - cert CN used to search the key [REQUIRED]
+// returns EncryptedKey pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION DEncEncryptedKey* dencEncryptedData_FindEncryptedKeyByCN(DEncEncryptedData* pEncData, const char* cn)
+{
+ int i, err = ERR_OK;
+ DEncEncryptedKey *pKey;
+ DigiDocMemBuf mbuf;
+
+ mbuf.pMem = 0;
+ mbuf.nLen = 0;
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ RETURN_OBJ_IF_NULL(cn, NULL)
+ for(i = 0; i < pEncData->nEncryptedKeys; i++) {
+ pKey = pEncData->arrEncryptedKeys[i];
+ if(pKey && pKey->pCert) {
+ err = ddocCertGetSubjectCN(pKey->pCert, &mbuf);
+ if(!strcmp((const char*)mbuf.pMem, cn)) {
+ ddocMemBuf_free(&mbuf);
+ return pKey;
+ }
+ }
+ }
+ ddocMemBuf_free(&mbuf);
+ return NULL;
+}
+
+
+//--------------------------------------------------
+// Accessor for EncryptedKey subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns EncryptedKey pointer or NULL for error
+//--------------------------------------------------
+EXP_OPTION DEncEncryptedKey* dencEncryptedData_GetLastEncryptedKey(DEncEncryptedData* pEncData)
+{
+ int nIdx;
+ RETURN_OBJ_IF_NULL(pEncData, NULL)
+ nIdx = pEncData->nEncryptedKeys-1;
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->nEncryptedKeys, ERR_DENC_BAD_KEY_IDX, NULL);
+ RETURN_OBJ_IF_NULL(pEncData->arrEncryptedKeys[nIdx], 0);
+ return pEncData->arrEncryptedKeys[nIdx];
+}
+
+//--------------------------------------------------
+// Accessor for encrypted data.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// ppBuf - address for encrypted data pointer [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_GetEncryptedData(DEncEncryptedData* pEncData, DigiDocMemBuf** ppBuf)
+{
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(ppBuf)
+ *ppBuf = &(pEncData->mbufEncryptedData);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Accessor for encrypted data status flag.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns status or -1 for error. Then use error API to check errors
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_GetEncryptedDataStatus(DEncEncryptedData* pEncData)
+{
+ SET_LAST_ERROR_RETURN_IF_NOT(pEncData, ERR_NULL_POINTER, -1)
+ return pEncData->nDataStatus;
+}
+
+
+//======================< DEncEncryptedData - mutators >===================
+
+//--------------------------------------------------
+// Mutatoror for Id atribute of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_SetId(DEncEncryptedData* pEncData, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncData->szId), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for Type atribute of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_SetType(DEncEncryptedData* pEncData, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncData->szType), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for MimeType atribute of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_SetMimeType(DEncEncryptedData* pEncData, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncData->szMimeType), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for xmlns atribute of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_SetXmlNs(DEncEncryptedData* pEncData, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(value)
+ err = dencValidateEncXmlNs(value);
+ if(err) return err;
+ err = ddocMemAssignString((char**)&(pEncData->szXmlNs), value);
+ return err;
+}
+
+
+//--------------------------------------------------
+// Mutatoror for EncryptionMethod subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_SetEncryptionMethod(DEncEncryptedData* pEncData, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(value)
+ // replace the buggy URI with correct one to enable
+ // decrypting files with buggy URI but write only
+ // correct URI in new files
+ if(!strcmp(value, DENC_ENC_METHOD_RSA1_5_BUGGY))
+ value = DENC_ENC_METHOD_RSA1_5;
+ err = dencEncDataValidateEncMethod(value);
+ if(err) return err;
+ err = ddocMemAssignString((char**)&(pEncData->szEncryptionMethod), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Adds unencrypted data to encrypted data element
+// waiting to be encrypted in next steps
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// data - new unencrypted data [REQUIRED]
+// len - length of data. Use -1 for null terminated strings [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_AppendData(DEncEncryptedData* pEncData, const char* data, int len)
+{
+ ddocDebug(3, "dencEncryptedData_AppendData", "data: %s, len: %d", (data ? "OK" : "NULL"), len);
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(data)
+ SET_LAST_ERROR_RETURN_IF_NOT(pEncData->nDataStatus == DENC_DATA_STATUS_UNINITIALIZED ||
+ pEncData->nDataStatus == DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED,
+ ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ if(pEncData->nDataStatus == DENC_DATA_STATUS_UNINITIALIZED)
+ pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED;
+ return ddocMemAppendData(&(pEncData->mbufEncryptedData), data, len);
+}
+
+//--------------------------------------------------
+// Mutatoror for Id atribute of EncryptionProperties subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_SetEncryptionPropertiesId(DEncEncryptedData* pEncData, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncData->encProperties.szId), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Deletes EncryptionProperties subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// nIdx - index of EncryptionProperty object to be removed [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_DeleteEncryptionProperty(DEncEncryptedData* pEncData, int nIdx)
+{
+ int err = ERR_OK, i;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->encProperties.nEncryptionProperties, ERR_DENC_BAD_PROP_IDX, ERR_DENC_BAD_PROP_IDX);
+ RETURN_IF_NULL_PARAM(pEncData->encProperties.arrEncryptionProperties[nIdx]);
+ // delete the given object
+ err = dencEncryptionProperty_free(pEncData->encProperties.arrEncryptionProperties[nIdx]);
+ if(err) return err;
+ pEncData->encProperties.arrEncryptionProperties[nIdx] = 0;
+ // move other objects 1 step close to array start
+ for(i = nIdx; i < pEncData->encProperties.nEncryptionProperties-1; i++)
+ pEncData->encProperties.arrEncryptionProperties[i] =
+ pEncData->encProperties.arrEncryptionProperties[i+1];
+ pEncData->encProperties.arrEncryptionProperties[pEncData->encProperties.nEncryptionProperties - 1] = 0;
+ pEncData->encProperties.nEncryptionProperties--;
+ return err;
+}
+
+//--------------------------------------------------
+// Deletes EncryptedKey subelement of DEncEncryptedData object.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// nIdx - index of EncryptedKey object to be removed [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_DeleteEncryptedKey(DEncEncryptedData* pEncData, int nIdx)
+{
+ int err = ERR_OK, i;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->nEncryptedKeys, ERR_DENC_BAD_KEY_IDX, ERR_DENC_BAD_KEY_IDX);
+ RETURN_IF_NULL_PARAM(pEncData->arrEncryptedKeys[nIdx]);
+ // delete the given object
+ err = dencEncryptedKey_free(pEncData->arrEncryptedKeys[nIdx]);
+ if(err) return err;
+ pEncData->arrEncryptedKeys[nIdx] = 0;
+ // move other objects 1 step closer to array start
+ for(i = nIdx; i < pEncData->nEncryptedKeys-1; i++)
+ pEncData->arrEncryptedKeys[i] =
+ pEncData->arrEncryptedKeys[i+1];
+ pEncData->arrEncryptedKeys[pEncData->nEncryptedKeys - 1] = 0;
+ pEncData->nEncryptedKeys--;
+ return err;
+}
+
+
+//--------------------------------------------------
+// Mutatoror for Id atribute of DEncEncryptedData object.
+// Sets the default value - "ED0"
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_SetId_default(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ err = ddocMemAssignString((char**)&(pEncData->szId), "ED0");
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for Type atribute of DEncEncryptedData object.
+// Sets the default value - "http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd"
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_SetType_default(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncData)
+ err = ddocMemAssignString((char**)&(pEncData->szType), DENC_ENCDATA_TYPE_DDOC);
+ return err;
+}
+
+//======================< DEncEncryptionProperty >===================
+
+//--------------------------------------------------
+// "Constructor" for EncryptionProperty
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// pEncProperty - address of buffer for new property object [REQUIRED]
+// szId - Id atribute of EncryptionProperty [OPTIONAL]
+// szTarget - Target atribute of EncryptionProperty [OPTIONAL]
+// szName - name atribute of EncryptionProperty [OPTIONAL]
+// szContent - content of EncryptionProperty [OPTIONAL]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptionProperty_new(DEncEncryptedData* pEncData,
+ DEncEncryptionProperty** ppEncProperty,
+ const char* szId, const char* szTarget,
+ const char* szName, const char* szContent)
+{
+ int err = ERR_OK, nProps;
+ DEncEncryptionProperty **pProps, *pProp;
+
+ // check parameters
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(ppEncProperty)
+ *ppEncProperty = 0; // mark as not yet allocated
+ // allocate memory for pointer array
+ nProps = pEncData->encProperties.nEncryptionProperties + 1;
+ pProps = (DEncEncryptionProperty **)realloc(pEncData->encProperties.arrEncryptionProperties,
+ sizeof(DEncEncryptionProperty *) * nProps);
+ if(!pProps)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ pEncData->encProperties.arrEncryptionProperties = pProps;
+ pProps[pEncData->encProperties.nEncryptionProperties] = 0;
+ // allocate memory for new property
+ pProp = (DEncEncryptionProperty*)malloc(sizeof(DEncEncryptionProperty));
+ if(!pProp)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ memset(pProp, 0, sizeof(DEncEncryptionProperty));
+ pProps[pEncData->encProperties.nEncryptionProperties] = pProp;
+ *ppEncProperty = pProp;
+ pEncData->encProperties.nEncryptionProperties = nProps;
+ // set data
+ if(szId) {
+ err = ddocMemAssignString((char**)&(pProp->szId), szId);
+ if(err) return err;
+ }
+ if(szTarget) {
+ err = ddocMemAssignString((char**)&(pProp->szTarget), szTarget);
+ if(err) return err;
+ }
+ if(szName) {
+ err = ddocMemAssignString((char**)&(pProp->szName), szName);
+ if(err) return err;
+ }
+ if(szContent) {
+ err = ddocMemAssignString((char**)&(pProp->szContent), szContent);
+ if(err) return err;
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" for EncryptionProperty
+// pEncProperty - address of buffer for new property object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptionProperty_free(DEncEncryptionProperty* pEncProperty)
+{
+ RETURN_IF_NULL_PARAM(pEncProperty)
+ if(pEncProperty->szId)
+ free(pEncProperty->szId);
+ if(pEncProperty->szTarget)
+ free(pEncProperty->szTarget);
+ if(pEncProperty->szName)
+ free(pEncProperty->szName);
+ if(pEncProperty->szContent)
+ free(pEncProperty->szContent);
+ free(pEncProperty);
+ return ERR_OK;
+}
+
+//======================< DEncEncryptionProperty - accessors >===================
+
+//--------------------------------------------------
+// Accessor for Id atribute of EncryptionProperty object.
+// pEncProp - pointer to DEncEncryptionProperty object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptionProperty_GetId(DEncEncryptionProperty* pEncProp)
+{
+ RETURN_OBJ_IF_NULL(pEncProp, NULL)
+ return pEncProp->szId;
+}
+
+//--------------------------------------------------
+// Accessor for Target atribute of EncryptionProperty object.
+// pEncProp - pointer to DEncEncryptionProperty object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptionProperty_GetTarget(DEncEncryptionProperty* pEncProp)
+{
+ RETURN_OBJ_IF_NULL(pEncProp, NULL)
+ return pEncProp->szTarget;
+}
+
+//--------------------------------------------------
+// Accessor for Name atribute of EncryptionProperty object.
+// pEncProp - pointer to DEncEncryptionProperty object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptionProperty_GetName(DEncEncryptionProperty* pEncProp)
+{
+ RETURN_OBJ_IF_NULL(pEncProp, NULL)
+ return pEncProp->szName;
+}
+
+//--------------------------------------------------
+// Accessor for content of EncryptionProperty object.
+// pEncProp - pointer to DEncEncryptionProperty object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptionProperty_GetContent(DEncEncryptionProperty* pEncProp)
+{
+ RETURN_OBJ_IF_NULL(pEncProp, NULL)
+ return pEncProp->szContent;
+}
+
+//======================< DEncEncryptionProperty - mutators >===================
+
+//--------------------------------------------------
+// Mutatoror for Id atribute of DEncEncryptionProperty object.
+// pEncProp - pointer to DEncEncryptionProperty object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptionProperty_SetId(DEncEncryptionProperty* pEncProp, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncProp)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncProp->szId), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for Target atribute of DEncEncryptionProperty object.
+// pEncProp - pointer to DEncEncryptionProperty object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptionProperty_SetTarget(DEncEncryptionProperty* pEncProp, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncProp)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncProp->szTarget), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for Name atribute of DEncEncryptionProperty object.
+// pEncProp - pointer to DEncEncryptionProperty object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptionProperty_SetName(DEncEncryptionProperty* pEncProp, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncProp)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncProp->szName), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for content of DEncEncryptionProperty object.
+// pEncProp - pointer to DEncEncryptionProperty object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptionProperty_SetContent(DEncEncryptionProperty* pEncProp, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncProp)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncProp->szContent), value);
+ return err;
+}
+
+
+//======================< DEncEncryptedKey >===================
+
+//--------------------------------------------------
+// Initializes transport key and init vector.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+int dencEncryptedData_initTransportKey(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK, l1;
+ char salt[8], indata[128], key[16];
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ // init random generator
+#ifdef WIN32
+ RAND_screen();
+ RAND_bytes((unsigned char*)salt, sizeof(salt));
+ RAND_bytes((unsigned char*)indata, sizeof(indata));
+ RAND_bytes((unsigned char*)pEncData->initVector, sizeof(pEncData->initVector));
+#else
+ if((l1 = RAND_load_file("/dev/urandom", 1024)) > 0) {
+ ddocDebug(4, "dencEncryptedData_initTransportKey", "rand load: %d", l1);
+ RAND_bytes((unsigned char*)salt, sizeof(salt));
+ RAND_bytes((unsigned char*)indata, sizeof(indata));
+ RAND_bytes((unsigned char*)pEncData->initVector, sizeof(pEncData->initVector));
+ }
+#endif
+ // intialize IV
+ memset(key, 0, sizeof(key));
+ l1 = EVP_BytesToKey(EVP_aes_128_cbc(), EVP_md5(), (const unsigned char*)salt, (const unsigned char*)indata, sizeof(indata), 1, (unsigned char*)key, NULL);
+ ddocDebug(3, "dencEncryptedData_initTransportKey", "BytesToKey: %d", l1);
+ err = ddocMemAssignData(&(pEncData->mbufTransportKey), key, sizeof(key));
+ if(err) return err;
+ ddocDebug(3, "dencEncryptedData_initTransportKey", "RC: %d key: %d",
+ l1, pEncData->mbufTransportKey.nLen);
+ pEncData->nKeyStatus = DENC_KEY_STATUS_INITIALIZED;
+ return err;
+}
+
+//--------------------------------------------------
+// Validates the <EncryptionMethod> parameter. We
+// currently support only RSA-1.5
+// szEncMethod - value to be checked
+// returns error code or ERR_OK
+//--------------------------------------------------
+int dencEncKeyValidateEncMethod(const char* szEncMethod)
+{
+ if(szEncMethod && strcmp(szEncMethod, DENC_ENC_METHOD_RSA1_5))
+ SET_LAST_ERROR_RETURN(ERR_DENC_ENC_METHOD, ERR_DENC_ENC_METHOD)
+ else
+ return ERR_OK;
+}
+
+
+//--------------------------------------------------
+// Encrypts data with RSA public key (receivers key?)
+// pCert - receivers certificate
+// data - input data
+// dLen - input data length
+// result - encrypted data
+// resLen - output buffer length / used bytes
+//--------------------------------------------------
+int dencEncryptWithCert(X509* pCert, const char* data, int dLen, char* result, int* resLen)
+{
+ int err = ERR_OK;
+ EVP_PKEY* pkey;
+
+ // check parameters
+ RETURN_IF_NULL_PARAM(pCert)
+ RETURN_IF_NULL_PARAM(data)
+ RETURN_IF_NULL_PARAM(result)
+ RETURN_IF_NULL_PARAM(resLen)
+ // get certificates public key
+ err = GetPublicKey(&pkey, pCert);
+ if(err) return err;
+ // encrypt data
+ memset((char*)result, 0, *resLen);
+ *resLen = RSA_public_encrypt(dLen, (const unsigned char*)data, (unsigned char*)result, pkey->pkey.rsa, RSA_PKCS1_PADDING);
+ // cleanup
+ EVP_PKEY_free(pkey); // should I ???
+
+ return err;
+}
+
+
+//--------------------------------------------------
+// "Constructor" for EncryptedKey
+// Encrypts the transport key for a receiver
+// and stores encrypted key in memory
+// Call this function repeatedly for all receivers,
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// pEncKey - address of buffer for new encrypted key object [REQUIRED]
+// pCert - recevers certificate [REQUIRED]
+// szEncMethod - encryption method [REQUIRED]
+// szId - Id atribute of EncryptedKey [OPTIONAL]
+// szRecipient - Recipient atribute of EncryptedKey [OPTIONAL]
+// szKeyName - KeyName subelement of EncryptedKey [OPTIONAL]
+// szCarriedKeyName - CarriedKeyName subelement of EncryptedKey [OPTIONAL]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedKey_new(DEncEncryptedData* pEncData,
+ DEncEncryptedKey** pEncKey, X509* pCert,
+ const char* szEncMethod, const char* szId,
+ const char* szRecipient, const char* szKeyName,
+ const char* szCarriedKeyName)
+{
+ int err = ERR_OK, nKeys, l1;
+ DEncEncryptedKey **pKeys, *pKey;
+ //AM 14.10.08 from 130 to 300
+ char tkey[300];
+
+ ddocDebug(3, "dencEncryptedKey_new", "cert: %s, method: %s, id: %s, recipient: %s, keyname: %s carriedkeyname: %s",
+ (pCert ? "OK" : "NULL"), szEncMethod, szId, szRecipient, szKeyName, szCarriedKeyName);
+ // check parameters
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(pEncKey)
+ err = dencEncKeyValidateEncMethod(szEncMethod);
+ if(err) return err;
+ *pEncKey = 0;
+ // increase the buffer for EncryptedKey pointers
+ nKeys = pEncData->nEncryptedKeys + 1;
+ pKeys = (DEncEncryptedKey **)realloc(pEncData->arrEncryptedKeys, sizeof(DEncEncryptedKey *) * nKeys);
+ if(!pKeys)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ pEncData->arrEncryptedKeys = pKeys;
+ pEncData->arrEncryptedKeys[pEncData->nEncryptedKeys] = 0;
+ pKey = (DEncEncryptedKey*)malloc(sizeof(DEncEncryptedKey));
+ if(!pKey)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ pEncData->arrEncryptedKeys[pEncData->nEncryptedKeys] = pKey;
+ pEncData->nEncryptedKeys = nKeys;
+ *pEncKey = pKey;
+ memset(pKey, 0, sizeof(DEncEncryptedKey));
+ // set required parameters
+ if(szEncMethod) {
+ err = ddocMemAssignString((char**)&(pKey->szEncryptionMethod), szEncMethod);
+ if(err) return err;
+ }
+ if(pCert) {
+ if(!ddocCertCheckKeyUsage(pCert, KUIDX_KEY_ENCIPHERMENT)) {
+ ddocDebug(1, "dencEncryptedKey_new", "ENC: cert has no key-encipherment key usage");
+ SET_LAST_ERROR(ERR_CERT_INVALID);
+ return ERR_CERT_INVALID;
+ } else
+ ddocDebug(3, "dencEncryptedKey_new", "ENC: cert has key-encipherment key usage");
+ pKey->pCert = pCert;
+ }
+ // set optional parameters
+ if(szId) {
+ err = ddocMemAssignString((char**)&(pKey->szId), szId);
+ if(err) return err;
+ }
+ if(szRecipient) {
+ err = ddocMemAssignString((char**)&(pKey->szRecipient), szRecipient);
+ if(err) return err;
+ }
+ if(szKeyName) {
+ err = ddocMemAssignString((char**)&(pKey->szKeyName), szKeyName);
+ if(err) return err;
+ }
+ if(szCarriedKeyName) {
+ err = ddocMemAssignString((char**)&(pKey->szCarriedKeyName), szCarriedKeyName);
+ if(err) return err;
+ }
+ if(pCert) {
+ // encrypt the key
+ if(pEncData->nKeyStatus == DENC_KEY_STATUS_UNINITIALIZED) {
+ err = dencEncryptedData_initTransportKey(pEncData);
+ if(err) return err;
+ }
+ l1 = sizeof(tkey);
+ err = dencEncryptWithCert(pCert, (const char*)pEncData->mbufTransportKey.pMem,
+ pEncData->mbufTransportKey.nLen, tkey, &l1);
+ if(err) return err;
+ //if(pKey)dencEncryptedKey_/free(&pKey);
+ //pKey = (DEncEncryptedKey*)malloc(sizeof(DEncEncryptedKey));
+ //memset(pKey, 0, sizeof(DEncEncryptedKey));
+ err = ddocMemAssignData(&(pKey->mbufTransportKey), tkey, l1);
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" for EncryptedKey
+// pEncKey - address of buffer for new encrypted key object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedKey_free(DEncEncryptedKey* pEncKey)
+{
+ RETURN_IF_NULL_PARAM(pEncKey)
+ if(pEncKey->szId)
+ free(pEncKey->szId);
+ if(pEncKey->szRecipient)
+ free(pEncKey->szRecipient);
+ if(pEncKey->szEncryptionMethod)
+ free(pEncKey->szEncryptionMethod);
+ if(pEncKey->szKeyName)
+ free(pEncKey->szKeyName);
+ if(pEncKey->szCarriedKeyName)
+ free(pEncKey->szCarriedKeyName);
+ if(pEncKey->pCert)
+ X509_free(pEncKey->pCert);
+ ddocMemBuf_free(&(pEncKey->mbufTransportKey));
+ free(pEncKey);
+ return ERR_OK;
+}
+
+//======================< DEncEncryptedKey - acessors >===================
+
+
+//--------------------------------------------------
+// Accessor for Id atribute of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedKey_GetId(DEncEncryptedKey* pEncKey)
+{
+ RETURN_OBJ_IF_NULL(pEncKey, NULL)
+ return pEncKey->szId;
+}
+
+//--------------------------------------------------
+// Accessor for Recipient atribute of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedKey_GetRecipient(DEncEncryptedKey* pEncKey)
+{
+ RETURN_OBJ_IF_NULL(pEncKey, NULL)
+ return pEncKey->szRecipient;
+}
+
+//--------------------------------------------------
+// Accessor for EncryptionMethod subelement of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedKey_GetEncryptionMethod(DEncEncryptedKey* pEncKey)
+{
+ RETURN_OBJ_IF_NULL(pEncKey, NULL)
+ return pEncKey->szEncryptionMethod;
+}
+
+//--------------------------------------------------
+// Accessor for KeyName subelement of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedKey_GetKeyName(DEncEncryptedKey* pEncKey)
+{
+ RETURN_OBJ_IF_NULL(pEncKey, NULL)
+ return pEncKey->szKeyName;
+}
+
+//--------------------------------------------------
+// Accessor for CarriedKeyName subelement of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION const char* dencEncryptedKey_GetCarriedKeyName(DEncEncryptedKey* pEncKey)
+{
+ RETURN_OBJ_IF_NULL(pEncKey, NULL)
+ return pEncKey->szCarriedKeyName;
+}
+
+//--------------------------------------------------
+// Accessor for certificate of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// returns value of atribute or NULL.
+//--------------------------------------------------
+EXP_OPTION X509* dencEncryptedKey_GetCertificate(DEncEncryptedKey* pEncKey)
+{
+ RETURN_OBJ_IF_NULL(pEncKey, NULL)
+ return pEncKey->pCert;
+}
+
+//======================< DEncEncryptedKey - mutators >===================
+
+//--------------------------------------------------
+// Mutatoror for Id atribute of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedKey_SetId(DEncEncryptedKey* pEncKey, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncKey)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncKey->szId), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for Recipient atribute of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedKey_SetRecipient(DEncEncryptedKey* pEncKey, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncKey)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncKey->szRecipient), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for EncryptionMethod subelement of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedKey_SetEncryptionMethod(DEncEncryptedKey* pEncKey, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncKey)
+ RETURN_IF_NULL_PARAM(value)
+ err = dencEncKeyValidateEncMethod(value);
+ if(err) return err;
+ err = ddocMemAssignString((char**)&(pEncKey->szEncryptionMethod), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for KeyName subelement of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedKey_SetKeyName(DEncEncryptedKey* pEncKey, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncKey)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncKey->szKeyName), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for CarriedKeyName subelement of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedKey_SetCarriedKeyName(DEncEncryptedKey* pEncKey, const char* value)
+{
+ int err = ERR_OK;
+ RETURN_IF_NULL_PARAM(pEncKey)
+ RETURN_IF_NULL_PARAM(value)
+ err = ddocMemAssignString((char**)&(pEncKey->szCarriedKeyName), value);
+ return err;
+}
+
+//--------------------------------------------------
+// Mutatoror for certificate of DEncEncryptedKey object.
+// pEncKey - pointer to DEncEncryptedKey object [REQUIRED]
+// value - new value for atribute [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedKey_SetCertificate(DEncEncryptedKey* pEncKey, X509* value)
+{
+ RETURN_IF_NULL_PARAM(pEncKey)
+ RETURN_IF_NULL_PARAM(value)
+ pEncKey->pCert = value;
+ return ERR_OK;
+}
+
+//==========< general crypto fucntions >============
+
+//--------------------------------------------------
+// Locates the correct EncryptedKey object by reading
+// users certificate from smartcard and searching the
+// right EncryptedKey object
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS11(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey)
+{
+ return dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot(pEncData, ppEncKey, 0);
+}
+
+//--------------------------------------------------
+// Locates the correct EncryptedKey object by reading
+// users certificate from smartcard and searching the
+// right EncryptedKey object
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED]
+// nSlot - slot nr
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey, int nSlot)
+{
+ int err = ERR_OK, i, n;
+ X509 *pCert = 0;
+ DEncEncryptedKey *pEncKey = 0;
+ char buf1[100], buf2[100];
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(ppEncKey)
+ *ppEncKey = 0; // mark as not found yet
+ err = findUsersCertificate(nSlot, &pCert);
+ if(err) return err;
+ memset(buf1, 0, sizeof(buf1));
+ err = ReadCertSerialNumber(buf1, sizeof(buf1), pCert);
+ if(err) return err;
+ ddocDebug(3, "dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot", "Users cert: %s", buf1);
+ n = dencEncryptedData_GetEncryptedKeyCount(pEncData);
+ for(i = 0; i < n; i++) {
+ pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i);
+ memset(buf2, 0, sizeof(buf2));
+ err = ReadCertSerialNumber(buf2, sizeof(buf2), pEncKey->pCert);
+ ddocDebug(3, "dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot", "Key: %d cert: %s", i, buf2);
+ if(!err && !strcmp(buf1, buf2)) {
+ *ppEncKey = pEncKey;
+ ddocDebug(3, "dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot", "Using key: %d cert: %s", i, buf2);
+ break;
+ }
+ }
+ if(pCert)
+ X509_free(pCert);
+ if(!*ppEncKey) {
+ ddocDebug(3, "dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot", "No matching key found!");
+ SET_LAST_ERROR_RETURN(ERR_DENC_NO_KEY_FOUND, ERR_DENC_NO_KEY_FOUND)
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// Locates the correct EncryptedKey object by reading
+// users certificate and private key from pkcs12 file and searching the
+// right EncryptedKey object
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED]
+// ppKey - address of private key pointer. Caller must free [REQUIRED]
+// szPkcs12File - pkcs12 file name [REQUIRED]
+// szPasswd - pkcs12 file password [REQUIRED]. Might be empty?
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS12(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey,
+ EVP_PKEY** ppKey, const char* szPkcs12File, const char* szPasswd)
+{
+ int err = ERR_OK, i, n;
+ X509 *pCert = 0;
+ DEncEncryptedKey *pEncKey = 0;
+ char buf1[100], buf2[100];
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(ppEncKey)
+ RETURN_IF_NULL_PARAM(ppKey)
+ *ppEncKey = 0; // mark as not found yet
+ *ppKey = 0;
+ err = ReadCertificateByPKCS12(&pCert, szPkcs12File, szPasswd, ppKey);
+ if(err) return err;
+ memset(buf1, 0, sizeof(buf1));
+ err = ReadCertSerialNumber(buf1, sizeof(buf1), pCert);
+ if(err) return err;
+ n = dencEncryptedData_GetEncryptedKeyCount(pEncData);
+ for(i = 0; i < n; i++) {
+ pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i);
+ memset(buf2, 0, sizeof(buf2));
+ err = ReadCertSerialNumber(buf2, sizeof(buf2), pEncKey->pCert);
+ if(!err && !strcmp(buf1, buf2)) {
+ *ppEncKey = pEncKey;
+ break;
+ }
+ }
+ if(pCert)
+ X509_free(pCert);
+ if(!*ppEncKey)
+ SET_LAST_ERROR_RETURN(ERR_DENC_NO_KEY_FOUND, ERR_DENC_NO_KEY_FOUND)
+ return err;
+}
+
+
+
+//--------------------------------------------------
+// AES encrypt/decrypt operations
+// pInData - input data
+// pOutData - output buffer
+// pKey - AES key
+// operation - ENCRYPT/DECRYPT
+// iv - init vector for the cipher
+//--------------------------------------------------
+int encryptDecrypt(DigiDocMemBuf *pInData, DigiDocMemBuf *pOutData,
+ DigiDocMemBuf *pKey, int operation, const char* iv)
+{
+ EVP_CIPHER_CTX ectx;
+ int err = ERR_OK, len, i, nInLen, nOutLen;
+ char padBuf[16], *pInMem;
+ int lOrigLen, lEncLen;
+
+ ddocDebug(3, "encryptDecrypt", "Input: %d, output: %d, key: %d, operation: %s",
+ (pInData ? pInData->nLen : 0), (pOutData ? pOutData->nLen : 0),
+ (pKey ? pKey->nLen : 0), (operation ? "ENCRYPT" : "DECRYPT"));
+ RETURN_IF_NULL_PARAM(pInData)
+ RETURN_IF_NULL_PARAM(pOutData)
+ RETURN_IF_NULL_PARAM(pKey)
+ nInLen = pInData->nLen;
+ pInMem = (char*)pInData->pMem;
+ // use the first 16 bytes as IV
+ // and remove this data from data to be decrypted
+ if(operation == DECRYPT) {
+ memcpy((char*)iv, (const char*)pInData->pMem, 16);
+ for(i = 0; i < 16; i++)
+ ddocDebug(3, "encryptDecrypt", "IV pos: %d = %d", i, iv[i]);
+ nInLen -= 16;
+ pInMem += 16;
+ ddocDebug(3, "encryptDecrypt", "DECRYPT using iv input left: %d", nInLen);
+ }
+ lOrigLen = lEncLen = 0;
+ len = nInLen % 16;
+ if(operation == ENCRYPT) {
+ len = 16 - (nInLen % 16);
+ ddocDebug(3, "encryptDecrypt", "Input len: %d adding padding: %d\n", nInLen, len);
+ memset(padBuf, 0, sizeof(padBuf));
+ for(i = 0; i < len; i++)
+ padBuf[i] = 0;
+ padBuf[len-1] = (unsigned char)len; // number of padded chars
+ }
+ if(pOutData->pMem)
+ free(pOutData->pMem);
+ pOutData->nLen = nInLen * 2 + len * 2;
+ if(operation == ENCRYPT)
+ pOutData->nLen += 16;
+ nOutLen = pOutData->nLen;
+ pOutData->pMem = (char*)malloc(pOutData->nLen);
+ memset(pOutData->pMem, 0, pOutData->nLen);
+ if(!pOutData->pMem)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ ddocDebug(3, "encryptDecrypt", "Allocated: %d", pOutData->nLen);
+ // copy init vector to begin of output data
+ if(operation == ENCRYPT)
+ memcpy(pOutData->pMem, iv, 16);
+ EVP_CIPHER_CTX_init(&ectx);
+ EVP_CipherInit_ex(&ectx, EVP_aes_128_cbc(), NULL, (const unsigned char*)pKey->pMem, (const unsigned char*)iv, operation);
+ //EVP_CIPHER_CTX_set_padding(&ectx, 1);
+ //checkErrors();
+ lOrigLen += nInLen;
+ i = nOutLen;
+ // set initial position for encryted data
+ if(operation == ENCRYPT)
+ pOutData->nLen = 16;
+ else
+ pOutData->nLen = 0;
+ EVP_CipherUpdate(&ectx, (unsigned char*)pOutData->pMem + pOutData->nLen, &i, (const unsigned char*)pInMem, nInLen);
+ lEncLen += i;
+ pOutData->nLen += i;
+ ddocDebug(3, "encryptDecrypt", "Initial update: %d into: %d -> %d", nInLen, nOutLen, i);
+
+ //TODO: in 1.1 don't check len
+ if(len && operation == ENCRYPT) {
+ EVP_CipherUpdate(&ectx, (unsigned char*)pOutData->pMem + pOutData->nLen, &i, (const unsigned char*)padBuf, len);
+ ddocDebug(3, "encryptDecrypt", "Padding update: %d -> %d", len, i);
+ pOutData->nLen += i;
+ lOrigLen += len;
+ nOutLen -= i;
+ lEncLen += i;
+ }
+ i = nOutLen;
+ EVP_CipherFinal_ex(&ectx, (unsigned char*)pOutData->pMem + pOutData->nLen, &i);
+ ddocDebug(3, "encryptDecrypt", "Final update: %d into: %d", i, nOutLen);
+ pOutData->nLen += i;
+ lEncLen += i;
+ ddocDebug(3, "encryptDecrypt", "Total input: %d encrypted: %d", lOrigLen, lEncLen);
+ EVP_CIPHER_CTX_cleanup(&ectx);
+ if(operation == DECRYPT) {
+ // check ANSI X.923 padding
+ len = (int)(unsigned char)((char*)pOutData->pMem)[pOutData->nLen-1];
+ if(len > 0 && len <= 16) {
+ ddocDebug(3, "encryptDecrypt", "X.923 check padding: %d", len);
+ // check if all previous are 0-s
+ for(i = pOutData->nLen - len; i < pOutData->nLen - 1; i++) {
+ ddocDebug(3, "encryptDecrypt", "Byte at: %d = %d", i, ((char*)pOutData->pMem)[i]);
+ if(((char*)pOutData->pMem)[i])
+ len = 0; // set not matched flag
+ }
+ if(len >= 1) {
+ ddocDebug(3, "encryptDecrypt", "X.923 decrypted len: %d reduce by: %d", pOutData->nLen, len);
+ pOutData->nLen -= len;
+ }
+ else
+ ddocDebug(3, "encryptDecrypt", "X.923 decrypted len remains: %d", pOutData->nLen);
+ }
+ else
+ ddocDebug(3, "encryptDecrypt", "Impossible padding: %d", len);
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// Encrypts data with the generated key
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// nCompressOption - flag: DENC_COMPRESS_ALLWAYS,
+// DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_encryptData(DEncEncryptedData* pEncData, int nCompressOption)
+{
+ int err = ERR_OK;
+ DigiDocMemBuf outData;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ // check compression
+ if(nCompressOption == DENC_COMPRESS_ALLWAYS ||
+ nCompressOption == DENC_COMPRESS_BEST_EFFORT) {
+ err = dencEncryptedData_compressData(pEncData, nCompressOption);
+ if(err) return err;
+ }
+ // check data status
+ if(pEncData->nDataStatus != DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED &&
+ pEncData->nDataStatus != DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ // init transport key if necessary
+ if(pEncData->nKeyStatus == DENC_KEY_STATUS_UNINITIALIZED) {
+ err = dencEncryptedData_initTransportKey(pEncData);
+ if(err) return err;
+ }
+ outData.pMem = 0;
+ outData.nLen = 0;
+ err = encryptDecrypt(&(pEncData->mbufEncryptedData), &outData,
+ &(pEncData->mbufTransportKey), ENCRYPT,
+ pEncData->initVector);
+ if(!err) {
+ free(pEncData->mbufEncryptedData.pMem);
+ pEncData->mbufEncryptedData.pMem = outData.pMem;
+ pEncData->mbufEncryptedData.nLen = outData.nLen;
+ // check if we have original length in <EncryptionProperties>
+ if(pEncData->nDataStatus == DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED)
+ pEncData->nDataStatus = DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED;
+ else
+ pEncData->nDataStatus = DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED;
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// Decrypts data with the generated key
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_decryptData(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK;
+ DigiDocMemBuf outData;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ // check data status
+ if(pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED &&
+ pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ // check transport key
+ if(pEncData->nKeyStatus == DENC_KEY_STATUS_UNINITIALIZED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_KEY_STATUS, ERR_DENC_KEY_STATUS)
+ outData.pMem = 0;
+ outData.nLen = 0;
+ err = encryptDecrypt(&(pEncData->mbufEncryptedData), &outData,
+ &(pEncData->mbufTransportKey), DECRYPT,
+ pEncData->initVector);
+ if(!err) {
+ free(pEncData->mbufEncryptedData.pMem);
+ pEncData->mbufEncryptedData.pMem = outData.pMem;
+ pEncData->mbufEncryptedData.nLen = outData.nLen;
+ if(pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED)
+ pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED;
+ else
+ pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED;
+ }
+ // decompress if necessary
+ if(!err && pEncData->nDataStatus == DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED)
+ err = dencEncryptedData_decompressData(pEncData);
+ return err;
+}
+
+
+//--------------------------------------------------
+// Decrypts data transport key with ID card and
+// then decrypts the data with the transport key.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// pEncKey - transport key to decrypt [REQUIRED]
+// pin - pin code for smart card [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_decrypt(DEncEncryptedData* pEncData,
+ DEncEncryptedKey* pEncKey,
+ const char* pin)
+{
+ int nSlot = nSlot = ConfigItem_lookup_int("DIGIDOC_AUTH_KEY_SLOT", 0);
+ return dencEncryptedData_decryptUsingSlot(pEncData, pEncKey, pin, nSlot);
+}
+
+//--------------------------------------------------
+// Decrypts data transport key with ID card and
+// then decrypts the data with the transport key.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// pEncKey - transport key to decrypt [REQUIRED]
+// pin - pin code for smart card [REQUIRED]
+// nSlot - slot nr
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_decryptUsingSlot(DEncEncryptedData* pEncData,
+ DEncEncryptedKey* pEncKey,
+ const char* pin, int nSlot)
+{
+ int err = ERR_OK, len;
+ DEncEncryptionProperty* pEncProp;
+ long l;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(pEncKey)
+ RETURN_IF_NULL_PARAM(pin)
+ // check data status
+ if(pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED &&
+ pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ pEncData->nKeyStatus = DENC_KEY_STATUS_UNINITIALIZED;
+ // it will shrink during decrypt so this is enough
+ pEncData->mbufTransportKey.nLen = pEncKey->mbufTransportKey.nLen;
+ pEncData->mbufTransportKey.pMem = (char*)malloc(pEncData->mbufTransportKey.nLen);
+ if(!pEncData->mbufTransportKey.pMem)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ ddocDebug(3, "dencEncryptedData_decrypt", "Decrypt enckey: %d into: %d",
+ pEncKey->mbufTransportKey.nLen, pEncData->mbufTransportKey.nLen);
+ len = pEncData->mbufTransportKey.nLen;
+ err = decryptWithEstID(nSlot, pin,
+ (const char*)pEncKey->mbufTransportKey.pMem, pEncKey->mbufTransportKey.nLen,
+ (char*)pEncData->mbufTransportKey.pMem, &len);
+ pEncData->mbufTransportKey.nLen = len;
+ if(err) return err;
+ pEncData->nKeyStatus = DENC_KEY_STATUS_INITIALIZED;
+ err = dencEncryptedData_decryptData(pEncData);
+ /*pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_SIZE);
+ if(pEncProp && pEncProp->szContent) {
+ l = atol(pEncProp->szContent);
+ if(l > 0 && l < pEncData->mbufEncryptedData.nLen) {
+ ddocDebug(4, "dencEncryptedData_decrypt", "Truncating decrypted data: %d to: %d",
+ pEncData->mbufEncryptedData.nLen, l);
+ pEncData->mbufEncryptedData.nLen = l;
+ }
+ }*/
+ return err;
+}
+
+//--------------------------------------------------
+// Decrypts data transport key with ID card and
+// then decrypts the data with the transport key.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// pEncKey - transport key to decrypt [REQUIRED]
+// pKey - private key for decrypting [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_decryptWithKey(DEncEncryptedData* pEncData,
+ DEncEncryptedKey* pEncKey,
+ EVP_PKEY* pKey)
+{
+ int err = ERR_OK, len;
+ DEncEncryptionProperty* pEncProp;
+ long l;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(pEncKey)
+ RETURN_IF_NULL_PARAM(pKey)
+ // check data status
+ if(pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED &&
+ pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ pEncData->nKeyStatus = DENC_KEY_STATUS_UNINITIALIZED;
+ // it will shrink during decrypt so this is enough
+ pEncData->mbufTransportKey.nLen = pEncKey->mbufTransportKey.nLen;
+ pEncData->mbufTransportKey.pMem = (char*)malloc(pEncData->mbufTransportKey.nLen);
+ if(!pEncData->mbufTransportKey.pMem)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ ddocDebug(3, "dencEncryptedData_decryptWithKey", "Decrypt enckey: %d into: %d",
+ pEncKey->mbufTransportKey.nLen, pEncData->mbufTransportKey.nLen);
+#if OPENSSL_VERSION_NUMBER > 0x10000000
+ len = EVP_PKEY_decrypt_old((unsigned char *)pEncData->mbufTransportKey.pMem,
+ (const unsigned char*)pEncKey->mbufTransportKey.pMem,
+ pEncKey->mbufTransportKey.nLen, pKey);
+#else
+ len = EVP_PKEY_decrypt((unsigned char *)pEncData->mbufTransportKey.pMem,
+ (const unsigned char*)pEncKey->mbufTransportKey.pMem,
+ pEncKey->mbufTransportKey.nLen, pKey);
+#endif
+ ddocDebug(3, "dencEncryptedData_decryptWithKey", "Decrypt rv: %d len: %l", err, len);
+ pEncData->mbufTransportKey.nLen = len;
+ if(len != 16) return ERR_DENC_DECRYPT;
+ else err = ERR_OK;
+ pEncData->nKeyStatus = DENC_KEY_STATUS_INITIALIZED;
+ err = dencEncryptedData_decryptData(pEncData);
+ pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_SIZE);
+ if(pEncProp && pEncProp->szContent) {
+ l = atol(pEncProp->szContent);
+ if(l > 0 && l < pEncData->mbufEncryptedData.nLen) {
+ ddocDebug(4, "dencEncryptedData_decrypt", "Truncating decrypted data: %d to: %d",
+ pEncData->mbufEncryptedData.nLen, l);
+ pEncData->mbufEncryptedData.nLen = l;
+ }
+ }
+ return err;
+}
+
+
+//--------------------------------------------------
+// Decrypts data transport key with ID card and
+// then decrypts the data with the transport key.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// tKey - decrypted transport key [REQUIRED]
+// keyLen - length of trasnport key [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_decrypt_withKey(DEncEncryptedData* pEncData,
+ const char* tKey, int keyLen)
+{
+ int err = ERR_OK;
+ DEncEncryptionProperty* pEncProp;
+ long l;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(tKey)
+ // check data status
+ if(pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED &&
+ pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ pEncData->mbufTransportKey.nLen = keyLen;
+ pEncData->mbufTransportKey.pMem = (char*)malloc(pEncData->mbufTransportKey.nLen);
+ if(!pEncData->mbufTransportKey.pMem)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ memcpy(pEncData->mbufTransportKey.pMem, tKey, keyLen);
+ ddocDebug(4, "dencEncryptedData_decrypt_withKey", "Decrypt enckey: %d into: %d",
+ keyLen, pEncData->mbufTransportKey.nLen);
+ pEncData->nKeyStatus = DENC_KEY_STATUS_INITIALIZED;
+ err = dencEncryptedData_decryptData(pEncData);
+ pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_SIZE);
+ if(pEncProp && pEncProp->szContent) {
+ l = atol(pEncProp->szContent);
+ if(l > 0 && l < pEncData->mbufEncryptedData.nLen) {
+ ddocDebug(4, "dencEncryptedData_decrypt_withKey", "Truncating decrypted data: %d to: %d",
+ pEncData->mbufEncryptedData.nLen, l);
+ pEncData->mbufEncryptedData.nLen = l;
+ }
+ }
+ return err;
+}
+
+
+//--------------------------------------------------
+// Compresses data with ZLIB. Cannot compress encrypted data!!!
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// nCompressOption - flag: DENC_COMPRESS_ALLWAYS,
+// DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_compressData(DEncEncryptedData* pEncData, int nCompressOption)
+{
+ int err = ERR_OK;
+ DigiDocMemBuf outData;
+ char buf[20];
+ DEncEncryptionProperty* pEncProperty;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ // check compress option
+ RETURN_IF_NOT(nCompressOption == DENC_COMPRESS_ALLWAYS ||
+ nCompressOption == DENC_COMPRESS_BEST_EFFORT, ERR_COMPRESS)
+ // check data status - cannot compress encrypted data!!!
+ if(pEncData->nDataStatus != DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ //AM 30.04.08 2048 instead of 1024
+ outData.nLen = pEncData->mbufEncryptedData.nLen + 2048; // it should get smaller
+ outData.pMem = malloc(outData.nLen);
+ if(!outData.pMem)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ err = compress OF(( (Bytef *)outData.pMem, (uLongf *)&outData.nLen,
+ (const Bytef *)pEncData->mbufEncryptedData.pMem, (uLong)pEncData->mbufEncryptedData.nLen));
+ ddocDebug(3, "dencEncryptedData_compressData", "Orig len: %d, compressed: %d, RC: %d",
+ pEncData->mbufEncryptedData.nLen, outData.nLen, err);
+ if(err != Z_OK) {
+ free(outData.pMem);
+ SET_LAST_ERROR_RETURN(ERR_COMPRESS, ERR_COMPRESS)
+ }
+ if(!err &&
+ ((nCompressOption == DENC_COMPRESS_ALLWAYS) ||
+ (nCompressOption == DENC_COMPRESS_BEST_EFFORT &&
+ outData.nLen < pEncData->mbufEncryptedData.nLen))) {
+ snprintf(buf, sizeof(buf), "%d", (int)(pEncData->mbufEncryptedData.nLen));
+ err = dencEncryptionProperty_new(pEncData, &pEncProperty,
+ NULL, NULL, ENCPROP_ORIG_SIZE, buf);
+ free(pEncData->mbufEncryptedData.pMem);
+ pEncData->mbufEncryptedData.pMem = outData.pMem;
+ pEncData->mbufEncryptedData.nLen = outData.nLen;
+ pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED;
+ // store original mime type
+ if(pEncData->szMimeType) {
+ pEncProperty = 0;
+ err = dencEncryptionProperty_new(pEncData, &pEncProperty,
+ NULL, NULL, ENCPROP_ORIG_MIME, pEncData->szMimeType);
+ free(pEncData->szMimeType);
+ }
+ pEncData->szMimeType = (char*)strdup(DENC_ENCDATA_MIME_ZLIB);
+ } else
+ free(outData.pMem);
+ return err;
+}
+
+//--------------------------------------------------
+// Decompresses data with ZLIB.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// nCompressOption - flag: DENC_COMPRESS_ALLWAYS,
+// DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptedData_decompressData(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK;
+ long origLen;
+ DigiDocMemBuf outData;
+ DEncEncryptionProperty* pEncProp;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ // check data status - cannot decompress encrypted data!!!
+ if(pEncData->nDataStatus != DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ // find original data size
+ pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_SIZE);
+ if(pEncProp && pEncProp->szContent) {
+ origLen = atol(pEncProp->szContent);
+ outData.nLen = (int)origLen;
+ } else
+ SET_LAST_ERROR_RETURN(ERR_DECOMPRESS, ERR_DECOMPRESS)
+ outData.pMem = malloc(outData.nLen);
+ if(!outData.pMem)
+ SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC)
+ err = uncompress OF(( (Bytef *)outData.pMem, (uLongf *)&outData.nLen,
+ (const Bytef *)pEncData->mbufEncryptedData.pMem, (uLong)pEncData->mbufEncryptedData.nLen));
+ ddocDebug(3, "dencEncryptedData_decompressData", "Compressed len: %d, orig-len: %ld, uncompressed: %d, RC: %d",
+ pEncData->mbufEncryptedData.nLen, origLen, outData.nLen, err);
+ if(err != Z_OK) {
+ free(outData.pMem);
+ SET_LAST_ERROR_RETURN(ERR_DECOMPRESS, ERR_DECOMPRESS)
+ }
+ if(!err) {
+ free(pEncData->mbufEncryptedData.pMem);
+ pEncData->mbufEncryptedData.pMem = outData.pMem;
+ pEncData->mbufEncryptedData.nLen = outData.nLen;
+ pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED;
+ if(pEncData->szMimeType)
+ free(pEncData->szMimeType);
+ // restor original mime type ?
+ pEncData->szMimeType = 0;
+ // find original mime type
+ pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_MIME);
+ if(pEncProp && pEncProp->szContent)
+ pEncData->szMimeType = (char*)strdup(pEncProp->szContent);
+ } else
+ free(outData.pMem);
+ return err;
+}
+
+//--------------------------------------------------
+// Encrypts a file and writes it to output file
+// The caller must have initialized the transport keys
+// but not the data.
+// pEncData - pointer to DEncEncryptedData object [REQUIRED]
+// szInputFileName - input data name [REQUIRED]
+// szOutputFileName - output file name [REQUIRED]
+// szMimeType - input data mime type [OPTIONAL]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencEncryptFile(DEncEncryptedData* pEncData,
+ const char* szInputFileName, const char* szOutputFileName,
+ const char* szMimeType)
+{
+ int err = ERR_OK, l1, l2, l3, i, nBlock;
+ long lOrigLen, lEncSize, lWritten;
+ EVP_CIPHER_CTX ectx;
+ EVP_ENCODE_CTX bctx;
+ char convInFileName[250], convOutFileName[250];
+ char buf1[4096], buf2[5120], buf3[6144], buf4[70], *p2;
+ DigiDocMemBuf mbuf;
+ FILE *hInFile, *hOutFile;
+ DEncEncryptionProperty* pEncProperty;
+
+ RETURN_IF_NULL_PARAM(pEncData)
+ RETURN_IF_NULL_PARAM(szInputFileName)
+ RETURN_IF_NULL_PARAM(szOutputFileName)
+ ddocDebug(3, "dencEncryptFile", "In-file: %s, out-file: %s, key: %d",
+ szInputFileName, szOutputFileName, pEncData->mbufTransportKey.nLen);
+ // check data status - must be uninitialized since we will read it from file
+ if(pEncData->nDataStatus != DENC_DATA_STATUS_UNINITIALIZED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS)
+ // check key status - must have been initialized already!
+ if(pEncData->nKeyStatus == DENC_KEY_STATUS_UNINITIALIZED)
+ SET_LAST_ERROR_RETURN(ERR_DENC_KEY_STATUS, ERR_DENC_KEY_STATUS)
+ // convert filenames
+ ddocConvertFileName( convInFileName, sizeof(convInFileName), szInputFileName );
+ ddocConvertFileName( convOutFileName, sizeof(convOutFileName), szOutputFileName );
+ if(strstr(szInputFileName, ".bdoc") || strstr(szInputFileName, ".asice"))
+ err = dencEncryptedData_SetMimeType(pEncData, "application/vnd.etsi.asic-e+zip");
+ // TODO: compress the data
+
+ // read and encrypt data
+ memset(buf4, 0, sizeof(buf4));
+ nBlock = 0;
+ if((hInFile = fopen(convInFileName, "rb")) != NULL) {
+ if((hOutFile = fopen(convOutFileName, "wb")) != NULL) {
+ // write header
+ mbuf.pMem = 0;
+ mbuf.nLen = 0;
+ err = dencGenEncryptedData_header_toXML(pEncData, &mbuf);
+ fwrite(mbuf.pMem, 1, mbuf.nLen, hOutFile);
+ ddocMemBuf_free(&mbuf);
+ // init encryption
+ EVP_CIPHER_CTX_init(&ectx);
+ // init encoding
+ EVP_EncodeInit(&bctx);
+ EVP_CipherInit_ex(&ectx, EVP_aes_128_cbc(), NULL,
+ (const unsigned char*)pEncData->mbufTransportKey.pMem,
+ (const unsigned char*)pEncData->initVector, ENCRYPT);
+ //EVP_CIPHER_CTX_set_padding(&ectx, 1);
+ lOrigLen = 0;
+ lEncSize = 0;
+ lWritten = 0;
+ // read file & encrypt & write to output
+ do {
+ memset(buf1, 0, sizeof(buf1));
+ l1 = fread(buf1, 1, sizeof(buf1), hInFile);
+ if(l1 > 0) {
+ lOrigLen += l1;
+ // padding for final block
+ if(l1 != sizeof(buf1)) {
+ l2 = 16 - (l1 % 16);
+ ddocDebug(3, "dencEncryptFile", "Original %d padding: %d, new block: %d", l1, l2, l1+l2);
+ for(i = 0; i < l2; i++)
+ buf1[l1 + i] = 0;
+ buf1[l1 + l2 - 1] = (unsigned char)l2;
+ l1 += l2;
+ }
+ memset(buf2, 0, sizeof(buf2));
+ l2 = sizeof(buf2);
+ p2 = buf2;
+ // first block of encrypted data will contain
+ // not encrypted IV vector in the first 16 bytes
+ if(nBlock == 0) {
+ memcpy(buf2, pEncData->initVector, 16);
+ p2 += 16;
+ l2 -= 16;
+ }
+ EVP_CipherUpdate(&ectx, (unsigned char*)p2, &l2, (const unsigned char*)buf1, l1);
+ ddocDebug(3, "dencEncryptFile", "Input: %d, block: %d, buf: %d encrypted: %d", l1, nBlock, sizeof(buf2), l2);
+ lEncSize += l2;
+ // if it's the final block
+ if(l1 != sizeof(buf1)) {
+ l3 = sizeof(buf2) - l2;
+ p2 = buf2 + l2;
+ if(nBlock == 0) {
+ p2 += 16;
+ l3 -= 16;
+ }
+ EVP_CipherFinal_ex(&ectx, (unsigned char*)p2, &l3);
+ ddocDebug(3, "dencEncryptFile", "Buf: %d Final encrypted: %d", sizeof(buf2) - l2, l3);
+ l2 += l3;
+ lEncSize += l3;
+ }
+ // base64 encode
+ l3 = sizeof(buf3);
+ memset(buf3, 0, l3);
+ // encode also the IV vector at the beginning of first block
+ if(nBlock == 0)
+ l2 += 16;
+ EVP_EncodeUpdate(&bctx, (unsigned char*)buf3, &l3, (byte*)buf2, l2);
+ lWritten += l3;
+ fwrite(buf3, 1, l3, hOutFile);
+ ddocDebug(3, "dencEncryptFile", "In: %d, encrypted: %d, base64: %d", l1, l2, l3);
+ }
+ nBlock++;
+ } while(!err && l1 > 0);
+ EVP_CIPHER_CTX_cleanup(&ectx);
+ // write the last portion of line data
+ l3 = sizeof(buf3);
+ memset(buf3, 0, l3);
+ EVP_EncodeFinal(&bctx, (unsigned char*)buf3, &l3);
+ lWritten += l3;
+ fwrite(buf3, 1, l3, hOutFile);
+ ddocDebug(4, "dencEncryptFile", "Total input: %d, blocks: %d, encrypted: %d written: %d", lOrigLen, nBlock, lEncSize, lWritten);
+ // setup encryption properties
+ snprintf(buf1, sizeof(buf1), "%ld", lOrigLen);
+ pEncProperty = 0;
+ err = dencEncryptionProperty_new(pEncData, &pEncProperty,
+ NULL, NULL, ENCPROP_ORIG_SIZE, buf1);
+ pEncProperty = 0;
+ err = dencEncryptionProperty_new(pEncData, &pEncProperty,
+ NULL, NULL, ENCPROP_FILENAME, szInputFileName);
+ // write trailer
+ mbuf.pMem = 0;
+ mbuf.nLen = 0;
+ err = dencGenEncryptedData_trailer_toXML(pEncData, &mbuf);
+ fwrite(mbuf.pMem, 1, mbuf.nLen, hOutFile);
+ ddocMemBuf_free(&mbuf);
+ fclose(hOutFile);
+ } else {
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE);
+ ddocDebug(1, "dencEncryptFile", "Error writing encrypted document: %s", convOutFileName);
+ }
+ fclose(hInFile);
+ } else {
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ);
+ ddocDebug(1, "dencEncryptFile", "Error reading input from file: %s", convInFileName);
+ }
+
+ return err;
+}
+
+
+//====================< RecipientInfo functions >==========================
+
+//--------------------------------------------------
+// "Constructor" of DEncRecvInfo object
+// ppRecvInfo - address of buffer for newly allocated object [REQUIRED]
+// szId - recipients id [REQUIRED]
+// szRecipient - recipient atribute [OPTIONAL]
+// szKeyName - KeyName element [OPTIONAL]
+// szCarriedKeyName - CarriedKeyName element [OPTIONAL]
+// pCert - certificate [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfo_new(DEncRecvInfo** ppRecvInfo,
+ const char* szId, const char* szRecipient,
+ const char* szKeyName, const char* szCarriedKeyName,
+ const X509* pCert)
+{
+ int err = ERR_OK;
+
+ // check input parameters
+ ddocDebug(3, "dencRecvInfo_new", "RecvInfo id: %s, recipient: %s, keyname: %s, ckeyname: %s cert: %s",
+ szId, szRecipient, szKeyName, szCarriedKeyName, (pCert ? "OK" : "NULL"));
+ RETURN_IF_NULL_PARAM(ppRecvInfo);
+ RETURN_IF_NULL_PARAM(szId);
+ RETURN_IF_NULL_PARAM(pCert);
+
+ *ppRecvInfo = (DEncRecvInfo*)malloc(sizeof(DEncRecvInfo));
+ // allocate new object
+ RETURN_IF_BAD_ALLOC(*ppRecvInfo);
+ memset(*ppRecvInfo, 0, sizeof(DEncRecvInfo));
+ // set required fields
+ if(szId) {
+ err = ddocMemAssignString((char**)&((*ppRecvInfo)->szId), szId);
+ if(err) return err;
+ }
+ (*ppRecvInfo)->pCert = (X509*)pCert;
+ // set optional fields
+ if(szRecipient) {
+ err = ddocMemAssignString((char**)&((*ppRecvInfo)->szRecipient), szRecipient);
+ if(err) return err;
+ }
+ if(szKeyName) {
+ err = ddocMemAssignString((char**)&((*ppRecvInfo)->szKeyName), szKeyName);
+ if(err) return err;
+ }
+ if(szCarriedKeyName) {
+ err = ddocMemAssignString((char**)&((*ppRecvInfo)->szCarriedKeyName), szCarriedKeyName);
+ if(err) return err;
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// "Destructor" of DEncRecvInfo object
+// pRecvInfo - address of buffer for newly allocated object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfo_free(DEncRecvInfo* pRecvInfo)
+{
+ int err = ERR_OK;
+
+ RETURN_IF_NULL_PARAM(pRecvInfo);
+ if(pRecvInfo->szId)
+ free(pRecvInfo->szId);
+ if(pRecvInfo->szRecipient)
+ free(pRecvInfo->szRecipient);
+ if(pRecvInfo->szKeyName)
+ free(pRecvInfo->szKeyName);
+ if(pRecvInfo->szCarriedKeyName)
+ free(pRecvInfo->szCarriedKeyName);
+ if(pRecvInfo->pCert)
+ X509_free(pRecvInfo->pCert);
+ return err;
+}
+
+//--------------------------------------------------
+// Replaces newlines with blanks
+// data - data with newlines
+// returns data without newlines
+//--------------------------------------------------
+char* removeNewlines(char* data)
+{
+ int i, n, j;
+ n = strlen(data);
+ for(i = j = 0; i < n; i++) {
+ if(data[i] != '\n' && data[i] != '\r') {
+ data[j] = data[i];
+ j++;
+ }
+ }
+ if(j < i)
+ data[j] = 0;
+ return data;
+}
+
+//--------------------------------------------------
+// Stores DEncRecvInfo object to configuration store
+// pRecvInfo - address of RecvInfo object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfo_store(DEncRecvInfo* pRecvInfo)
+{
+ int err = ERR_OK;
+ char key[100], *p;
+
+ RETURN_IF_NULL_PARAM(pRecvInfo);
+ RETURN_IF_NULL_PARAM(pRecvInfo->szId);
+ RETURN_IF_NULL_PARAM(pRecvInfo->pCert);
+ if(!err) {
+ snprintf(key, sizeof(key), "RECV_%s_RECIPIENT", pRecvInfo->szId);
+ if(pRecvInfo->szRecipient)
+ err = createOrReplacePrivateConfigItem(NULL, key, removeNewlines(pRecvInfo->szRecipient));
+ else
+ err = ConfigItem_delete(key);
+ }
+ if(!err) {
+ snprintf(key, sizeof(key), "RECV_%s_KEY_NAME", pRecvInfo->szId);
+ if(pRecvInfo->szKeyName)
+ err = createOrReplacePrivateConfigItem(NULL, key, removeNewlines(pRecvInfo->szKeyName));
+ else
+ err = ConfigItem_delete(key);
+ }
+ if(!err) {
+ snprintf(key, sizeof(key), "RECV_%s_CARRIED_KEY_NAME", pRecvInfo->szId);
+ if(pRecvInfo->szCarriedKeyName)
+ err = createOrReplacePrivateConfigItem(NULL, key, removeNewlines(pRecvInfo->szCarriedKeyName));
+ else
+ err = ConfigItem_delete(key);
+ }
+ if(!err && pRecvInfo->pCert) {
+ snprintf(key, sizeof(key), "RECV_%s_CERT", pRecvInfo->szId);
+ err = getCertPEM(pRecvInfo->pCert, 0, &p);
+ if(!err && p) {
+ err = createOrReplacePrivateConfigItem(NULL, key, removeNewlines(p));
+ free(p);
+ }
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// Deletes DEncRecvInfo object from configuration store
+// pRecvInfo - address of RecvInfo [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfo_delete(DEncRecvInfo* pRecvInfo)
+{
+ int err = ERR_OK;
+ char key[100];
+
+ RETURN_IF_NULL_PARAM(pRecvInfo);
+ RETURN_IF_NULL_PARAM(pRecvInfo->szId);
+ snprintf(key, sizeof(key), "RECV_%s_RECIPIENT", pRecvInfo->szId);
+ err = ConfigItem_delete(key);
+ snprintf(key, sizeof(key), "RECV_%s_KEY_NAME", pRecvInfo->szId);
+ err = ConfigItem_delete(key);
+ snprintf(key, sizeof(key), "RECV_%s_CARRIED_KEY_NAME", pRecvInfo->szId);
+ err = ConfigItem_delete(key);
+ snprintf(key, sizeof(key), "RECV_%s_CERT", pRecvInfo->szId);
+ err = ConfigItem_delete(key);
+ return err;
+}
+
+
+//--------------------------------------------------
+// Finds the DEncRecvInfo object with the given id
+// pConfStore - store to search in [OPTIONAL]. Use NULL for default
+// ppRecvInfo - address of buffer for newly allocated object [REQUIRED]
+// szId - id of the object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfo_findById(ConfigurationStore *pConfStore,
+ DEncRecvInfo** ppRecvInfo, const char* szId)
+{
+ int err = ERR_OK;
+ char key[100], *p;
+ X509* pCert = NULL;
+
+ RETURN_IF_NULL_PARAM(ppRecvInfo);
+ *ppRecvInfo = 0; // mark as not found
+ // check for existence first
+ snprintf(key, sizeof(key), "RECV_%s_CERT", szId);
+ if(pConfStore)
+ p = (char*)ConfigItem_lookup_fromStore(pConfStore, key);
+ else
+ p = (char*)ConfigItem_lookup(key);
+ if(!p) return err;
+ err = ddocDecodeX509PEMData(&pCert, (const char*)p, strlen((const char*)p));
+ if(!pCert) return err;
+ err = dencRecvInfo_new(ppRecvInfo, szId, NULL, NULL, NULL, pCert);
+ // now set the optional items if possible
+ snprintf(key, sizeof(key), "RECV_%s_RECIPIENT", szId);
+ if(pConfStore)
+ p = (char*)ConfigItem_lookup_fromStore(pConfStore, key);
+ else
+ p = (char*)ConfigItem_lookup(key);
+ if(p)
+ (*ppRecvInfo)->szRecipient = (char*)strdup(p);
+ snprintf(key, sizeof(key), "RECV_%s_KEY_NAME", szId);
+ if(pConfStore)
+ p = (char*)ConfigItem_lookup_fromStore(pConfStore, key);
+ else
+ p = (char*)ConfigItem_lookup(key);
+ if(p)
+ (*ppRecvInfo)->szKeyName = (char*)strdup(p);
+ snprintf(key, sizeof(key), "RECV_%s_CARRIED_KEY_NAME", szId);
+ if(pConfStore)
+ p = (char*)ConfigItem_lookup_fromStore(pConfStore, key);
+ else
+ p = (char*)ConfigItem_lookup(key);
+ if(p)
+ (*ppRecvInfo)->szCarriedKeyName = (char*)strdup(p);
+ return err;
+}
+
+//--------------------------------------------------
+// Returns all DEncRecvInfo objects
+// pRecvInfoList - address of the list receiving the items [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfo_findAll(DEncRecvInfoList* pRecvInfoList)
+{
+ int err = ERR_OK, i, j, k;
+ char id[50];
+ ConfigurationStore confStore;
+ DEncRecvInfo* pRecvInfo;
+
+ RETURN_IF_NULL_PARAM(pRecvInfoList);
+ pRecvInfoList->nItems = 0;
+ pRecvInfoList->pItems = NULL;
+ confStore.nItems = 0;
+ confStore.pItems = NULL;
+ // search the id's
+ err = ConfigItem_findByPrefix(&confStore, "RECV");
+ ddocDebug(4, "dencRecvInfo_findAll", "RECV items: %d", confStore.nItems);
+ for(i = 0; confStore.pItems && i < confStore.nItems; i++) {
+ j = (confStore.pItems[i] && confStore.pItems[i]->szKey) ?
+ strlen(confStore.pItems[i]->szKey) : 0;
+ if(j && !strcmp(confStore.pItems[i]->szKey + j - 4, "CERT")) {
+ j -= 6;
+ for(k = j; k > 0 && confStore.pItems[i]->szKey[k] != '_'; k--);
+ memset(id, 0, sizeof(id));
+ strncpy(id, confStore.pItems[i]->szKey + k + 1, j - k);
+ ddocDebug(4, "dencRecvInfo_findAll", "Read obj with id: %s", id);
+ err = dencRecvInfo_findById(&confStore, &pRecvInfo, id);
+ if(!err && pRecvInfo)
+ err = dencRecvInfoList_add(pRecvInfoList, pRecvInfo);
+ }
+ }
+
+ // cleanup
+ cleanupConfigStore(&confStore);
+ return err;
+}
+
+//====================< RecipientInfoList functions >==========================
+
+//--------------------------------------------------
+// Adds a DEncRecvInfo object to the list
+// pRecvInfoList - address of the list receiving the item [REQUIRED]
+// pRecvInfo - new object to be added
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfoList_add(DEncRecvInfoList* pRecvInfoList, DEncRecvInfo *pRecvInfo)
+{
+ int err = ERR_OK;
+ DEncRecvInfo** pItems;
+
+ RETURN_IF_NULL_PARAM(pRecvInfoList);
+ RETURN_IF_NULL_PARAM(pRecvInfo);
+ pItems = (DEncRecvInfo**)realloc(pRecvInfoList->pItems,
+ (pRecvInfoList->nItems + 1) * sizeof(DEncRecvInfo *));
+ RETURN_IF_BAD_ALLOC(pItems);
+ pRecvInfoList->pItems = pItems;
+ pRecvInfoList->pItems[pRecvInfoList->nItems] = pRecvInfo;
+ pRecvInfoList->nItems++;
+ return err;
+}
+
+//--------------------------------------------------
+// Frees the contents of a DEncRecvInfoList object
+// pRecvInfoList - address of the list [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfoList_free(DEncRecvInfoList* pRecvInfoList)
+{
+ int err = ERR_OK, i;
+
+ RETURN_IF_NULL_PARAM(pRecvInfoList);
+ for(i = 0; i < pRecvInfoList->nItems; i++) {
+ if(pRecvInfoList->pItems[i])
+ dencRecvInfo_free(pRecvInfoList->pItems[i]);
+ }
+ free(pRecvInfoList->pItems);
+ pRecvInfoList->pItems = 0;
+ pRecvInfoList->nItems = 0;
+ return err;
+}
+
+//--------------------------------------------------
+// Removes the given DEncRecvInfo object from the list
+// pRecvInfoList - address of the list [REQUIRED]
+// szId - id of the obect to be removed [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencRecvInfoList_delete(DEncRecvInfoList* pRecvInfoList, const char* szId)
+{
+ int err = ERR_OK, i, j;
+
+ ddocDebug(4, "dencRecvInfoList_delete", "Deleting id: %s orig-len: %d", szId, pRecvInfoList->nItems);
+ RETURN_IF_NULL_PARAM(pRecvInfoList);
+ RETURN_IF_NULL_PARAM(szId);
+ for(i = j = 0; i < pRecvInfoList->nItems; i++) {
+ if(pRecvInfoList->pItems[j] &&
+ pRecvInfoList->pItems[j]->szId &&
+ !strcmp(pRecvInfoList->pItems[j]->szId, szId)) {
+ free(pRecvInfoList->pItems[j]);
+ ddocDebug(4, "dencRecvInfoList_delete", "Dleting item on pos: %d", j);
+ } else {
+ pRecvInfoList->pItems[j] = pRecvInfoList->pItems[i];
+ j++;
+ }
+ }
+ pRecvInfoList->nItems = j;
+ ddocDebug(4, "dencRecvInfoList_delete", "remaining-len: %d", pRecvInfoList->nItems);
+ return err;
+}
+
+//====================< original content functions >===================
+
+//--------------------------------------------------
+// Returns the count of "orig_file" properties
+// pEncData - EncryptedData object [REQUIRED]
+// returns count or -1 for error.
+//--------------------------------------------------
+EXP_OPTION int dencOrigContent_count(DEncEncryptedData* pEncData)
+{
+ int nCount = 0, i, n;
+ DEncEncryptionProperty* pEncProp = 0;
+ char* pName;
+
+ SET_LAST_ERROR_RETURN_IF_NOT(pEncData, ERR_NULL_POINTER, -1)
+ n = dencEncryptedData_GetEncryptionPropertiesCount(pEncData);
+ for(i = 0; i < n; i++) {
+ pEncProp = (DEncEncryptionProperty*)dencEncryptedData_GetEncryptionProperty(pEncData, i);
+ if(pEncProp) {
+ pName = (char*)dencEncryptionProperty_GetName(pEncProp);
+ if(pName && !strcmp(pName, ENCPROP_ORIG_CONTENT))
+ nCount++;
+ }
+ }
+ return nCount;
+}
+
+//--------------------------------------------------
+// Creates a new property of type "orig_file"
+// pEncData - EncryptedData object [REQUIRED]
+// szOrigContentId - Id atribute for new Property object [OPTIONAL]
+// szName - original file name [REQUIRED]
+// szSize - size as string or irginal file [REQUIRED]
+// szMime - mime type or original file [REQUIRED]
+// szDfId - Id atribute of original file [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencOrigContent_add(DEncEncryptedData* pEncData, const char* szOrigContentId,
+ const char* szName, const char* szSize, const char* szMime, const char* szDfId)
+{
+ int err = ERR_OK, l1 = 0;
+ char* p1 = 0;
+ DEncEncryptionProperty* pEncProp = 0;
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ RETURN_IF_NULL_PARAM(szName);
+ RETURN_IF_NULL_PARAM(szSize);
+ RETURN_IF_NULL_PARAM(szMime);
+ RETURN_IF_NULL_PARAM(szDfId);
+ l1 = strlen(szName) + strlen(szSize) + strlen(szMime) + strlen(szDfId) + 10;
+ p1 = (char*)malloc(l1);
+ RETURN_IF_BAD_ALLOC(p1);
+ memset(p1, 0, l1);
+ snprintf(p1, l1, "%s|%s|%s|%s", szName, szSize, szMime, szDfId);
+ err = dencEncryptionProperty_new(pEncData, &pEncProp, szOrigContentId,
+ NULL, ENCPROP_ORIG_CONTENT, p1);
+ if(p1)
+ free(p1);
+ return err;
+}
+
+
+//--------------------------------------------------
+// Returns the info from "orig_file" properties
+// pEncData - EncryptedData object [REQUIRED]
+// szOrigContentId - Id atribute for new Property object [OPTIONAL]
+// szName - buffer for original file name [REQUIRED]
+// nNameLen - buffer length of szName [REQUIRED]
+// szSize - buffer for size as string or irginal file [REQUIRED]
+// nSizeLen - buffer length of szSize [REQUIRED]
+// szMime - buffer for mime type or original file [REQUIRED]
+// nMimeLen - buffer length of szMime [REQUIRED]
+// szDfId - buffer for Id atribute of original file [REQUIRED]
+// nDfIdLen - buffer length of szDfId [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencOrigContent_findByIndex(DEncEncryptedData* pEncData, int origContIdx,
+ char* szName, int nNameLen, char* szSize, int nSizeLen,
+ char* szMime, int nMimeLen, char* szDfId, int nDfIdLen)
+{
+ int nCount = -1, i, n, j, k, l, m;
+ DEncEncryptionProperty* pEncProp = 0;
+ char *p1;
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ RETURN_IF_NULL_PARAM(szName);
+ RETURN_IF_NULL_PARAM(szSize);
+ RETURN_IF_NULL_PARAM(szMime);
+ RETURN_IF_NULL_PARAM(szDfId);
+ memset(szName, 0, nNameLen);
+ memset(szSize, 0, nSizeLen);
+ memset(szMime, 0, nMimeLen);
+ memset(szDfId, 0, nDfIdLen);
+ n = dencEncryptedData_GetEncryptionPropertiesCount(pEncData);
+ for(i = 0; i < n; i++) {
+ pEncProp = (DEncEncryptionProperty*)dencEncryptedData_GetEncryptionProperty(pEncData, i);
+ if(pEncProp) {
+ p1 = (char*)dencEncryptionProperty_GetName(pEncProp);
+ if(p1 && !strcmp(p1, ENCPROP_ORIG_CONTENT))
+ nCount++;
+ ddocDebug(4, "dencOrigContent_findByIndex", "Prop: %d, name: %s count: %d", i, p1, nCount);
+ if(nCount == origContIdx && p1 && !strcmp(p1, ENCPROP_ORIG_CONTENT)) {
+ p1 = (char*)dencEncryptionProperty_GetContent(pEncProp);
+ ddocDebug(4, "dencOrigContent_findByIndex", "Prop: %d, count: %d, content: %s", i, nCount, p1);
+ if(p1) {
+ k = strlen(p1);
+ for(j = l = m = 0; j < k; j++) {
+ if(p1[j] == '|') {
+ l = 0;
+ m++;
+ } else {
+ switch(m) {
+ case 0: if(l < nNameLen) szName[l] = p1[j]; l++; break;
+ case 1: if(l < nSizeLen) szSize[l] = p1[j]; l++; break;
+ case 2: if(l < nMimeLen) szMime[l] = p1[j]; l++; break;
+ case 3: if(l < nDfIdLen) szDfId[l] = p1[j]; l++; break;
+ }
+ }
+ }
+ ddocDebug(4, "dencOrigContent_findByIndex", "Prop: %d, name: %s size: %s, mime: %s, id: %s", i, szName, szSize, szMime, szDfId);
+ }
+ }
+ }
+ }
+ if(!szName[0] && !szSize[0]) { // if not property name="orig_files" was not found then use Filename and OriginalSize
+ for(i = 0; i < n; i++) {
+ pEncProp = (DEncEncryptionProperty*)dencEncryptedData_GetEncryptionProperty(pEncData, i);
+ if(pEncProp) {
+ p1 = (char*)dencEncryptionProperty_GetName(pEncProp);
+ if(p1 && !strcmp(p1, ENCPROP_FILENAME)) {
+ p1 = (char*)dencEncryptionProperty_GetContent(pEncProp);
+ if(p1)
+ strncpy(szName, p1, nNameLen);
+ }
+ if(p1 && !strcmp(p1, ENCPROP_ORIG_SIZE)) {
+ p1 = (char*)dencEncryptionProperty_GetContent(pEncProp);
+ if(p1)
+ strncpy(szSize, p1, nSizeLen);
+ }
+ }
+ }
+ }
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Checks if there is a digidoc document in this
+// encrypted document.
+// pEncData - EncryptedData object [REQUIRED]
+// returns 1 if digidoc document is inside
+//--------------------------------------------------
+EXP_OPTION int dencOrigContent_isDigiDocInside(DEncEncryptedData* pEncData)
+{
+ int i, n;
+ DEncEncryptionProperty* pEncProp = 0;
+ char *p1, *p2;
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ if(pEncData->szMimeType && !strcmp(pEncData->szMimeType, DENC_ENCDATA_TYPE_DDOC)) {
+ ddocDebug(3, "dencOrigContent_isDigiDocInside", "mime: %s", pEncData->szMimeType);
+ return 1;
+ }
+ n = dencEncryptedData_GetEncryptionPropertiesCount(pEncData);
+ ddocDebug(3, "dencOrigContent_isDigiDocInside", "Props: %d", n);
+ for(i = 0; i < n; i++) {
+ pEncProp = (DEncEncryptionProperty*)dencEncryptedData_GetEncryptionProperty(pEncData, i);
+ if(pEncProp) {
+ p1 = (char*)dencEncryptionProperty_GetName(pEncProp);
+ ddocDebug(3, "dencOrigContent_isDigiDocInside", "Prop: %d name: %s", i, p1);
+ if(p1 && !strcmp(p1, ENCPROP_ORIG_MIME)) {
+ p2 = (char*)dencEncryptionProperty_GetContent(pEncProp);
+ ddocDebug(3, "dencOrigContent_isDigiDocInside", "Prop: %d mime: %s", i, p2);
+ if(p2 && !strcmp(p2, DENC_ENCDATA_TYPE_DDOC)) {
+ ddocDebug(3, "dencOrigContent_isDigiDocInside", "Name: %s mime: %s", p1, p2);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+//--------------------------------------------------
+// Registers digidoc document as encrypted datatype
+// and stores it's data file info.
+// pEncData - EncryptedData object [REQUIRED]
+// pSigDoc - SignedDoc object [REQUIRED]
+// returns 1 if digidoc document is inside
+//--------------------------------------------------
+EXP_OPTION int dencOrigContent_registerDigiDoc(DEncEncryptedData* pEncData, SignedDoc* pSigDoc)
+{
+ int err = ERR_OK, i, n;
+ DEncEncryptionProperty* pEncProp = 0;
+ DataFile* pDf;
+ char buf[500], *sVer;
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ // set the mime type
+ sVer = (char*)ConfigItem_lookup_str("DENC_VERSION", DENC_VERSION_1_0);
+ err = dencEncryptedData_SetMimeType(pEncData, DENC_ENCDATA_TYPE_DDOC);
+ n = getCountOfDataFiles(pSigDoc);
+ for(i = 0; i < n; i++) {
+ pDf = getDataFile(pSigDoc, i);
+ if(pDf) {
+ pEncProp = 0;
+ snprintf(buf, sizeof(buf), "%s|%ld|%s|%s", getSimpleFileName(pDf->szFileName), pDf->nSize, pDf->szMimeType, pDf->szId);
+ err = dencEncryptionProperty_new(pEncData, &pEncProp,
+ NULL, NULL, ENCPROP_ORIG_CONTENT, buf);
+ }
+ }
+ return err;
+}
+
+//====================< other meta-info functions >===================
+
+//--------------------------------------------------
+// Sets the library name and version property
+// pEncData - EncryptedData object [REQUIRED]
+// returns count or -1 for error.
+//--------------------------------------------------
+EXP_OPTION int dencMetaInfo_SetLibVersion(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK;
+ DEncEncryptionProperty* pEncProp = 0;
+ char buf[500];
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ // set the library name and version
+ snprintf(buf, sizeof(buf), "%s|%s", getLibName(), getLibVersion());
+ pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_LIB_VERSION);
+ if(pEncProp) { // property exists, set the content
+ err = dencEncryptionProperty_SetContent(pEncProp, (const char*)buf);
+ } else { // create a new property
+ err = dencEncryptionProperty_new(pEncData, &pEncProp, NULL, NULL,
+ ENCPROP_LIB_VERSION, buf);
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// Sets the format name and version property
+// pEncData - EncryptedData object [REQUIRED]
+// returns count or -1 for error.
+//--------------------------------------------------
+EXP_OPTION int dencMetaInfo_SetFormatVersion(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK;
+ DEncEncryptionProperty* pEncProp = 0;
+ char buf[500];
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ // set the library name and version
+ snprintf(buf, sizeof(buf), "%s|%s", DENC_FORMAT_ENCDOC_XML, ConfigItem_lookup_str("DENC_VERSION", DENC_VERSION_1_0));
+ pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_DOC_FORMAT);
+ if(pEncProp) { // property exists, set the content
+ err = dencEncryptionProperty_SetContent(pEncProp, (const char*)buf);
+ } else { // create a new property
+ err = dencEncryptionProperty_new(pEncData, &pEncProp, NULL, NULL,
+ ENCPROP_DOC_FORMAT, buf);
+ }
+ return err;
+}
+
+
+
+//--------------------------------------------------
+// Returns the library name and version meta-info of this document
+// pEncData - EncryptedData object [REQUIRED]
+// szLibrary - buffer for library name
+// nLibLen - length of library name buffer
+// szVersion - buffer for version info
+// nVerLen - length of version info buffer
+// returns count or -1 for error.
+//--------------------------------------------------
+EXP_OPTION int dencMetaInfo_GetLibVersion(DEncEncryptedData* pEncData, char* szLibrary, int nLibLen, char* szVersion, int nVerLen)
+{
+ int err = ERR_OK, i, j, n;
+ DEncEncryptionProperty* pEncProp = 0;
+ char *p1;
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ RETURN_IF_NULL_PARAM(szLibrary);
+ RETURN_IF_NULL_PARAM(szVersion);
+ // mark as not found
+ memset(szLibrary, 0, nLibLen);
+ memset(szVersion, 0, nVerLen);
+ pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_LIB_VERSION);
+ if(pEncProp) { // property exists, set the content
+ p1 = (char*)dencEncryptionProperty_GetContent(pEncProp);
+ if(p1) {
+ for(i = j = n = 0; p1[i]; i++) {
+ if(p1[i] == '|' && j < nLibLen - 1) {
+ szLibrary[j] = 0;
+ j = 0;
+ n++;
+ continue;
+ } else {
+ if(!n) {
+ if(j < nLibLen - 1)
+ szLibrary[j++] = p1[i];
+ } else {
+ if(j < nVerLen - 1)
+ szVersion[j++] = p1[i];
+ }
+ }
+ }
+ }
+ } return err;
+}
+
+
+//--------------------------------------------------
+// Returns the format name and version meta-info of this document
+// pEncData - EncryptedData object [REQUIRED]
+// returns count or -1 for error.
+//--------------------------------------------------
+EXP_OPTION int dencMetaInfo_GetFormatVersion(DEncEncryptedData* pEncData, char* szFormat, int nFormat, char* szVersion, int nVersion)
+{
+ int err = ERR_OK, i, j, n;
+ DEncEncryptionProperty* pEncProp = 0;
+ char *p1;
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ RETURN_IF_NULL_PARAM(szFormat);
+ RETURN_IF_NULL_PARAM(szVersion);
+ // mark as not found
+ memset(szFormat, 0, nFormat);
+ memset(szVersion, 0, nVersion);
+ pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_DOC_FORMAT);
+ if(pEncProp) { // property exists, set the content
+ p1 = (char*)dencEncryptionProperty_GetContent(pEncProp);
+ if(p1) {
+ for(i = j = n = 0; p1[i]; i++) {
+ if(p1[i] == '|' && j < nFormat - 1) {
+ szFormat[j] = 0;
+ j = 0;
+ n++;
+ continue;
+ } else {
+ if(!n) {
+ if(j < nFormat - 1)
+ szFormat[j++] = p1[i];
+ } else {
+ if(j < nVersion - 1)
+ szVersion[j++] = p1[i];
+ }
+ }
+ }
+ }
+ } return err;
+}
+
+//--------------------------------------------------
+// Deletes the meta-info properties
+// pEncData - EncryptedData object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencMetaInfo_deleteVersionInfo(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK, i, j;
+
+ RETURN_IF_NULL_PARAM(pEncData);
+ // delete doc-format property
+ j = -1;
+ for(i = 0; i < pEncData->encProperties.nEncryptionProperties; i++) {
+ if(pEncData->encProperties.arrEncryptionProperties[i] &&
+ pEncData->encProperties.arrEncryptionProperties[i]->szName &&
+ !strcmp(pEncData->encProperties.arrEncryptionProperties[i]->szName, ENCPROP_DOC_FORMAT)) {
+ j = i;
+ break;
+ }
+ }
+ if(j >= 0)
+ err = dencEncryptedData_DeleteEncryptionProperty(pEncData, j);
+ // delete lib-version property
+ j = -1;
+ for(i = 0; i < pEncData->encProperties.nEncryptionProperties; i++) {
+ if(pEncData->encProperties.arrEncryptionProperties[i] &&
+ pEncData->encProperties.arrEncryptionProperties[i]->szName &&
+ !strcmp(pEncData->encProperties.arrEncryptionProperties[i]->szName, ENCPROP_LIB_VERSION)) {
+ j = i;
+ break;
+ }
+ }
+ if(j >= 0)
+ err = dencEncryptedData_DeleteEncryptionProperty(pEncData, j);
+ return err;
+}
+
+
+//--------------------------------------------------
+// Validates cdoc structure
+// pEncData - EncryptedData object [REQUIRED]
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int dencValidate(DEncEncryptedData* pEncData)
+{
+ int err = ERR_OK, i;
+ char* p1 = 0;
+ char errbuf[300];
+ X509* pCert = 0;
+
+ if(!pEncData) {
+ printf("\nERROR: 164 Invalid format. No <EncryptedData> found!");
+ SET_LAST_ERROR_RETURN_CODE(ERR_VALIDATE);
+ }
+ // xmlns
+ p1 = (char*)dencEncryptedData_GetXmlNs(pEncData);
+ if(!p1 || strcmp(p1, DENC_XMLNS_XMLENC)) {
+ printf("\nERROR: 164 Invalid xmlns attribute: %s. xmlns attribute is required atribute and only valid value is: %s\n", (p1 ? p1 : ""), DENC_XMLNS_XMLENC);
+ err = ERR_VALIDATE;
+ }
+ // <EncryptionMethod>
+ p1 = (char*)dencEncryptedData_GetEncryptionMethod(pEncData);
+ if(!p1 || strcmp(p1, DENC_ENC_METHOD_AES128)) {
+ printf("\nERROR: 164 Invalid EncryptedData encryption method: %s. Encryption method is required atribute and only valid value is: %s\n", (p1 ? p1 : ""), DENC_ENC_METHOD_AES128);
+ err = ERR_VALIDATE;
+ }
+ // encrypted data itself
+ if(!pEncData->mbufEncryptedData.pMem || !pEncData->mbufEncryptedData.nLen) {
+ printf("\nERROR: 164 empty cdoc! This <EncryptedData> element has no encrypted data!\n");
+ err = ERR_VALIDATE;
+ }
+ // encryption properties
+ for(i = 0; i < dencEncryptedData_GetEncryptionPropertiesCount(pEncData); i++) {
+ DEncEncryptionProperty* pEncProp = dencEncryptedData_GetEncryptionProperty(pEncData, i);
+ if(pEncProp) {
+ p1 = (char*)dencEncryptionProperty_GetName(pEncProp);
+ if(!p1 || !strlen(p1)) {
+ printf("\nERROR: 164 Invalid encryption property: %d. Encryption property name attribute is required and may not be empty!\n", i);
+ err = ERR_VALIDATE;
+ }
+ p1 = (char*)dencEncryptionProperty_GetContent(pEncProp);
+ if(!p1 || !strlen(p1)) {
+ printf("\nERROR: 164 Invalid encryption property: %d. Encryption property content may not be empty!\n", i);
+ err = ERR_VALIDATE;
+ }
+ }
+ }
+ if(!dencEncryptedData_GetEncryptedKeyCount(pEncData)) {
+ printf("\nERROR: 164 Invalid cdoc. This cdoc has no EncryptedKey elements!\n");
+ err = ERR_VALIDATE;
+ }
+ // encrypted keys
+ for(i = 0; i < dencEncryptedData_GetEncryptedKeyCount(pEncData); i++) {
+ DEncEncryptedKey* pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i);
+ // encryption method
+ p1 = (char*)dencEncryptedKey_GetEncryptionMethod(pEncKey);
+ if(!p1 || strcmp(p1, DENC_ENC_METHOD_RSA1_5)) {
+ printf("\nERROR: 164 Invalid EncryptedKey encryption method: %s. Encryption method is required atribute and only valid value is: %s\n", (p1 ? p1 : ""), DENC_ENC_METHOD_RSA1_5);
+ err = ERR_VALIDATE;
+ }
+ // recipients cert
+ pCert = dencEncryptedKey_GetCertificate(pEncKey);
+ if(!pCert) {
+ printf("\nERROR: 164 Invalid encrypted key: %d. Recipients certificate is required!\n", i);
+ err = ERR_VALIDATE;
+ } else {
+ if(!ddocCertCheckKeyUsage(pCert, KUIDX_DATA_ENCIPHERMENT)) {
+ printf("\nERROR: 164 RecipientsCertificate is not suitable for encryption - keyEncipherment flag not set!\n");
+ err = ERR_VALIDATE;
+ }
+ }
+ }
+
+ // xmlns
+ if(err)
+ SET_LAST_ERROR(err);
+ return err;
+}
+