diff options
Diffstat (limited to 'libdigidoc/DigiDocEnc.c')
-rw-r--r-- | libdigidoc/DigiDocEnc.c | 2743 |
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; +} + |