summaryrefslogtreecommitdiff
path: root/libdigidoc/DigiDocCsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdigidoc/DigiDocCsp.c')
-rw-r--r--libdigidoc/DigiDocCsp.c2229
1 files changed, 2229 insertions, 0 deletions
diff --git a/libdigidoc/DigiDocCsp.c b/libdigidoc/DigiDocCsp.c
new file mode 100644
index 0000000..ee0081b
--- /dev/null
+++ b/libdigidoc/DigiDocCsp.c
@@ -0,0 +1,2229 @@
+//==================================================
+// FILE: DigiDocCsp.c
+// PROJECT: Digi Doc
+// DESCRIPTION: Digi Doc functions for creating
+// and reading signed documents.
+// 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 >=============================
+// 20.10.2004 Changed createOCSPRequest, added SignedDoc parameeter
+// 10.02.2004 Changed decodeCertificateData
+// ReadCertSerialNumber
+// ReadCertificate
+// NotaryInfo_new
+// 01.02.2004 Aare Amenberg
+// from comments "Functions from EstIDLib.c"
+// functions from EstIdLib.c file
+// 20.11.2003 Aare Amenberg
+// removed tes2.resp file creating
+// 29.10.2003 Created by AA
+//
+//==================================================
+#ifdef WIN32
+
+#define WIN32_PKCS 1
+
+#include <windows.h>
+#include <wincrypt.h>
+#include <libdigidoc/DigiDocDefs.h>
+#include <libdigidoc/DigiDocLib.h>
+#include <libdigidoc/DigiDocCert.h>
+#include <libdigidoc/DigiDocMem.h>
+#include <libdigidoc/DigiDocConfig.h>
+#include <libdigidoc/DigiDocOCSP.h>
+#include <libdigidoc/DigiDocObj.h>
+#include <libdigidoc/DigiDocGen.h>
+#include <libdigidoc/DigiDocVerify.h>
+#include <libdigidoc/DigiDocConvert.h>
+#include <libdigidoc/DigiDocDebug.h>
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#include <assert.h>
+#include <malloc.h>
+#include <direct.h>
+
+#include <fcntl.h>
+#include <time.h>
+
+
+#include <openssl/sha.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/ocsp.h>
+#include <openssl/pkcs12.h>
+
+#include <libxml/globals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h> /* only for xmlNewInputFromFile() */
+#include <libxml/tree.h>
+#include <libxml/debugXML.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/c14n.h>
+
+#include "DigiCrypt.h"
+#include "DigiDocCert.h"
+
+#include "DigiDocCsp.h"
+
+CSProvider * cCSProvider;
+CSProvider * knownCSProviders[3];
+
+
+//AARE01102003
+typedef struct StoreHandle_st {
+ HCERTSTORE hHandle;
+ BOOL fRoot;
+} StoreHandle;
+
+
+BOOL Digi_OpenStore(StoreHandle *hStore);
+void Digi_CloseStore(StoreHandle *hStore);
+BOOL Digi_IsValidResponderCert(PCCERT_CONTEXT pCert);
+
+X509 * Digi_FindX509CopyFromStore(StoreHandle *hStore, X509 *pX509cert);
+X509 *Digi_FindResponderCert(StoreHandle *hStore, X509 *poSignerCert);
+char *Digi_GetName(X509_NAME *pName);
+BOOL Digi_CheckEnhancedKeyUsage(PCCERT_CONTEXT pCert, char *psValue);
+X509 *Digi_FindCertByResponse(StoreHandle *hStore, OCSP_RESPONSE *poResponse);
+PCCERT_CONTEXT Digi_FindCertBySubject(StoreHandle *hStore,char *psCN, BOOL bCheckValid, const char* szSerialNr, BOOL bCA);
+BOOL Digi_CompareCN(char *psSub1, char *psSub2);
+X509 **Digi_MakeCertList(X509 *poX509Main, StoreHandle *hStore);
+X509 **Digi_MakeCertListLow(X509 *poX509Main, StoreHandle *hStore);
+BOOL Digi_CheckResponderCertByResponse(X509 *poX509Responder, OCSP_RESPONSE *poResponse);
+
+void Digi_FreeCertList(X509 **caCerts);
+BOOL Digi_IsCert1SubjectDNEqualCert2IssuerDN(X509 *pCert1, X509 *pCert2);
+int ReadTestAare(char *pkcs12file);
+int Test_ReadCertData(X509 *poX509);
+int Test_ReadCertDataC(PCCERT_CONTEXT pCert);
+
+// Reads a certificate from pkcs12 container
+EXP_OPTION int Digi_readCertificateByPKCS12OnlyCertHandle(const char *pkcs12file, const char * passwd, X509 **x509);
+int Digi_getConfirmationWithCertSearch(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, char* pkcs12File, char* password,
+ char* notaryURL, char* proxyHost, char* proxyPort);
+//int Digi_setNotaryCertificate(NotaryInfo* pNotary, X509* notCert);
+int Digi_verifyNotaryInfoWithCertSearch(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo);
+
+// verifies this one signature
+int Digi_verifySignatureInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo,
+ const char* szDataFile);
+// verifies the whole document (returns on first err)
+int Digi_verifySigDoc(const SignedDoc* pSigDoc, const char* szDataFile);
+int Digi_verifySigDocWithCertSearch(const SignedDoc* pSigDoc, const char* szDataFile);
+int Digi_verifyNotaryInfoCERT(const SignedDoc* pSigDoc,
+ const NotaryInfo* pNotInfo,
+ const X509** caCerts,
+ const X509* notCert,
+ const X509* pSigCA);
+//int Digi_initializeNotaryInfoWithOCSP(SignedDoc* pSigDoc, NotaryInfo* pNotary,
+// OCSP_RESPONSE* resp, X509* notCert, int initDigest);
+
+
+// verifies signed doc
+int verifySigDoc_ByCertStore(const SignedDoc* pSigDoc, const char* szDataFile);
+// Verifies this signature
+int verifySignatureInfo_ByCertStore(const SignedDoc* pSigDoc,
+ const SignatureInfo* pSigInfo, const char* szDataFile);
+// Verfies NotaryInfo signature
+int verifyNotaryInfo_ByCertStore(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo);
+
+// resolves certificate chain from MS CertStore upto root cert
+int resolveCertChain_ByCertStore(CertItem* pListStart);
+
+int GetAllCertificatesFromStore(const CertSearchStore *sS, CertItem **certList, int *numberOfCerts);
+void prepareString(const char * strIN,char * strOUT);
+void reverseArray(unsigned char *array, unsigned long arrayLen);
+
+extern int setup_verifyCERT(X509_STORE **newX509_STORE, const char *CApath, const X509** certs);
+
+extern X509_ALGOR* setSignAlgorithm(const EVP_MD * type);
+
+extern EXP_OPTION int signOCSPRequestPKCS12(OCSP_REQUEST *req, const char* filename, const char* passwd);
+
+
+extern LPBYTE getDefaultKeyName(CSProvider * cProvider);
+//extern CERT_PUBLIC_KEY_INFO * getCardKeyInfo(const char * ppContainerName);
+extern int GetCertificateFromStore(const CertSearchStore *sS, X509 **x509);
+extern int GetSignedHashWithEstIdCSPkey(const char * dataToBeSigned,unsigned long dataLen,unsigned char *pbKeyBlob, unsigned long *pbKeyBlobLen,unsigned char *hash, unsigned long *hashLen, unsigned char * hashedSignature,unsigned long * sigLen);
+extern int GetSignedHashWithKeyAndCSP(char *psKeyName, char *psCSPName, const char * dataToBeSigned,unsigned long dataLen,unsigned char *pbKeyBlob, unsigned long *pbKeyBlobLen,unsigned char *hash, unsigned long *hashLen, unsigned char * hashedSignature,unsigned long * sigLen, const char*
+);
+extern X509 * findIssuerCertificatefromStore(X509 *x509);
+X509* Digi_FindDirectCA(X509 *poX509Main, StoreHandle *hStore);
+
+X509* Digi_FindCertBySubjectAndHash(StoreHandle *hStore, char *psCN, BOOL bCheckValid, const char* szSerialNr, BOOL bCA, DigiDocMemBuf *pHash);
+
+//==========< macros >====================
+
+#define SET_LAST_ERROR(code) (addError((code), __FILE__, __LINE__, ""))
+#define SET_LAST_ERROR_IF_NOT(expr, code) { if(!(expr)) addError((code), __FILE__, __LINE__, #expr); }
+#define SET_LAST_ERROR_RETURN(code, retVal) { SET_LAST_ERROR(code); return (retVal); }
+#define SET_LAST_ERROR_RETURN_IF_NOT(expr, code, retVal) { if(!(expr)) { addError((code), __FILE__, __LINE__, #expr); return (retVal); } }
+#define SET_LAST_ERROR_RETURN_VOID_IF_NOT(expr, code) { if(!(expr)) { addError((code), __FILE__, __LINE__, #expr); return; } }
+#define RETURN_IF_NOT(expr, code) SET_LAST_ERROR_RETURN_IF_NOT((expr), (code), (code));
+#define RETURN_IF_NULL(p) RETURN_IF_NOT((p), ERR_NULL_POINTER);
+#define RETURN_VOID_IF_NULL(p) SET_LAST_ERROR_RETURN_VOID_IF_NOT((p), ERR_NULL_POINTER);
+#define RETURN_OBJ_IF_NULL(p, obj) SET_LAST_ERROR_RETURN_IF_NOT((p), ERR_NULL_POINTER, (obj));
+#define SET_LAST_ERROR_RETURN_CODE(code) { SET_LAST_ERROR(code); return (code); }
+
+//========================================
+
+
+BOOL Digi_OpenStore(StoreHandle *hStore)
+{
+ BOOL fRes = FALSE;
+ if (hStore != NULL) {
+ memset(hStore,0,sizeof(StoreHandle));
+ hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL,
+ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"CA");
+ if (hStore->hHandle != NULL)
+ fRes = TRUE;
+ }
+ return(fRes);
+}
+
+void Digi_CloseStore(StoreHandle *hStore)
+{
+if (hStore != NULL && hStore->hHandle)
+ CertCloseStore(hStore->hHandle,CERT_CLOSE_STORE_FORCE_FLAG);
+hStore->hHandle = NULL;
+hStore->fRoot = FALSE;
+}
+
+
+X509 * Digi_FindX509CopyFromStore(StoreHandle *hStore, X509 *pX509cert) {
+ X509 *pResultCert = NULL;
+ char* certBlob;
+ int certBlobLen;
+ PCCERT_CONTEXT pCertFindContext = NULL;
+ PCCERT_CONTEXT pCertContext = NULL;
+ char *psValue = "1.3.6.1.5.5.7.3.9";
+
+ if (hStore == NULL || pX509cert == NULL) return(pResultCert);
+
+ certBlobLen = i2d_X509(pX509cert, NULL) + 1000;
+ certBlob = malloc(certBlobLen);
+
+ encodeCert(pX509cert,certBlob,&certBlobLen);
+ if (!certBlob) return(pResultCert);
+
+ pCertFindContext = CertCreateCertificateContext(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,certBlob,certBlobLen);
+ if (!pCertFindContext) return(pResultCert);
+
+ pCertContext = CertFindCertificateInStore(hStore->hHandle, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0, CERT_FIND_EXISTING, pCertFindContext, NULL);
+
+ if (pCertContext) { //cert found
+ if (Digi_CheckEnhancedKeyUsage(pCertContext,psValue) != TRUE) return(pResultCert);
+ ddocDecodeX509Data(&pResultCert,pCertContext->pbCertEncoded,pCertContext->cbCertEncoded);
+ } else {
+ char schultz[300];
+ snprintf(schultz, sizeof(schultz), "CertFindCertificateInStore open failed with 0x%0lx ", GetLastError());
+ return(pResultCert);
+ }
+
+ if (certBlob) free(certBlob);
+
+ return pResultCert;
+}
+
+
+
+X509 *Digi_FindResponderCert(StoreHandle *hStore, X509 *poSignerCert)
+{
+X509 *poResultCert = NULL;
+FILETIME oResultTime;
+X509 *poX509;
+BOOL fSet;
+PCCERT_CONTEXT pCert = NULL;
+X509_NAME *poX509SignerName = NULL;
+X509_NAME *poX509CurrentName = NULL;
+
+poX509SignerName = X509_get_issuer_name(poSignerCert);
+while (pCert = CertEnumCertificatesInStore(hStore->hHandle, pCert))
+ {
+ fSet = FALSE;
+ //get handle
+ //AA100204
+ ddocDecodeX509Data(&poX509, pCert->pbCertEncoded,pCert->cbCertEncoded);
+ if (poX509 != NULL)
+ {
+ //get current cert issuer
+ poX509CurrentName = X509_get_issuer_name(poX509);
+ //TEST
+ //psTemp = Digi_GetName(poX509CurrentName);
+ //Digi_CheckEnhancedKeyUsage(pCert,"1.3.6.1.5.5");
+ //Test_ReadCertData(poX509);
+ //END TEST
+ // if issuer match
+ if (poX509SignerName != NULL && poX509CurrentName != NULL && X509_NAME_cmp(poX509SignerName, poX509CurrentName) == 0)
+ {
+ // check date
+ // NULL, if current time
+ if (Digi_IsValidResponderCert(pCert) == TRUE)
+ {
+ if (poResultCert == NULL)
+ fSet = TRUE;
+ else
+ {
+ if (CompareFileTime(&pCert->pCertInfo->NotBefore, &oResultTime) > 0)
+ fSet = TRUE;
+ }
+ if (fSet == TRUE)
+ {
+ //delete previous if exists
+ if (poResultCert != NULL)
+ X509_free(poResultCert);
+ //set result value
+ poResultCert = poX509;
+ memmove(&oResultTime,&pCert->pCertInfo->NotBefore,sizeof(FILETIME));
+ }
+ }
+ }
+ }
+ if (poX509 != NULL && fSet == FALSE)
+ X509_free(poX509);
+ }
+
+
+return(poResultCert);
+}
+
+int Test_ReadCertDataC(PCCERT_CONTEXT pCert)
+{
+int iRes = 0;
+X509 *poX509 = NULL;
+if (pCert != NULL);
+ //AA100204
+ ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+if (poX509 != NULL)
+ iRes = Test_ReadCertData(poX509);
+return(iRes);
+}
+
+
+
+int Test_ReadCertData(X509 *poX509)
+{
+ int iRes;
+ DigiDocMemBuf mbuf1;
+ DigiDocMemBuf mbuf2;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ mbuf2.pMem = 0;
+ mbuf2.nLen = 0;
+ // get issuer DN
+ iRes = ddocCertGetIssuerDN(poX509, &mbuf1);
+ iRes = ddocMemAppendData(&mbuf1, "\n", -1);
+ // get subject DN
+ iRes = ddocCertGetSubjectDN(poX509, &mbuf2);
+ iRes = ddocMemAppendData(&mbuf1, (const char*)mbuf2.pMem, mbuf2.nLen);
+ // display it
+ MessageBox(NULL,(const char*)mbuf1.pMem,"TEST",0);
+ ddocMemBuf_free(&mbuf1);
+ ddocMemBuf_free(&mbuf2);
+ return(0);
+}
+
+BOOL Digi_IsValidResponderCert(PCCERT_CONTEXT pCert)
+{
+BOOL fIsValid = FALSE;
+char *psValue = "1.3.6.1.5.5.7.3.9";
+if (pCert != NULL)
+ {
+ fIsValid = Digi_CheckEnhancedKeyUsage(pCert,psValue);
+ if (fIsValid == TRUE)
+ {
+ if (CertVerifyTimeValidity(NULL,pCert->pCertInfo) != 0)
+ fIsValid = FALSE;
+ }
+ }
+return(fIsValid);
+}
+
+
+BOOL Digi_CheckEnhancedKeyUsage(PCCERT_CONTEXT pCert, char *psValue)
+{
+BOOL fRes = FALSE;
+DWORD dwFlags = CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG;
+PCERT_ENHKEY_USAGE pUsage = NULL;
+//DWORD cUsageIdentifier - number of elements in rgpszUsageIdentifier
+//LPSTR *rgpszUsageIdentifier - array;
+DWORD cbUsage = 0;
+BOOL fCallRes;
+int iI;
+char *psValueCurrent;
+fCallRes = CertGetEnhancedKeyUsage(pCert,dwFlags,NULL, &cbUsage);
+if (fCallRes == TRUE)
+ {
+ pUsage = (PCERT_ENHKEY_USAGE)malloc(cbUsage);
+ fCallRes = CertGetEnhancedKeyUsage(pCert,dwFlags,pUsage, &cbUsage);
+ if (fCallRes == TRUE)
+ {
+ for (iI=0; iI < (int)pUsage->cUsageIdentifier;++iI)
+ {
+ psValueCurrent = pUsage->rgpszUsageIdentifier[iI];
+ if (psValueCurrent != NULL && psValue != NULL)
+ {
+ if (strstr(psValueCurrent,psValue) != NULL)
+ {
+ fRes = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+if (pUsage != NULL)
+ free(pUsage);
+return(fRes);
+}
+
+
+X509 *Digi_FindCertByResponse(StoreHandle *hStore, OCSP_RESPONSE *poResponse)
+{
+ X509 *poX509 = NULL;
+ PCCERT_CONTEXT pCert = NULL;
+ OCSP_RESPID *rid = NULL;
+ OCSP_BASICRESP *br = NULL;
+ OCSP_RESPDATA *rd = NULL;
+ int iLen;
+ char sCN[255];
+
+ if (poResponse != NULL) {
+ if ((br = OCSP_response_get1_basic(poResponse)) == NULL)
+ return(poX509);
+ rd = br->tbsResponseData;
+ rid = rd->responderId;
+ if (rid->type != V_OCSP_RESPID_NAME) {
+ if(br) OCSP_BASICRESP_free(br);
+ return(poX509);
+ }
+ iLen = X509_NAME_get_text_by_NID(rid->value.byName,NID_commonName,sCN,sizeof(sCN));
+ if (iLen > 0) //VS: 18.03.2006 - use only currently valid cert for new notary
+ pCert = Digi_FindCertBySubject(hStore, sCN, TRUE, 0, TRUE);
+ if(pCert != NULL)
+ //AA100204
+ ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+ }
+ if(br) OCSP_BASICRESP_free(br);
+ return(poX509);
+}
+
+
+
+//Added by AA 09/10/2003
+BOOL Digi_CheckResponderCertByResponse(X509 *poX509Responder, OCSP_RESPONSE *poResponse)
+{
+BOOL fRes = FALSE;
+OCSP_RESPID *rid = NULL;
+OCSP_BASICRESP *br = NULL;
+OCSP_RESPDATA *rd = NULL;
+int iLen;
+char sCNResp[255];
+char sCNCert[255];
+if (poResponse != NULL)
+ {
+ if ((br = OCSP_response_get1_basic(poResponse)) == NULL)
+ return(fRes);
+ rd = br->tbsResponseData;
+ rid = rd->responderId;
+ if (rid->type != V_OCSP_RESPID_NAME)
+ return(fRes);
+ iLen = X509_NAME_get_text_by_NID(rid->value.byName,NID_commonName,sCNResp,sizeof(sCNResp));
+ if (iLen > 0)
+ {
+ iLen = X509_NAME_get_text_by_NID(X509_get_subject_name(poX509Responder),NID_commonName, sCNCert,sizeof(sCNCert));
+ if (iLen > 0)
+ {
+ fRes = Digi_CompareCN(sCNResp,sCNCert);
+ }
+ }
+ }
+return(fRes);
+}
+
+//VS: 18.03.2006 - use only currently valid cert for new notary
+PCCERT_CONTEXT Digi_FindCertBySubject(StoreHandle *hStore, char *psCN, BOOL bCheckValid, const char* szSerialNr, BOOL bCA)
+{
+ PCCERT_CONTEXT pCert = NULL;
+ BOOL fFind = FALSE;
+ X509 *poX509;
+ char sSerial[255];
+ time_t tNow;
+ DigiDocMemBuf mbuf;
+
+ mbuf.pMem = 0;
+ mbuf.nLen = 0;
+
+ if (hStore == NULL || psCN == NULL)
+ return(pCert);
+ Digi_CloseStore(hStore);
+ hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL,
+ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG, (bCA ? L"CA" : L"My"));
+ if (hStore->hHandle == NULL)
+ return(pCert);
+ //get signer issuer
+ while (fFind == FALSE && (pCert = CertEnumCertificatesInStore(hStore->hHandle,pCert)))
+ {
+ //AA100204
+ ddocDecodeX509Data(&poX509, pCert->pbCertEncoded,pCert->cbCertEncoded);
+ if (poX509 != NULL)
+ {
+ //iLen = X509_NAME_get_text_by_NID(X509_get_subject_name(poX509),NID_commonName, sSubject,255);
+
+ ddocCertGetSubjectCN(poX509, &mbuf);
+
+ if(mbuf.nLen > 0) {
+ fFind = Digi_CompareCN((char*)mbuf.pMem, psCN);
+ if(fFind) {
+ if(szSerialNr) { //VS: 18.03.2006 - look for a cert with specific serial nr
+ ReadCertSerialNumber(sSerial, sizeof(sSerial)-1, poX509);
+ fFind = !strcmp(szSerialNr, sSerial);
+ } else if(bCheckValid) { //VS: 18.03.2006 - use only currently valid cert for new notary
+ time(&tNow);
+ fFind = !isCertValid(poX509, tNow);
+ }
+ }
+ }
+ X509_free(poX509);
+ }
+ }
+ if (fFind == FALSE)
+ pCert = NULL;
+ return(pCert);
+}
+
+X509* Digi_FindCertBySubjectAndHash(StoreHandle *hStore, char *psCN, BOOL bCheckValid, const char* szSerialNr, BOOL bCA, DigiDocMemBuf *pHash)
+{
+ PCCERT_CONTEXT pCert = NULL;
+ BOOL fFind = FALSE;
+ X509 *poX509 = NULL, *pSCert = NULL;
+ char sSerial[255];
+ time_t tNow;
+ DigiDocMemBuf mbuf1, mbuf2, mbuf3; //, mbuf4, mbuf5;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ mbuf2.pMem = 0;
+ mbuf2.nLen = 0;
+ mbuf3.pMem = 0;
+ mbuf3.nLen = 0;
+ /*mbuf4.pMem = 0;
+ mbuf4.nLen = 0;
+ mbuf5.pMem = 0;
+ mbuf5.nLen = 0;*/
+ if (hStore == NULL || psCN == NULL)
+ return NULL;
+ Digi_CloseStore(hStore);
+ hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL,
+ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG, (bCA ? L"CA" : L"My"));
+ if (hStore->hHandle == NULL)
+ return NULL;
+ ddocEncodeBase64(pHash, &mbuf3);
+ ddocDebug(3, "Digi_FindCertBySubjectAndHash", "Find CN: %s serial: %s subj-hash: %s", psCN, szSerialNr, (char*)mbuf3.pMem);
+ ddocMemBuf_free(&mbuf3);
+ //get signer issuer
+ while (fFind == FALSE && (pCert = CertEnumCertificatesInStore(hStore->hHandle,pCert)))
+ {
+ //AA100204
+ ddocDecodeX509Data(&poX509, pCert->pbCertEncoded,pCert->cbCertEncoded);
+ if (poX509 != NULL)
+ {
+ //iLen = X509_NAME_get_text_by_NID(X509_get_subject_name(poX509),NID_commonName, sSubject,255);
+ ddocCertGetSubjectCN(poX509, &mbuf1);
+ if(mbuf1.nLen > 0) {
+ fFind = Digi_CompareCN((char*)mbuf1.pMem, psCN);
+ if(fFind) {
+ if(szSerialNr) { //VS: 18.03.2006 - look for a cert with specific serial nr
+ ReadCertSerialNumber(sSerial, sizeof(sSerial)-1, poX509);
+ fFind = !strcmp(szSerialNr, sSerial);
+ } else if(bCheckValid) { //VS: 18.03.2006 - use only currently valid cert for new notary
+ time(&tNow);
+ fFind = !isCertValid(poX509, tNow);
+ }
+ }
+ if(fFind && pHash && poX509) {
+ readSubjectKeyIdentifier(poX509, &mbuf2);
+ ddocEncodeBase64(&mbuf2, &mbuf3);
+ //readAuthorityKeyIdentifier(poX509, &mbuf4);
+ //ddocEncodeBase64(&mbuf4, &mbuf5);
+ if(!ddocMemCompareMemBufs(pHash, &mbuf2)) {
+ pSCert = poX509;
+ fFind = TRUE;
+ //break;
+ }
+ else
+ fFind = FALSE;
+ }
+ }
+ //ddocDebug(3, "Digi_FindCertBySubjectAndHash", "Compare CN: %s serial: %s subj-hash: %s auth-hash: %s rc: %d", (char*)mbuf1.pMem, sSerial, (char*)mbuf3.pMem, (char*)mbuf5.pMem, fFind);
+ ddocDebug(3, "Digi_FindCertBySubjectAndHash", "Compare CN: %s serial: %s subj-hash: %s rc: %d", (char*)mbuf1.pMem, sSerial, (char*)mbuf3.pMem, fFind);
+ if(!pSCert) {
+ X509_free(poX509);
+ poX509 = NULL;
+ }
+ ddocMemBuf_free(&mbuf1);
+ ddocMemBuf_free(&mbuf2);
+ ddocMemBuf_free(&mbuf3);
+ //ddocMemBuf_free(&mbuf4);
+ //ddocMemBuf_free(&mbuf5);
+ }
+ }
+ if(fFind == FALSE)
+ pCert = NULL;
+ ddocMemBuf_free(&mbuf1);
+ ddocMemBuf_free(&mbuf2);
+ ddocMemBuf_free(&mbuf3);
+ //ddocMemBuf_free(&mbuf4);
+ //ddocMemBuf_free(&mbuf5);
+ return pSCert;
+}
+
+//----------------------------------------------------
+// Returns a list of certificates based on the
+// search criteria
+// szCN - CN of certs to search for
+// tValid - check validity on the given date (if not 0)
+// szSerialNr - serach for certs with this serial nr
+// pMBuf - public key hash to search
+//----------------------------------------------------
+X509 **Digi_FindCACerts(StoreHandle *hStore, const char* szCN, time_t tValid,
+ const char* szSerialNr, DigiDocMemBuf* pMBuf)
+{
+ int iMaxCerts = 512;
+ int iRes = 0, l1, l2;
+ X509 **caCerts = NULL;
+ X509 *poX509;
+ PCCERT_CONTEXT pCert = NULL;
+ BOOL fAdd;
+ char buf1[255], buf2[100];
+ DigiDocMemBuf mbuf1;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ //ddocDebug(3, "Digi_FindCACerts", "CN: %s tValid: %ld serial: %s,
+ // open CA store
+ if(!hStore) return NULL;
+ Digi_CloseStore(hStore);
+ hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL,
+ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"CA");
+ if (hStore->hHandle == NULL) {
+ return NULL;
+ }
+
+ // alloc list and initalize all positions to NULL
+ caCerts = (X509**)malloc(sizeof(void*) * (iMaxCerts+1));
+ if(caCerts == NULL) {
+ return(caCerts);
+ }
+ memset(caCerts,0,sizeof(void*) * (iMaxCerts+1));
+
+
+ if(hStore->hHandle != NULL) {
+ while(pCert= CertEnumCertificatesInStore(hStore->hHandle, pCert)) {
+ fAdd = FALSE;
+ ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+ if(poX509 != NULL) {
+ // check CN
+ if(szCN) {
+ buf1[0] = 0;
+ X509_NAME_get_text_by_NID(X509_get_subject_name(poX509), NID_commonName, buf1, sizeof(buf1));
+ fAdd = Digi_CompareCN((char*)szCN, buf1);
+ }
+ // check serial nr
+ if(szSerialNr) {
+ buf1[0] = 0;
+ ReadCertSerialNumber(buf1, sizeof(buf1)-1, poX509);
+ fAdd = !strcmp(szSerialNr, (const char*)buf1);
+ }
+ // check pubkey hash
+ if(pMBuf) {
+ ddocCertGetPubkeyDigest(poX509, &mbuf1);
+ l1 = sizeof(buf1);
+ l2 = sizeof(buf2);
+ bin2hex((const byte*)mbuf1.pMem, mbuf1.nLen, buf1, &l1);
+ bin2hex((const byte*)pMBuf->pMem, pMBuf->nLen, buf2, &l2);
+ ddocDebug(3, "Digi_FindCACerts", "Compare cert-hash: %s with searched-hash %s", buf1, buf2);
+ fAdd = !ddocMemCompareMemBufs(&mbuf1, pMBuf);
+ ddocMemBuf_free(&mbuf1);
+ }
+ if(tValid)
+ fAdd = !isCertValid(poX509, tValid);
+ }
+ // if any of the conditiones matched then add cert to list
+ if (fAdd == TRUE) {
+ caCerts[iRes] = poX509;
+ ++iRes;
+ }
+ else
+ X509_free(poX509);
+ }
+ }
+ // if no certs found then free the array
+ caCerts[iRes] = NULL;
+ if(iRes == 0) {
+ free(caCerts);
+ caCerts = NULL;
+ }
+ return(caCerts);
+}
+
+
+X509 **Digi_MakeCertList(X509 *poX509Main, StoreHandle *hStore)
+{
+X509 **caCerts = NULL;
+memset(hStore,0,sizeof(StoreHandle));
+hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL,
+ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"CA");
+if (hStore->hHandle != NULL)
+ {
+ caCerts = Digi_MakeCertListLow(poX509Main, hStore);
+ if (caCerts == NULL)
+ {
+ CertCloseStore(hStore->hHandle,CERT_CLOSE_STORE_FORCE_FLAG);
+ hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL,
+ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"ROOT");
+ if (hStore->hHandle != NULL)
+ {
+ hStore->fRoot = TRUE;
+ caCerts = Digi_MakeCertListLow(poX509Main, hStore);
+ }
+ }
+ }
+return(caCerts);
+}
+
+
+X509 **Digi_MakeCertListLow(X509 *poX509Main, StoreHandle *hStore)
+{
+int iMaxCerts = 512;
+int iRes = 0;
+X509 **caCerts = NULL;
+X509 *poX509;
+PCCERT_CONTEXT pCert = NULL;
+BOOL fAdd;
+if (poX509Main == NULL)
+ return(caCerts);
+caCerts = (X509**)malloc(sizeof(void*) * (iMaxCerts+1));
+if (caCerts == NULL)
+ return(caCerts);
+memset(caCerts,0,sizeof(void*) * (iMaxCerts+1));
+
+if (hStore->hHandle != NULL)
+ {
+ while( pCert= CertEnumCertificatesInStore( hStore->hHandle,pCert))
+ {
+ fAdd = FALSE;
+ ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+ //TEST
+ //Test_ReadCertData(poX509);
+ //ENDTEST
+ if (poX509 != NULL)
+ fAdd = Digi_IsCert1SubjectDNEqualCert2IssuerDN(poX509,poX509Main);
+ if (fAdd == TRUE)
+ {
+ caCerts[iRes] = poX509;
+ ++iRes;
+ }
+ else
+ X509_free(poX509);
+ }
+ }
+//Added by AA 2004/03/15
+caCerts[iRes] = NULL;
+if (iRes == 0)
+ {
+ free(caCerts);
+ caCerts = NULL;
+ }
+return(caCerts);
+}
+
+
+X509* Digi_FindDirectCA(X509 *poX509Main, StoreHandle *hStore)
+{
+ X509 *poX509;
+ PCCERT_CONTEXT pCert = NULL;
+
+ if (poX509Main == NULL)
+ return NULL;
+
+ if (hStore->hHandle != NULL) {
+ while(pCert = CertEnumCertificatesInStore( hStore->hHandle, pCert)) {
+ ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+ if(poX509 != NULL) {
+ if(Digi_IsCert1SubjectDNEqualCert2IssuerDN(poX509, poX509Main)) {
+ return poX509;
+ }
+ }
+ else
+ X509_free(poX509);
+ }
+ }
+ return NULL;
+}
+
+void Digi_FreeCertList(X509 **caCerts)
+{
+int iMaxCerts = 512;
+int i;
+if (caCerts != NULL)
+ {
+ for(i = 0; i < iMaxCerts; i++)
+ {
+ if(caCerts[i] != NULL)
+ X509_free(caCerts[i]);
+ }
+ free(caCerts);
+ }
+}
+
+
+BOOL Digi_CompareCN(char *psSub1, char *psSub2)
+{
+ BOOL fRes = FALSE;
+ if (psSub1 != NULL && psSub2 != NULL )
+ {
+ if (strlen(psSub1) > 0 || strlen(psSub2) > 0)
+ {
+ if (strcmp(psSub1,psSub2) == 0)
+ fRes = TRUE;
+ }
+ }
+ return(fRes);
+}
+
+
+int countCerts(const X509** certs)
+{
+ int i = 0;
+ while(certs && certs[i])
+ i++;
+ return i;
+}
+
+BOOL Digi_IsCert1SubjectDNEqualCert2IssuerDN(X509 *pCert1, X509 *pCert2)
+{
+BOOL fEqual = FALSE;
+unsigned long ulHash1;
+unsigned long ulHash2;
+ulHash1 = X509_subject_name_hash(pCert1);
+ulHash2 = X509_issuer_name_hash(pCert2);
+if (ulHash1 == ulHash2)
+ fEqual = TRUE;
+return(fEqual);
+}
+
+
+//29/09/2003
+//31/05/2006 - (g_current_TSAProfile->g_bAddTimeStamp) enables timestamping
+int Digi_getConfirmationWithCertSearch(SignedDoc* pSigDoc, SignatureInfo* pSigInfo,
+ char* pkcs12File, char *password,
+ char* notaryURL, char* proxyHost, char* proxyPort)
+{
+ int err = ERR_OK, err2 = ERR_OK, i, l1;
+ StoreHandle hStore;
+ NotaryInfo* pNotInf = NULL;
+ X509 *pNotCert = NULL, *pNotCertFound = NULL, *pSigCa = 0;
+ X509 **caCerts = NULL;
+ X509 **respCerts = NULL;
+ const DigiDocMemBuf *pMBuf = 0;
+ char szCN[255], buf1[100];
+
+ // set default values from config file
+ if(ConfigItem_lookup_bool("SIGN_OCSP", 1)) {
+ if(!pkcs12File || !strlen(pkcs12File))
+ pkcs12File = (char*)ConfigItem_lookup("DIGIDOC_PKCS_FILE");
+ if(!password || !strlen(password))
+ password = (char*)ConfigItem_lookup("DIGIDOC_PKCS_PASSWD");
+ }
+ if(!notaryURL || !strlen(notaryURL))
+ notaryURL = (char*)ConfigItem_lookup("DIGIDOC_OCSP_URL");
+ if(ConfigItem_lookup_bool("USE_PROXY", 1)) {
+ proxyHost = (char*)ConfigItem_lookup("DIGIDOC_PROXY_HOST");
+ RETURN_IF_NOT(proxyHost, ERR_WRONG_URL_OR_PROXY);
+ proxyPort = (char*)ConfigItem_lookup("DIGIDOC_PROXY_PORT");
+ RETURN_IF_NOT(proxyPort, ERR_WRONG_URL_OR_PROXY);
+ }
+ if (Digi_OpenStore(&hStore) == FALSE)
+ SET_LAST_ERROR_RETURN_CODE(ERR_CERT_STORE_READ);
+ // we need to find some CA-s of signer before asking for
+ // confirmation in order to be able to construct certid
+ // we need this because of users direct CA
+ respCerts = Digi_MakeCertListLow(ddocSigInfo_GetSignersCert(pSigInfo), &hStore);
+ if(respCerts) {
+ for(i = 0; respCerts[i]; i++) // find lowest (middle) ca - direct ca of signers cert
+ pSigCa = respCerts[i];
+ }
+ // VS: ver 1.5.33 - make this decision lower if confirmation can still be retrieved
+ //if(!respCerts) SET_LAST_ERROR_RETURN_CODE(ERR_SIGNERS_CERT_NOT_TRUSTED);
+ err = getConfirmation(pSigDoc, pSigInfo, respCerts, NULL,
+ pkcs12File, password,
+ notaryURL, proxyHost, proxyPort);
+ //Digi_FreeCertList(respCerts);
+ if(respCerts) {
+ for(i = 0; respCerts[i]; i++) {
+ if(respCerts[i] && respCerts[i] != pSigCa) {
+ X509_free(respCerts[i]);
+ respCerts[i] = 0;
+ }
+ }
+ }
+ if(err) return err;
+ pNotInf = pSigInfo->pNotary;
+ pMBuf = ddocNotInfo_GetResponderId(pNotInf);
+ RETURN_IF_NOT(pMBuf != NULL, ERR_NOTARY_SIG_MATCH);
+ if(pNotInf->nRespIdType == RESPID_NAME_TYPE) {
+ szCN[0] = 0;
+ if(pMBuf && pMBuf->pMem)
+ findCN((char*)pMBuf->pMem, szCN, sizeof(szCN));
+ pMBuf = NULL; // don't look for pubkey hash
+ ddocDebug(3, "Digi_getConfirmationWithCertSearch", "Find OCSP resp CA-s by key %s", szCN);
+ } else if(pNotInf->nRespIdType == RESPID_KEY_TYPE) {
+ // look for pubkey hash in Digi_FindCACerts
+ pMBuf = &(pNotInf->mbufRespId);
+ szCN[0] = 0;
+ l1 = sizeof(buf1);
+ bin2hex((const byte*)pNotInf->mbufRespId.pMem, pNotInf->mbufRespId.nLen, buf1, &l1);
+ ddocDebug(3, "Digi_getConfirmationWithCertSearch", "Find OCSP resp CA-s by hash %s", buf1);
+ }
+
+
+ RETURN_IF_NOT(pNotInf != NULL, ERR_NOTARY_SIG_MATCH);
+ // find a list of potential responder certificates
+ // search only by responder id = CN. Should I check also validity on current time ?
+ respCerts = Digi_FindCACerts(&hStore, (szCN[0] ? szCN : NULL), 0, 0, (DigiDocMemBuf*)pMBuf);
+ clearErrors();
+
+ if(!err && respCerts) {
+ i = 0;
+ do {
+ pNotCert = respCerts[i];
+ // get the next potential notary cert
+ if(pNotCert) {
+ // find CA certs for it
+ Digi_CloseStore(&hStore);
+ caCerts = Digi_MakeCertList(pNotCert, &hStore);
+
+ if (caCerts != NULL) {
+ err2 = finalizeAndVerifyNotary2(pSigDoc, pSigInfo, pNotInf, (const X509**)caCerts, (const X509*)pNotCert, pSigCa);
+ // if this didn't verify then free the cert and mark the slot as freed
+ if(err2) {
+ // remove certid and certvalue created for verification
+ removeNotaryInfoCert(pSigInfo);
+ // mark slot as freed (was done above)
+ respCerts[i] = 0;
+ }
+ // found one cert, save it for later
+ if(!err2) {
+ // if one cert was already found
+ // then pick the freshes one - one were not-after-date is latest
+ if(pNotCertFound) {
+ if(getCertNotAfterTimeT(pNotCert) > getCertNotAfterTimeT(pNotCertFound)) {
+ // release older cert
+ X509_free(pNotCertFound);
+ pNotCertFound = pNotCert;
+ }
+ }
+ pNotCertFound = pNotCert;
+ }
+ // else don't free, give ownership to new Notary!
+ // mark the slot as freed
+ respCerts[i] = 0;
+ }
+ else {
+ err = ERR_CERT_STORE_READ;
+ //fprintf(hFile, "No CA-s found, err: %d\n", err);
+ }
+ // free CA certs
+ Digi_FreeCertList(caCerts);
+ }
+ i++;
+ } while(pNotCert);
+ // free the remaining responder certs
+ Digi_FreeCertList(respCerts);
+ }
+
+ // else clear verifying errors
+ clearErrors();
+ // final check with the selected responders certificate
+ if(pNotCertFound) {
+ Digi_CloseStore(&hStore);
+ caCerts = Digi_MakeCertList(pNotCertFound, &hStore);
+ err = finalizeAndVerifyNotary2(pSigDoc, pSigInfo, pNotInf, (const X509**)caCerts, (const X509*)pNotCertFound, pSigCa);
+ Digi_FreeCertList(caCerts);
+ }
+ else
+ err = ERR_OCSP_CERT_NOTFOUND;
+ //fprintf(hFile, "OCSP finalize RC: %d\n", err);
+ // reset original signature content
+ if(pSigInfo->mbufOrigContent.pMem)
+ ddocMemBuf_free(&(pSigInfo->mbufOrigContent));
+ Digi_CloseStore(&hStore);
+ if(err != ERR_OK)
+ SET_LAST_ERROR(err);
+ return(err);
+}
+
+//--------------------------------------------------
+// Verfies NotaryInfo signature
+// pSigDoc - signed doc object
+// pNotInfo - NotaryInfo object
+// caFiles - array of CA file names terminated with NULL
+// CApath - path to (directory) all certs
+// notCertFile - Notary (e.g. OCSP responder) cert file
+//--------------------------------------------------
+int Digi_verifyNotaryInfoWithCertSearch(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo)
+{
+ X509** caCerts = NULL;
+ X509* notCert = NULL;
+ X509* cert = NULL, *pSigCA = NULL, *pSigCert = NULL;
+ StoreHandle hStore;
+ SignatureInfo *pSigInfo = NULL;
+ int err = ERR_OK;
+
+ if(pNotInfo)
+ pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotInfo);
+ if(pSigInfo != NULL) {
+ cert = ddocSigInfo_GetOCSPRespondersCert(pSigInfo);
+ }
+ caCerts = Digi_MakeCertList(cert,&hStore);
+ if(caCerts == NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_CERT_STORE_READ);
+ //siin leitakse responderi cert vastavalt kirjeldusele
+ //notCert = Digi_FindResponderCert(&hStore,cert);
+ //08.03.2005 leitakse responderi koopia win certstoorest
+ if(!err) {
+ notCert = Digi_FindX509CopyFromStore(&hStore,cert);
+ pSigCert = ddocSigInfo_GetSignersCert(pSigInfo);
+ pSigCA = Digi_FindDirectCA(pSigCert, &hStore);
+ if((!notCert || !pSigCA) && hStore.fRoot == 1) { // try also CA store
+ Digi_CloseStore(&hStore);
+ memset(&hStore,0,sizeof(StoreHandle));
+ hStore.hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL,
+ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"CA");
+ if(!notCert)
+ notCert = Digi_FindX509CopyFromStore(&hStore,cert);
+ if(!pSigCA)
+ pSigCA = Digi_FindDirectCA(pSigCert, &hStore);
+ }
+ if (notCert)
+ err = Digi_verifyNotaryInfoCERT(pSigDoc, pNotInfo, (const X509**)caCerts, notCert, pSigCA);
+ else
+ err = ERR_OCSP_CERT_NOTFOUND;
+ }
+ Digi_CloseStore(&hStore);
+ Digi_FreeCertList(caCerts);
+ //AM 23.05.08 where notCert is freed?
+ if(notCert)
+ X509_free(notCert);
+ if(pSigCA)
+ X509_free(pSigCA);
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+//============================================================
+// Verifies the whole document, but returns on first error
+// Use the functions defined earlier to verify all contents
+// step by step.
+// pSigDoc - signed doc data
+//
+//============================================================
+int Digi_verifySigDocWithCertSearch(const SignedDoc* pSigDoc, const char* szDataFile)
+
+{
+ SignatureInfo* pSigInfo;
+ NotaryInfo* pNotInfo;
+ int i, d, err = ERR_OK;
+
+ RETURN_IF_NULL(pSigDoc);
+ //assert(pSigDoc);
+ d = getCountOfSignatures(pSigDoc);
+ for(i = 0; i < d; i++) {
+ pSigInfo = getSignature(pSigDoc, i);
+ err = Digi_verifySignatureInfo(pSigDoc, pSigInfo, szDataFile);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ pNotInfo = pSigInfo->pNotary;
+ err = Digi_verifyNotaryInfoWithCertSearch(pSigDoc, pNotInfo);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ }
+ return err;
+}
+
+
+//--------------------------------------------------
+// Reads a certificate from pkcs12 conteiner
+//--------------------------------------------------
+// AA 18/09/2003
+EXP_OPTION int Digi_readCertificateByPKCS12OnlyCertHandle(const char *pkcs12file, const char * passwd, X509 **x509)
+{
+ int err = ERR_OK;
+ EVP_PKEY *pkey;
+ // VS: 26.01.2010 - initialize
+ (*x509) = 0;
+ //AM 16.09.08 DigiDocClient calling it with empty strings even ocsp request signing is off
+ if(!strcmp(pkcs12file, ""))
+ return ERR_OK;
+ err = ReadCertificateByPKCS12(x509,pkcs12file,passwd,&pkey);
+ //AM 22.05.08 pKey should be freed
+ if(err == 0 && pkey)
+ EVP_PKEY_free(pkey);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ return ERR_OK;
+}
+
+//============================================================
+// Verifies this signature
+// pSigDoc - signed doc data
+// pSigInfo - signature info object
+// signerCA - direct signer CA certs filename
+// szDateFile - name of the digidoc file
+// bUseCA - use CA certs or not 1/0
+// from original file and use it for hash function.
+// This is usefull if the file has been generated by
+// another library and possibly formats these elements
+// differently.
+//============================================================
+int Digi_verifySignatureInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const char* szDataFile)
+{
+ char buf2[100], *p1 = 0;
+ X509* pCaCert = 0;
+ int err = ERR_OK, k = 0;
+ StoreHandle hStore;
+ DigiDocMemBuf mbuf1;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ buf2[0] = 0;
+ if(!Digi_OpenStore(&hStore))
+ return ERR_CERT_STORE_READ;
+ //p1 = ddocSigInfo_GetSignersCert_IssuerName(pSigInfo);
+ p1 = (char*)ddocSigInfo_GetSignersCert_IssuerNameAndHash(pSigInfo, &mbuf1);
+ //strncpy(buf1, ddocSigInfo_GetSignersCert_IssuerName(pSigInfo), sizeof(buf1));
+ if(p1)
+ findCN((char*)p1, buf2, sizeof(buf2));
+ pCaCert = Digi_FindCertBySubjectAndHash(&hStore, buf2, FALSE, 0, TRUE, &mbuf1);
+ if(!pCaCert) {
+ ddocDebug(1, "Digi_verifySignatureInfo", "ERR112 cert: %s", buf2);
+ //AM 02.03.09 teadmata olek kui leia CA serti
+ return ERR_UNKNOWN_CA;
+ }
+ err = verifySignatureInfoCERT(pSigDoc, pSigInfo, pCaCert,
+ szDataFile, (pCaCert != NULL));
+ if(pCaCert)
+ X509_free(pCaCert);
+ Digi_CloseStore(&hStore);
+ ddocMemBuf_free(&mbuf1);
+ if((k = getCountOfSignerRoles(pSigInfo, 0)) > 1) {
+ ddocDebug(1, "Digi_verifySignatureInfo", "Number of roles: %d, Currently supports max 1 roles", k);
+ SET_LAST_ERROR(ERR_MAX_1_ROLES);
+ err = ERR_MAX_1_ROLES;
+ }
+ return err;
+}
+
+
+//============================================================
+// Verifies the whole document, but returns on first error
+// Use the functions defined earlier to verify all contents
+// step by step.
+// pSigDoc - signed doc data
+//
+//============================================================
+
+int Digi_verifySigDoc(const SignedDoc* pSigDoc, const char* szDataFile)
+
+{
+ SignatureInfo* pSigInfo;
+ NotaryInfo* pNotInfo;
+ int i, d, err = ERR_OK;
+
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ //assert(pSigDoc);
+ d = getCountOfSignatures(pSigDoc);
+ for(i = 0; i < d; i++) {
+ pSigInfo = getSignature(pSigDoc, i);
+ err = Digi_verifySignatureInfo(pSigDoc, pSigInfo, szDataFile);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ }
+ d = getCountOfNotaryInfos(pSigDoc);
+ for(i = 0;i < d; i++) {
+ pNotInfo = getNotaryInfo(pSigDoc, i);
+ err = Digi_verifyNotaryInfoWithCertSearch(pSigDoc, pNotInfo);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ }
+ return ERR_OK;
+}
+
+
+//--------------------------------------------------
+// Verfies NotaryInfo signature
+// pSigDoc - signed doc object
+// pNotInfo - NotaryInfo object
+// caCerts - CA certificate pointer array terminated with NULL
+// CApath - path to (directory) all certs
+// notCertFile - Notary (e.g. OCSP responder) cert file
+//--------------------------------------------------
+int Digi_verifyNotaryInfoCERT(const SignedDoc* pSigDoc,
+ const NotaryInfo* pNotInfo,
+ const X509** caCerts,
+ const X509* notCert,
+ const X509* pSigCA)
+{
+ SignatureInfo* pSigInfo = NULL;
+ pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotInfo);
+ RETURN_IF_NOT(pSigInfo != NULL, ERR_NOTARY_NO_SIGNATURE);
+ return verifyNotaryInfoCERT2(pSigDoc, pSigInfo, pNotInfo, caCerts, 0, notCert, pSigCA);
+}
+
+
+//====================================================================
+// Finds issuer certificate of given certificate
+// returns NULL if not found or any error occures
+// The stores "My","CA" and "Root" will be scanned.
+//====================================================================
+EXP_OPTION X509 * findIssuerCertificatefromMsStore(X509 *x509){
+ return findIssuerCertificatefromStore(x509);
+
+}
+
+//Functions from EstIDLib.c
+
+
+//============================================================
+// Calculates and stores a signature for this SignatureInfo object
+// Uses EstEID card as CSP to sign the info
+// pSigInfo - signature info object
+//============================================================
+EXP_OPTION int calculateSigInfoSignatureWithCSPEstID(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int iByKeyContainer, const char* szPin)
+{
+ int err = ERR_OK, l1;
+ PCCERT_CONTEXT pCert;
+ char buf1[300];
+ unsigned long sigLen;
+ int digLen, len=0;
+ char sigDig[300],signature[2084], *p1;
+ char *psKeyName = NULL;
+ char *psCSPName = NULL;
+ //long tmpSerial;
+ //HCRYPTPROV hProvider;
+ DWORD dwRes;
+ X509 *pX509;
+ DigiDocMemBuf *pMBuf1;
+
+ ddocDebug(3, "calculateSigInfoSignatureWithCSPEstID", "Sign id: %s", pSigInfo->szId);
+ pCert = DigiCrypt_FindContext((BOOL) iByKeyContainer, &dwRes);
+ if(pCert == NULL) {
+ if (dwRes == dDigiCrypt_Error_NotFoundCSP)
+ err = ERR_CSP_NO_CARD_DATA;
+ if(dwRes == dDigiCrypt_Error_UserCancel)
+ err = ERR_CSP_USER_CANCEL;
+ if (dwRes == dDigiCrypt_Error_NoDefaultKey)
+ err = ERR_CSP_NODEFKEY_CONTAINER;
+ if (dwRes == dDIgiCrypt_Error_NotFoundCert)
+ err = ERR_CSP_CERT_FOUND;
+
+ SET_LAST_ERROR_RETURN_CODE(err);
+ }
+ psKeyName = DigiCrypt_FindContext_GetKeyName();
+ psCSPName = DigiCrypt_FindContext_GetCSPName();
+ //AA100204
+ ddocDecodeX509Data(&pX509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+ err = setSignatureCert(pSigInfo, pX509);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ //AA-Viimase minuti jama
+ createTimestamp(pSigDoc, sigDig, sizeof(sigDig));
+ setString(&(pSigInfo->szTimeStamp), sigDig, -1);
+ // Signed properties digest
+ // now calculate signed properties digest
+ err = calculateSignedPropertiesDigest(pSigDoc, pSigInfo);
+ // TODO: replace later
+ pMBuf1 = ddocDigestValue_GetDigestValue(pSigInfo->pSigPropDigest);
+ ddocSigInfo_SetSigPropRealDigest(pSigInfo, (const char*)pMBuf1->pMem, pMBuf1->nLen);
+ // signature type & val
+ ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, SIGN_RSA_NAME, 0, 0);
+ // calc signed-info digest
+ l1 = sizeof(buf1);
+ err = calculateSignedInfoDigest(pSigDoc, pSigInfo, (byte*)buf1, &l1);
+ err = ddocSigInfo_SetSigInfoRealDigest(pSigInfo, buf1, l1);
+ sigLen = sizeof(signature);
+ memset(signature, 0, sizeof(signature));
+ p1 = createXMLSignedInfo(pSigDoc, pSigInfo);
+ len = strlen(p1);
+
+ // sign the <SignedInfo> hash with CSP
+ digLen = sizeof(sigDig);
+ err = GetSignedHashWithKeyAndCSP(psKeyName,psCSPName, p1, len, NULL, NULL, sigDig, &digLen,&signature[0],&sigLen,szPin);
+ if(p1)
+ free(p1);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ // set signature value
+ ddocSigInfo_SetSignatureValue(pSigInfo, signature, (int)sigLen);
+ ddocDebug(3, "calculateSigInfoSignatureWithCSPEstID", "End signing Sign id: %s, rc: %d", pSigInfo->szId, err);
+ return ERR_OK;
+}
+
+
+
+X509* findCertificate(const CertSearch * cS){
+ //debugPrint("findCertificate");
+ X509* poCert = NULL;
+ if(cS==NULL){
+ return NULL;
+ }else if(cS->searchType==CERT_SEARCH_BY_X509){
+ ReadCertificate(&poCert,cS->x509FileName);
+ return(poCert);
+ }else if(cS->searchType==CERT_SEARCH_BY_PKCS12){
+ X509 * x509=NULL;
+ EVP_PKEY * pKey=NULL;
+ int err=0;
+ err=ReadCertificateByPKCS12(&x509,cS->pkcs12FileName,cS->pswd,&pKey);
+ EVP_PKEY_free(pKey);
+ if(err==ERR_OK){
+ return x509;
+ }else{
+ SET_LAST_ERROR(err);
+ return NULL;
+ }
+ }else if(cS->searchType==CERT_SEARCH_BY_STORE){
+ #ifdef WIN32_CSP
+ X509 * x509=NULL;
+ int err=0;
+ RETURN_OBJ_IF_NULL(cS->certSearchStore, NULL);
+ err=GetCertificateFromStore(cS->certSearchStore,&x509);
+ //debugPrint("return from findCertificate (MS Store)");
+ if(err==ERR_OK){
+ return x509;
+ }else{
+ SET_LAST_ERROR(err);
+ return NULL;
+ }
+ #else
+ return NULL;
+ #endif
+ }else{
+ return NULL;
+ }
+}
+
+EXP_OPTION int findAllCertificates(const CertSearchStore *sS, X509 ***certsArray, int *numberOfCerts){
+ #ifdef WIN32_CSP
+ int rc=0,i;
+ X509 **array;
+ CertItem *certItem, *certItem2;
+ rc=GetAllCertificatesFromStore(sS,&certItem,numberOfCerts);
+ if(rc==ERR_OK){
+ array=malloc(sizeof(X509*)*(*numberOfCerts));
+ RETURN_IF_BAD_ALLOC(array);
+ for(i=0;i< *numberOfCerts ;i++){
+ array[i]=certItem->pCert;
+ certItem2=certItem;
+ certItem=certItem->nextItem;
+ free(certItem2);
+ }
+ *certsArray=array;
+ }
+ if (rc != ERR_OK) SET_LAST_ERROR(rc);
+ return rc;
+ #else
+ SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_CERT_SEARCH);
+ #endif // WIN32_CSP
+}
+
+/***********************************************************************/
+//=========================================================================
+// Returns pointer to current CSP. If current CSP was not initialized (i.e
+// NULL ) and input parameter is TRUE then active CSP is asked from
+// function getActiveProvider() and if CSP is "EST ID CSP" then
+// signature flag in CSP structure will turned to true
+//=========================================================================
+EXP_OPTION CSProvider * getCurrentCSProvider(BOOL tryToFindIfMissing){
+ if(tryToFindIfMissing==FALSE){
+ return cCSProvider;
+ }
+ // so tryToFindIfMissing was true, we need to find out if not found yet
+ if(cCSProvider==NULL ){
+ //cCSProvider=getActiveProvider();
+ if(cCSProvider!=NULL){
+ if(strcmp(cCSProvider->CSPName,EST_EID_CSP)==0)
+ cCSProvider->at_sig=TRUE;
+ else
+ cCSProvider->at_sig=FALSE;
+ }
+ }
+ return cCSProvider;
+
+}
+EXP_OPTION void setCurrentCSProvider(CSProvider * newProvider){
+ cCSProvider=newProvider;
+}
+
+
+
+//=====================================================
+EXP_OPTION CertSearchStore* CertSearchStore_new()
+{
+ CertSearchStore* certSearch;
+ certSearch=(CertSearchStore*)malloc(sizeof(CertSearchStore));
+ memset(certSearch, 0, sizeof(CertSearchStore));
+ return certSearch;
+}
+
+EXP_OPTION void CertSearchStore_free(CertSearchStore* certSearchStore){
+ int i=0;
+ RETURN_VOID_IF_NULL(certSearchStore);
+ if (certSearchStore->subDNCriterias) {
+ for(; i < certSearchStore->numberOfSubDNCriterias ; i++ ){
+ if(certSearchStore->subDNCriterias[i] != NULL){
+ free(certSearchStore->subDNCriterias[i]);
+ }
+ }
+ free(certSearchStore->subDNCriterias);
+ }
+ certSearchStore->numberOfSubDNCriterias=0;
+ if (certSearchStore->issDNCriterias) {
+ for(; i < certSearchStore->numberOfIssDNCriterias ; i++ ){
+ if(certSearchStore->issDNCriterias[i] != NULL){
+ free(certSearchStore->issDNCriterias[i]);
+ }
+ }
+ free(certSearchStore->issDNCriterias);
+ }
+ certSearchStore->numberOfIssDNCriterias=0;
+ if(certSearchStore->storeName != NULL){
+ free(certSearchStore->storeName);
+ }
+ if(certSearchStore->publicKeyInfo){
+ free(certSearchStore->publicKeyInfo);
+ }
+ free(certSearchStore);
+ certSearchStore=NULL;
+}
+
+
+EXP_OPTION CertSearch* CertSearch_new(){
+ CertSearch* certSearch;
+ certSearch=(CertSearch*)malloc(sizeof(CertSearch));
+ memset(certSearch, 0, sizeof(CertSearch));
+ return certSearch;
+}
+
+EXP_OPTION void CertSearch_free(CertSearch* certSearch){
+ if(certSearch->certSearchStore != NULL){
+ CertSearchStore_free(certSearch->certSearchStore);
+ }
+ if(certSearch->pkcs12FileName != NULL){
+ free(certSearch->pkcs12FileName);
+ }
+ if(certSearch->pswd != NULL){
+ free(certSearch->pswd);
+ }
+ if(certSearch->x509FileName != NULL){
+ free(certSearch->x509FileName);
+ }
+ if(certSearch->keyFileName != NULL){
+ free(certSearch->keyFileName);
+ }
+ free(certSearch);
+ certSearch=NULL;
+
+}
+
+EXP_OPTION void CertSearch_setX509FileName(CertSearch* certSearch, const char* str)
+{
+ if(certSearch && str) {
+ setString((char**)&certSearch->x509FileName, str, -1);
+ }
+}
+
+EXP_OPTION void CertSearch_setKeyFileName(CertSearch* certSearch, const char* str)
+{
+ if(certSearch && str) {
+ setString((char**)&certSearch->keyFileName, str, -1);
+ }
+}
+
+EXP_OPTION void CertSearch_setPkcs12FileName(CertSearch* certSearch, const char* str)
+{
+ if(certSearch && str) {
+ setString((char**)&certSearch->pkcs12FileName, str, -1);
+ }
+}
+
+EXP_OPTION void CertSearch_setPasswd(CertSearch* certSearch, const char* str)
+{
+ if(certSearch && str) {
+ setString((char**)&certSearch->pswd, str, -1);
+ }
+}
+
+
+
+// Frees cert handles and items in this list.
+// WARNING! when caller does not own the first cert in chain,
+// then pass pListStart->nextItem instead of pListStart itself.
+EXP_OPTION void CertList_free(CertItem* pListStart) {
+ if (pListStart) {
+ CertItem* pItem = pListStart;
+ CertItem* pTmp;
+ while (pItem) {
+ pTmp = pItem->nextItem;
+ X509_free((X509*)pItem->pCert);
+ free(pItem);
+ pItem = pTmp;
+ }
+ }
+}
+
+//=====================================================================
+// reads certificate from system store
+// IN CertSearchStore *sS - search criterias
+// OUT x509 certificate
+//=====================================================================
+int GetAllCertificatesFromStore(const CertSearchStore *sS, CertItem ** certList, int *numberOfCerts)
+{
+ int retCode=ERR_OK;
+/*
+ int retCode1=ERR_UNSUPPORTED_CERT_SEARCH; // Unknown search type
+ int retCode2=ERR_CSP_OPEN_STORE; // Can not open system store
+ int retCode3=ERR_CSP_CERT_FOUND; // Certificate not found from store, probably cetificate not registered
+ int retCode4=ERR_INCORRECT_CERT_SEARCH; // search type Sub DN but mismatch of parameters
+ int retCode5=ERR_PKCS_CERT_DECODE;
+*/
+
+ int i=0,certCounter=0;
+ int initSize=10;
+ X509 *x509;
+ CertItem *certFirst,*certCurrent,*certIt;
+ BOOL certFound=FALSE;
+ BOOL useSerial=FALSE;
+ BOOL useSubDN=FALSE;
+ BOOL useIssDN=FALSE;
+ HCERTSTORE hCertStore = NULL;
+ PCCERT_CONTEXT pCert=NULL;
+ char defaultName[]="My";
+ char* storeName;
+ char buf[4000];
+ char buf1[4000];
+ long tmpSerial;
+ int err;
+ DigiDocMemBuf mbuf1;
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+
+ RETURN_IF_NOT(numberOfCerts !=NULL, ERR_NULL_SER_NUM_POINTER);
+
+ if((sS->searchType&(CERT_STORE_SEARCH_BY_SERIAL|CERT_STORE_SEARCH_BY_SUBJECT_DN|CERT_STORE_SEARCH_BY_ISSUER_DN)) == 0)
+ SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_CERT_SEARCH);
+
+ if((sS->searchType&CERT_STORE_SEARCH_BY_SERIAL) != 0){
+ useSerial=TRUE;
+ }
+ if((sS->searchType&CERT_STORE_SEARCH_BY_SUBJECT_DN) != 0){
+ useSubDN=TRUE;
+ if(sS->numberOfSubDNCriterias<1)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ if (sS->subDNCriterias == NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ for(i=0;i<sS->numberOfSubDNCriterias;i++){
+ if(sS->subDNCriterias[i]==NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ }
+ }
+ if((sS->searchType&CERT_STORE_SEARCH_BY_ISSUER_DN) != 0){
+ useIssDN=TRUE;
+ if(sS->numberOfIssDNCriterias<1)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+
+ if (sS->issDNCriterias == NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ for(i=0;i<sS->numberOfIssDNCriterias;i++){
+ if(sS->issDNCriterias[i]==NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ }
+ }
+ if(sS->storeName!=NULL){
+ storeName=sS->storeName;
+ }else{
+ storeName=defaultName;
+ }
+ certFirst = malloc(sizeof(CertItem));
+ RETURN_IF_BAD_ALLOC(certFirst);
+ // memset(certFirst,0,sizeof(certFirst)); <-- Andrus: fills with zeros only first 32 bits
+ memset(certFirst,0,sizeof(CertItem));
+ *certList=certFirst;
+ certCurrent=certFirst;
+ /////******************** start task ***********************************
+ while(TRUE){
+ hCertStore=CertOpenSystemStore(0,storeName);
+ if(!hCertStore){
+ retCode=ERR_CSP_OPEN_STORE;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+
+ while(TRUE){
+ pCert = CertEnumCertificatesInStore( hCertStore,pCert);
+ if(!pCert)
+ break;
+ //AA100204
+ ddocDecodeX509Data(&x509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+ RETURN_IF_NOT(x509 != NULL, ERR_PKCS_CERT_DECODE);
+
+ // if serial is a criteria check it
+ if(useSerial){
+ //AA-viimase minuti jama
+ //ReadCertSerialNumber(&tmpSerial,x509);
+ ReadCertSerialNumber(buf,sizeof(buf),x509);
+ tmpSerial = atol(buf);
+ if(tmpSerial == sS->certSerial){
+ certFound=TRUE;
+ }else{
+ certFound=FALSE;
+ X509_free(x509);
+ continue;
+ }
+ }//if(useSerial){
+
+ // if issuer name is a criteria check it
+ if(useIssDN){
+ int len=0;
+ X509_NAME * x509name;
+ x509name = X509_get_issuer_name(x509);
+ len=sizeof(buf);
+ memset(buf,0,len);
+ memset(buf1,0,sizeof(buf1));
+
+ //AM 26.09.08
+ //X509_NAME_oneline(x509name,buf,len);
+ err = ddocCertGetIssuerDN(x509, &mbuf1);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ len=strlen((char*)mbuf1.pMem);
+ prepareString((char*)mbuf1.pMem,buf1);
+ for(i=0;i<sS->numberOfIssDNCriterias;i++){
+ memset(buf,0,sizeof(buf));
+ prepareString(sS->issDNCriterias[i],buf);
+ if(strstr(buf1,buf)){
+ certFound=TRUE;
+ }else{
+ certFound=FALSE;
+ //X509_free(x509); <-- Andrus: free operation performed in the end of useIssDN block
+ break;
+ }
+ }
+ if(!certFound){
+ X509_free(x509);
+ continue;
+ }
+ }//if(useIssDN){
+
+ // if subject name is a criteria check it
+ if(useSubDN){
+ int len=0;
+ X509_NAME * x509name;
+ x509name = X509_get_subject_name(x509);
+ len=sizeof(buf);
+ memset(buf,0,len);
+ memset(buf1,0,sizeof(buf1));
+
+ //AM 26.09.08
+ //X509_NAME_oneline(x509name,buf,len);
+ err = ddocCertGetSubjectDN(x509, &mbuf1);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ len=strlen((char*)mbuf1.pMem);
+ prepareString((char*)mbuf1.pMem,buf1);
+ for(i=0;i<sS->numberOfSubDNCriterias;i++){
+ memset(buf,0,sizeof(buf));
+ prepareString(sS->subDNCriterias[i],buf);
+ if(strstr(buf1,buf)){
+ certFound=TRUE;
+ }else{
+ certFound=FALSE;
+ break;
+ }
+ }
+ // did we find ?
+ if(!certFound){
+ X509_free(x509);
+ continue;
+ }
+ }//if(useSubDN){
+ ddocMemBuf_free(&mbuf1);
+ // did we find ?
+ if(certFound){
+ certCounter++;
+ if(certCounter==1){
+ certFirst->pCert=x509;
+ continue;
+ }
+ certIt = malloc(sizeof(CertItem));
+ RETURN_IF_BAD_ALLOC(certIt);
+ // memset(certIt,0,sizeof(certIt)); <-- Andrus: fills with zeros only first 32 bits
+ memset(certIt,0,sizeof(CertItem));
+ certIt->pCert=x509;
+ certCurrent->nextItem=certIt;
+ certCurrent=certIt;
+ }else{
+ X509_free(x509);
+ continue;
+ }
+ }//while(pCertt=CertEnumCertificatesInStore(hCertStore,pCert))
+ *numberOfCerts=certCounter;
+ if( certCounter<1 ){
+ retCode = ERR_CSP_CERT_FOUND;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ break;
+ }//while(TRUE){
+ /////******************** close and free objects ***********************************
+ if(pCert) {CertFreeCertificateContext(pCert); }
+ if(hCertStore) {CertCloseStore(hCertStore,CERT_CLOSE_STORE_FORCE_FLAG);hCertStore=0;}
+ return retCode;
+ /////*******************************************************************************
+}
+//==========================================================
+// removes all spaces and tabs and makes all characters uppercase
+//==========================================================
+void prepareString(const char * strIN,char * strOUT){
+ int len=0;
+ int i=0;
+ int tempLen=0;
+ len=strlen(strIN);
+
+ if(len==0){
+ return;
+ }
+ for (;i<len ; i++) {
+ if((strIN[i] == ' ') || (strIN[i] == '\t')){
+ continue;
+ }else if( strIN[i]>0x60 && strIN[i]<0x7B ){
+ strOUT[tempLen++] = (strIN[i]-0x20);
+ }else {
+ strOUT[tempLen++] = strIN[i];
+ }
+ }
+}
+
+//=====================================================================
+// reads certificate from system store
+// IN CertSearchStore *sS - search criterias
+// OUT x509 certificate
+//=====================================================================
+int GetCertificateFromStore(const CertSearchStore *sS, X509 **cert){
+ int retCode=ERR_OK;
+ int retCode1=ERR_UNSUPPORTED_CERT_SEARCH; // Unknown search type
+ int retCode2=ERR_CSP_OPEN_STORE; // Can not open system store
+ int retCode3=ERR_CSP_CERT_FOUND; // Certificate not found from store, probably cetificate not registered
+ int retCode4=ERR_INCORRECT_CERT_SEARCH; // search type Sub DN but mismatch of parameters
+ int retCode5=ERR_PKCS_CERT_DECODE;
+
+ int i=0;
+ X509 *x509;
+ BOOL certFound=FALSE;
+ BOOL useKeyInfo=FALSE;
+ BOOL useSerial=FALSE;
+ BOOL useSubDN=FALSE;
+ BOOL useIssDN=FALSE;
+ HCERTSTORE hCertStore = NULL;
+ CERT_PUBLIC_KEY_INFO* pKeyInfo;
+ PCCERT_CONTEXT pCert=NULL;
+ char defaultName[]="My";
+ char* storeName;
+ char buf[3000];
+ char buf1[3000];
+ long tmpSerial;
+ int err=0;
+ DigiDocMemBuf mbuf1;
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ //---------------------------------
+ // TODO: it's just a test - remove it
+ //---------------------------------
+ /*
+ char* pSelArr[] = {"Good reader", "Better reader", "The best reader", NULL};
+ int iRes = runDigiDocDialogUnit(pSelArr, "Please select smartcard reader:");
+ if (iRes != -1) {
+ // handle picked element
+ char resultAsText[128];
+ //sprintf(resultAsText, "Selected item with index=%d", iRes);
+ MessageBox(NULL, resultAsText, "DigiDoc", MB_OK|MB_ICONEXCLAMATION);
+ } else {
+ // if possible, handle Cancel operation
+ }
+ */
+ //---------------------------------
+ // End of TODO
+ //---------------------------------
+ if((sS->searchType&(CERT_STORE_SEARCH_BY_SERIAL|CERT_STORE_SEARCH_BY_SUBJECT_DN|CERT_STORE_SEARCH_BY_ISSUER_DN|CERT_STORE_SEARCH_BY_KEY_INFO)) == 0)
+ SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_CERT_SEARCH);
+ if((sS->searchType&CERT_STORE_SEARCH_BY_KEY_INFO) != 0){
+ useKeyInfo=TRUE;
+ pKeyInfo=sS->publicKeyInfo;
+ if(pKeyInfo==NULL){
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ }
+ }
+ if((sS->searchType&CERT_STORE_SEARCH_BY_SERIAL) != 0){
+ useSerial=TRUE;
+ }
+ if((sS->searchType&CERT_STORE_SEARCH_BY_SUBJECT_DN) != 0){
+ useSubDN=TRUE;
+ if(sS->numberOfSubDNCriterias<1)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ if (sS->subDNCriterias == NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ for(i=0;i<sS->numberOfSubDNCriterias;i++){
+ if(sS->subDNCriterias[i]==NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ }
+ }
+ if((sS->searchType&CERT_STORE_SEARCH_BY_ISSUER_DN) != 0){
+ useIssDN=TRUE;
+ if(sS->numberOfIssDNCriterias<1)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ if (sS->issDNCriterias == NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ for(i=0;i<sS->numberOfIssDNCriterias;i++){
+ if(sS->issDNCriterias[i]==NULL)
+ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH);
+ }
+ }
+ if(sS->storeName!=NULL){
+ storeName=sS->storeName;
+ }else{
+ storeName=&defaultName[0];
+ }
+ /////******************** start task ***********************************
+ while(TRUE){
+ hCertStore=CertOpenSystemStore(0,storeName);
+ if(!hCertStore){
+ retCode = ERR_CSP_OPEN_STORE;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ if(useKeyInfo){
+ pCert=CertFindCertificateInStore(hCertStore,X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,0,CERT_FIND_PUBLIC_KEY,pKeyInfo,NULL );
+ if(pCert){
+ //AA100204
+ ddocDecodeX509Data(&x509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+ certFound=TRUE;
+ //memcpy(cert,x509,sizeof(x509));
+ //X509_free(x509);
+ *cert=x509;
+ break;
+ }
+ }//if(useSerial){
+ while( pCert= CertEnumCertificatesInStore( hCertStore,pCert)){
+ //AA100204
+ ddocDecodeX509Data(&x509,pCert->pbCertEncoded,pCert->cbCertEncoded);
+ RETURN_IF_NOT(x509 != NULL, ERR_PKCS_CERT_DECODE);
+ if(useSerial){
+ //AA-Viimase minuti jama
+ //ReadCertSerialNumber(&tmpSerial,x509);
+ ReadCertSerialNumber(buf,sizeof(buf),x509);
+ tmpSerial = atol(buf);
+ if(tmpSerial == sS->certSerial){
+ certFound=TRUE;
+ }else{
+ certFound=FALSE;
+ X509_free(x509);
+ continue;
+ }
+ }//if(useSerial){
+ if(useIssDN){
+ int len=0;
+ X509_NAME * x509name;
+ x509name = X509_get_issuer_name(x509);
+ len=sizeof(buf);
+ memset(buf,0,len);
+ memset(buf1,0,sizeof(buf1));
+
+ //AM 26.09.08
+ //X509_NAME_oneline(x509name,buf,len);
+ err = ddocCertGetIssuerDN(x509, &mbuf1);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ len=strlen((char*)mbuf1.pMem);
+ prepareString((char*)mbuf1.pMem,buf1);
+
+ for(i=0;i<sS->numberOfIssDNCriterias;i++){
+ memset(buf,0,sizeof(buf));
+ prepareString(sS->issDNCriterias[i],buf);
+ if(strstr(buf1,buf)){
+ certFound=TRUE;
+ }else{
+ certFound=FALSE;
+ X509_free(x509);
+ break;
+ }
+ }
+ if(!certFound){
+ X509_free(x509);
+ continue;
+ }
+ }//if(useIssDN){
+
+ if(useSubDN){
+ int len=0;
+ X509_NAME * x509name;
+ x509name = X509_get_subject_name(x509);
+ len=sizeof(buf);
+ memset(buf,0,len);
+ memset(buf1,0,sizeof(buf1));
+
+ //AM 26.09.08
+ //X509_NAME_oneline(x509name,buf,len);
+ err = ddocCertGetSubjectDN(x509, &mbuf1);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ len=strlen((char*)mbuf1.pMem);
+ prepareString((char*)mbuf1.pMem,buf1);
+
+ for(i=0;i<sS->numberOfSubDNCriterias;i++){
+ memset(buf,0,sizeof(buf));
+ prepareString(sS->subDNCriterias[i],buf);
+ if(strstr(buf1,buf)){
+ certFound=TRUE;
+ }else{
+ certFound=FALSE;
+ break;
+ }
+ }
+ // did we find ?
+ if(!certFound){
+ X509_free(x509);
+ continue;
+ }
+ }//if(useSubDN){
+ ddocMemBuf_free(&mbuf1);
+ // did we find ?
+ if(certFound){
+ break;
+ }else{
+ X509_free(x509);
+ continue;
+ }
+ }//while(pCertt=CertEnumCertificatesInStore(hCertStore,pCert))
+ if( certFound ){
+ //memcpy(cert,x509,sizeof(x509));
+ //X509_free(x509);
+ *cert=x509;
+ }else{
+ retCode=ERR_CSP_CERT_FOUND;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ break;
+ }//while(TRUE){
+
+ /////******************** close and free objects ***********************************
+ if(pCert) {CertFreeCertificateContext(pCert); }
+ if(hCertStore) {CertCloseStore(hCertStore,CERT_CLOSE_STORE_FORCE_FLAG);hCertStore=0;}
+ return retCode;
+ /////*******************************************************************************
+}
+//=======================================================
+//Asks and returns key name or NULL if can not be found.
+//Key name must be freed. Name will be like "AUT_VIISAKAS,VILLU,19901012020"
+//IN cProvider - crypto provider name, "EstEID Card CSP" in
+// EstID's case.
+//=======================================================
+LPBYTE getDefaultKeyName(CSProvider * cCSP){
+ BOOL fRes;
+ HCRYPTPROV hProv = 0;
+ LPBYTE pbContName = NULL;//string, key name to be stored
+ DWORD dwContName;
+ if(cCSP==NULL){
+ cCSP=getCurrentCSProvider(TRUE);
+ }
+ if(cCSP==NULL){
+ return NULL;
+ }
+ if(cCSP->rsa_full){
+ fRes = CryptAcquireContext(&hProv,NULL,cCSP->CSPName, PROV_RSA_FULL, 0);
+ }else{
+ fRes = CryptAcquireContext(&hProv,NULL,cCSP->CSPName, PROV_RSA_SIG, 0);
+ }
+ if (RCRYPT_FAILED(fRes)){ return NULL; }
+ // asks keypair name, in auth case it is AUT_<name, given name, code>
+ // first size and the the keyname itself
+ fRes = CryptGetProvParam(hProv,PP_CONTAINER,NULL,&dwContName,0);
+ if (RCRYPT_FAILED(fRes)){ return NULL; }
+ //pbContName =(LPBYTE) LocalAlloc(0,dwContName);
+ pbContName =(LPBYTE) malloc(dwContName);
+ if(pbContName != NULL ){
+ fRes = CryptGetProvParam(hProv,PP_CONTAINER,pbContName,&dwContName,0);
+ }
+ //in pbContName-s there is now ASCII string
+ fRes = CryptReleaseContext(hProv,0);
+ if (RCRYPT_FAILED(fRes)){ return NULL; }
+ hProv =0;
+ return pbContName;
+
+}
+
+//========================================================================
+// Returns issuer certificate context
+//========================================================================
+const CERT_CONTEXT * findCertFromStore(const CERT_CONTEXT *cert, const char *storeName)
+{
+ HCERTSTORE hCertStore = NULL;
+ const CERT_CONTEXT *issuer = NULL;
+ DWORD flag=CERT_STORE_SIGNATURE_FLAG;
+ hCertStore=CertOpenSystemStore(0,storeName);
+ if(!hCertStore){
+ return NULL;
+ }
+ issuer = CertGetIssuerCertificateFromStore(hCertStore,cert,NULL,&flag);
+ CertCloseStore(hCertStore,0);
+ return issuer;
+}
+
+//=========================================================================
+X509 * findIssuerCertificatefromStore(X509 *x509)
+{
+ const CERT_CONTEXT *cert = NULL;
+ const CERT_CONTEXT *issuer = NULL;
+ char * storeNames[] = {"CA","Root","My"};
+
+ unsigned char certBlob[5000];
+ int i, certBlobLen = sizeof(certBlob);
+ X509 *x509issuer = NULL;
+
+ RETURN_OBJ_IF_NULL(x509, NULL);
+ //encode(
+ memset(certBlob,0,sizeof(certBlob));
+ encodeCert(x509,(char *)certBlob,&certBlobLen);
+ cert = CertCreateCertificateContext(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,certBlob,certBlobLen);
+ if(cert == NULL){
+ return NULL;
+ }
+ for( i=0;i<3;i++){
+ issuer=findCertFromStore(cert,storeNames[i]);
+ if(issuer){
+ break;
+ }
+ }
+ if(issuer){
+ //AA100204
+ ddocDecodeX509Data(&x509issuer,issuer->pbCertEncoded,issuer->cbCertEncoded);
+ CertFreeCertificateContext(issuer);
+ }
+ CertFreeCertificateContext(cert);
+
+ return x509issuer;
+
+}
+
+
+//=====================================================================
+// hashes and signes data with EstId card, returns also public_key_blob
+// which can be used in order to verify signature
+// IN dataToBeSigned - source data buffer
+// IN dataLen - how many bytes will be read from source buffer
+// OUT pbKeyBlob - public key buffer( corresponding private key was used to sign.
+// OUT pbKeyBlobLen - public key length in buffer
+// OUT hash - output data buffer for hash
+// OUT hashLen - data length in output buffer
+// OUT hashedSignature - output data buffer for hashed and signed data
+// OUT sigLen - data length in output buffer
+// IN szPin - PIN2 [optional]
+//=====================================================================
+int GetSignedHashWithKeyAndCSP( char *psKeyName, char *psCSPName,
+ const char * dataToBeSigned,unsigned long dataLen,
+ unsigned char *pbKeyBlob, unsigned long *pbKeyBlobLen,
+ unsigned char *hash, unsigned long *hashLen,
+ unsigned char * hashedSignature,unsigned long * sigLen,
+ const char* szPin)
+{
+ int retCode=ERR_OK, l1;
+ HCRYPTPROV hProv = 0;
+ HCRYPTHASH sha1 = 0;
+ HCRYPTKEY hKey = 0;
+ PCCERT_CONTEXT pCert=NULL;
+ BOOL fRes;
+ DWORD dwRes;
+ char *p1 = 0;
+
+ ddocDebug(3, "GetSignedHashWithKeyAndCSP", "key: %s csp: %s, pin-len: %d", psKeyName, psCSPName, (szPin ? strlen(szPin) : 0));
+ // debug
+ ddocDebug(3, "GetSignedHashWithKeyAndCSP", "data to sign: \'%s\' len: %d tlen: %d", dataToBeSigned, dataLen, strlen(dataToBeSigned));
+ //////******************** start task *************************************
+ while(TRUE){
+ //
+ //sprintf(sTemp,"CSP=%s \nCON=%s\n%d",psCSPName,psKeyName,DigiCrypt_FindContext_GetCSPType(psCSPName));
+ //MessageBox(NULL,sTemp,"TEST",MB_OK);
+ //
+ fRes=CryptAcquireContext(&hProv,psKeyName,psCSPName,DigiCrypt_FindContext_GetCSPType(psCSPName),0);//CRYPT_VERIFYCONTEXT);
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "CryptAcquireContext: \'%s\' rc: %d", psKeyName, fRes);
+
+ if(fRes==FALSE){
+ dwRes = GetLastError();
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in CryptAcquireContext: %ld hex: %x", dwRes, dwRes);
+ retCode=ERR_CSP_NO_CARD_DATA;
+ break;
+
+ }
+ fRes=CryptCreateHash(hProv,CALG_SHA1,0,0,&sha1);
+ if(fRes==FALSE){
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "CryptCreateHash RC (bool): %d", (int)fRes);
+ retCode=ERR_CSP_NO_HASH_START;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ // start hash
+ fRes=CryptHashData(sha1,dataToBeSigned,dataLen,0);
+
+ if(fRes==FALSE){
+ retCode=ERR_CSP_NO_HASH;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ if(hash!=NULL){
+ ddocDebug(3, "GetSignedHashWithKeyAndCSP", "caling CryptGetHashParam hash: %s len: %ld", hash, *hashLen);
+ fRes=CryptGetHashParam(sha1,HP_HASHVAL, hash,hashLen ,0);
+ if(fRes==FALSE){
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "CryptGetHashParam RC (bool): %d", (int)fRes);
+ retCode=ERR_CSP_NO_HASH_RESULT;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ // debug
+ l1 = *hashLen * 2 + 10;
+ p1 = (char*)malloc(l1);
+ if(p1) {
+ memset(p1, 0, l1);
+ encode((const byte*)hash, *hashLen, (byte*)p1, &l1);
+ ddocDebug(3, "GetSignedHashWithKeyAndCSP", "hash: %s len: %d", p1, l1);
+ free(p1);
+ p1 = 0;
+ }
+ }
+
+ if(hashedSignature != NULL) {
+ //use by standard way is not allways possible -- AT_SIGNATURE -- main thing is that cert is ok nor the keyspec
+ //instead of that we should use CryptAcquireCertificatePrivateKey function. But then we must change basic context of this function.
+ //workaround -- we try with both keyspecs
+ // set PIN2 for signing if possible
+ if(szPin && strlen(szPin)) {
+ ddocDebug(3, "GetSignedHashWithKeyAndCSP", "Setting PIN len: %d", strlen(szPin));
+ fRes = CryptSetProvParam(hProv, PP_SIGNATURE_PIN, (const BYTE*)szPin, 0 );
+ ddocDebug(3, "GetSignedHashWithKeyAndCSP", "PIN setting: %d", fRes);
+ }
+ fRes=CryptSignHash(sha1,AT_SIGNATURE ,NULL,0, hashedSignature,sigLen);
+ if(fRes==FALSE)
+ {
+ dwRes = GetLastError();
+ //try again with keyspec AT_KEYEXCHANGE
+ if(dwRes==0x8009000d) // wrong keyspec
+ {
+ fRes=CryptSignHash(sha1,AT_KEYEXCHANGE ,NULL,0, NULL,sigLen); //*sigLen should be 128... this can be avoided whi
+ fRes=CryptSignHash(sha1,AT_KEYEXCHANGE ,NULL,0, hashedSignature,sigLen);
+ if(fRes==FALSE)
+ {
+ dwRes = GetLastError();
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in CryptSignHash: %ld", dwRes);
+ retCode=ERR_CSP_SIGN;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ } else if(dwRes == 0x8010006e) {
+ ddocDebug(2, "GetSignedHashWithKeyAndCSP", "user cancelled signing");
+ retCode=ERR_CSP_USER_CANCEL;
+ SET_LAST_ERROR(ERR_CSP_USER_CANCEL);
+ break;
+ }
+ else
+ {
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in signing: %uld hex: %x", dwRes, dwRes);
+ retCode=ERR_CSP_SIGN;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ }
+ } else
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "hashed signature is NULL");
+
+ // we must switsh end and begining
+ // because windows uses little-endian but verification
+ // assumes big-endian
+ reverseArray(hashedSignature, *sigLen);
+
+ if(pbKeyBlob!=NULL){
+ fRes=CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hKey);
+ if(fRes==FALSE){
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in CryptGetUserKey");
+ retCode=ERR_CSP_OPEN_KEY;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ fRes=CryptExportKey(hKey,0,PUBLICKEYBLOB,0,pbKeyBlob,pbKeyBlobLen);
+ if(fRes==FALSE){
+ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in CryptExportKey");
+ retCode=ERR_CSP_READ_KEY;
+ SET_LAST_ERROR(retCode);
+ break;
+ }
+ }
+
+ break;
+ }//while(TRUE)
+ ///********************** free objects ************************************
+ if(hKey){
+ CryptDestroyKey(hKey);hKey=0;
+ }
+ if(sha1){
+ CryptDestroyHash(sha1);sha1= 0;
+ }
+ if(hProv){
+ CryptReleaseContext(hProv,0);
+ }
+ ddocDebug(3, "GetSignedHashWithKeyAndCSP", "end of signing RC: %d", retCode);
+ return retCode;
+ /////*******************************************************************************
+}
+
+//===============================================================
+// This function is used to change order in a massive. Last byte
+// becomes first and so on.
+// IN/OUT array - massive to be changed
+// IN arrayLen - array's length
+//===============================================================
+void reverseArray(unsigned char *array, unsigned long arrayLen)
+{
+ int ri, rj;
+ unsigned char t;
+
+ for (ri = 0, rj = arrayLen - 1; ri < rj; ++ri, --rj) {
+ t = array[ri];
+ array[ri] = array[rj];
+ array[rj] = t;
+ }
+}
+
+
+
+#endif