//============================================================ // Reads in an OCSP Response file in DER format // szFileName - OCSP response file name //============================================================ int ReadOCSPResponse(OCSP_RESPONSE **newOCSP_RESPONSE, const char* szFileName) { BIO *bin = NULL; OCSP_RESPONSE *resp = NULL; int err = ERR_OK; ddocDebug(4, "ReadOCSPResponse", "File: %s", szFileName); RETURN_IF_NULL_PARAM(newOCSP_RESPONSE); RETURN_IF_NULL_PARAM(szFileName); if((bin = BIO_new_file(szFileName, "rb")) != NULL) { ddocDebug(4, "ReadOCSPResponse", "File opened"); resp = d2i_OCSP_RESPONSE_bio(bin, NULL); BIO_free(bin); if (resp == NULL) { err = ERR_OCSP_WRONG_VERSION; } } else { ddocDebug(4, "ReadOCSPResponse", "Cannot read file:%s", szFileName); err =ERR_FILE_READ; } if (err != ERR_OK) SET_LAST_ERROR(err); *newOCSP_RESPONSE = resp; return err; }
STDMETHODIMP CComDigiDocLib::getSupportedFormats(VARIANT *ret) { const char** pArr = ::getSupportedFormats(); unsigned int nElems = 0; SAFEARRAY* pSArr; BSTR HUGEP* pData; // detect number of elements for(; *pArr != NULL; pArr++, nElems++); // initialize SAFEARRAY pSArr = SafeArrayCreateVector(VT_BSTR, 0, nElems); if (pSArr == NULL) { return E_OUTOFMEMORY; } // init variant V_ARRAY(ret) = pSArr; V_VT(ret) = (VT_ARRAY | VT_BSTR); // copy data to variant pArr = ::getSupportedFormats(); SafeArrayAccessData(pSArr, (void HUGEP**)&pData); long lArr[1]; USES_CONVERSION; ddocDebug(1, "getSupportedFormats", "num formats: %d", nElems); for(lArr[0] = 0; lArr[0] < (long)nElems; lArr[0]++) { ddocDebug(1, "getSupportedFormats", "format: %d - %s", lArr[0], pArr[lArr[0]]); pData[lArr[0]] = SysAllocString(A2OLE(pArr[lArr[0]])); } SafeArrayUnaccessData(pSArr); return S_OK; }
//============================================================ // Locates a private key on the token on basis of its CKA_ID attribute. // hSession - card session handle // idData - id value // idLen - length of id value // hKey - address of key handle to be returned // return objects handle or -1 for failure //============================================================ CK_RV LocatePrivateKeyWithId(CK_SESSION_HANDLE hSession, CK_BYTE_PTR idData, CK_ULONG idLen, CK_OBJECT_HANDLE_PTR hKey) { CK_OBJECT_HANDLE Objects[10]; CK_RV rv; CK_ULONG ulObjectCount = sizeof(Objects)/sizeof(CK_OBJECT_HANDLE), i; CK_OBJECT_CLASS ObjClass = CKO_PRIVATE_KEY; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) }, { CKA_ID, (void*)idData, idLen } }; CK_ULONG ulCount = sizeof(Template1) / sizeof(CK_ATTRIBUTE); char buf2[40]; int l2; l2 = sizeof(buf2); bin2hex((const byte*)idData, idLen, (char*)buf2, &l2); ddocDebug(3, "LocatePrivateKeyWithId", "LocatePrivateKey with id: %s", buf2); //Template1[1].pValue = idData; rv = (*ckFunc->C_FindObjectsInit)(hSession, Template1, ulCount); if(rv==CKR_OK) { // Get list of object handles rv = (*ckFunc->C_FindObjects)(hSession,Objects,ulObjectCount, &ulObjectCount); ddocDebug(3, "LocatePrivateKeyWithId", "Find: %d count: %ld", rv, ulObjectCount); if(rv==CKR_OK) { // get labels of all possible private keys for(i = 0; i < ulObjectCount; i++) { ddocDebug(3, "LocatePrivateKeyWithId", "Key handle: %d", Objects[i]); *hKey = Objects[i]; } // for i < ulObjectsCount } } // Remember to call C_FindObjectsFinal to terminate the search rv = (*ckFunc->C_FindObjectsFinal)(hSession); return rv; }
//============================================================ // Loads the PKCS#11 driver and // tests if the driver loaded correctly // Returns 0 for ok otherwise error code //============================================================ int loadAndTestDriver(const char* driver, LIBHANDLE* pLibrary, CK_SLOT_ID* slotids, int slots, CK_ULONG slot) { CK_TOKEN_INFO tokinfo; CK_SLOT_INFO slotinfo; CK_ULONG idlen, i, ok; CK_RV rv; int err = ERR_OK; // initialize *pLibrary = NULL; memset(slotids, 0, sizeof(CK_SLOT_ID) * slots); // try to load the driver *pLibrary = initPKCS11Library(driver); if(!(*pLibrary)) SET_LAST_ERROR_RETURN_CODE(ERR_PKCS_LIB_LOAD); idlen = slots; rv = GetSlotIds(slotids, &idlen); ddocDebug(3, "loadAndTestDriver", "RV: %d slots: %ld", (int)rv, (long)idlen); if (rv != CKR_OK) { err = ERR_PKCS_SLOT_LIST; SET_LAST_ERROR(err); } if ((slot < 0) || (slot >= idlen)) { err = ERR_PKCS_WRONG_SLOT; SET_LAST_ERROR(err); } // it's useful to test DLL load status this way: ok = 0; for(i = 0; i < idlen; i++) { rv = GetSlotInfo(&slotinfo, slotids[i]); if(slotinfo.flags & CKF_TOKEN_PRESENT) { ddocDebug(3, "loadAndTestDriver", "Read Token: %ld", (long)i); rv = GetTokenInfo(&tokinfo, slotids[i]); // if !CKR_OK test tokinfo.label[31] = 0; ddocDebug(3, "loadAndTestDriver", "RV: %d Token: %s", (int)rv, tokinfo.label); if(rv != CKR_OK) slotids[i] = INVALID_SLOTIID; // set bad slotids to 0 else ok++; // count the good slots } else { slotids[i] = INVALID_SLOTIID; // no tokne in this slot } } // fill other slotid's with invalid slotid for(i = idlen; i < (CK_ULONG)slots; i++) slotids[i] = INVALID_SLOTIID; if(ok < slot) { err = ERR_PKCS_CARD_READ; // if not enough good slots SET_LAST_ERROR(err); } // in case of error try to unload the module and notify caller if (err) { if (*pLibrary) closePKCS11Library(*pLibrary, 0); *pLibrary = NULL; } return err; }
//-------------------------------------------------- // Prepares a new signature for signing and calculates // the final hash value to sign. // pSigDoc - signed document object // ppSigInfo - pointer for address of newly allocated signature // manifest - manifest or role // city - signers address , city // state - signers address , state or province // zip - signers address , postal code // country - signers address , country name // id - id for new signature. Optional, use NULL for default // return returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocPrepareSignature(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* manifest, const char* city, const char* state, const char* zip, const char* country, X509* pCert, const char* id) { int err = ERR_OK, l1; DigiDocMemBuf mbuf1, *pMBuf1; char buf1[50]; mbuf1.pMem = 0; mbuf1.nLen = 0; ddocDebug(3, "ddocPrepareSignature", "Preparing signature manifest: %s country: %s, state: %s, city: %s, zip: %s, cert: %s, id: %s", (manifest ? manifest : "NULL"), (country ? country : "NULL"), (state ? state : "NULL"), (city ? city : "NULL"), (zip ? zip : "NULL"), (pCert ? "OK" : "ERROR"), (id ? id : "NULL")); // check mandator fields RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(ppSigInfo); RETURN_IF_NULL_PARAM(pCert); clearErrors(); // add new signature err = SignatureInfo_new(ppSigInfo, pSigDoc, id); RETURN_IF_NOT(err == ERR_OK, err); // automatically calculate doc-info elements for this signature addAllDocInfos(pSigDoc, *ppSigInfo); // add signature production place if (city || state || zip || country) err = setSignatureProductionPlace(*ppSigInfo, city, state, zip, country); // add user roles/manifests if (manifest) err = addSignerRole(*ppSigInfo, 0, manifest, -1, 0); RETURN_IF_NOT(err == ERR_OK, err); // add signers certificate err = setSignatureCert(*ppSigInfo, pCert); RETURN_IF_NOT(err == ERR_OK, err); // timestamp createTimestamp(pSigDoc, (char*)buf1, sizeof(buf1)); setString((char**)&((*ppSigInfo)->szTimeStamp), (const char*)buf1, -1); // now calculate signed properties digest err = calculateSignedPropertiesDigest(pSigDoc, *ppSigInfo); // TODO: replace later pMBuf1 = ddocDigestValue_GetDigestValue((*ppSigInfo)->pSigPropDigest); ddocSigInfo_SetSigPropRealDigest(*ppSigInfo, (const char*)pMBuf1->pMem, pMBuf1->nLen); // signature type & val ddocSignatureValue_new(&((*ppSigInfo)->pSigValue), 0, SIGN_RSA_NAME, 0, 0); // calc signed-info digest l1 = sizeof(buf1); err = calculateSignedInfoDigest(pSigDoc, *ppSigInfo, (byte*)buf1, &l1); err = ddocSigInfo_SetSigInfoRealDigest(*ppSigInfo, buf1, l1); // debug output - final hash to sign pMBuf1 = ddocDigestValue_GetDigestValue((*ppSigInfo)->pSigInfoRealDigest); ddocEncodeBase64(pMBuf1, &mbuf1); ddocDebug(3, "ddocPrepareSignature", "signing hash %s len: %d b64len: %d", (char*)mbuf1.pMem, mbuf1.nLen, l1); ddocMemBuf_free(&mbuf1); return err; }
//============================================================ // Locates a private key on the token on basis of its CKA_LABEL attribute. // hSession - card session handle // idData - address of an array of label buffers // idlen - array of label lengths // return objects handle or -1 for failure //============================================================ CK_RV LocatePrivateKey(CK_SESSION_HANDLE hSession, char idData[20][20], CK_ULONG idLen[20], CK_OBJECT_HANDLE_PTR hKeys) { CK_OBJECT_HANDLE Objects[10]; CK_RV rv; CK_ULONG ulObjectCount = sizeof(Objects)/sizeof(CK_OBJECT_HANDLE), i; // CK_BBOOL IsTrue = TRUE; CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE; // Set up a template to search for all Private Key tokens // Given the session context, that is associated with // one slot we will find only one object CK_OBJECT_CLASS ObjClass = CKO_PRIVATE_KEY; char buf1[20]; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) } }; CK_ATTRIBUTE Template2[] = { { CKA_ID, (void*)0, idLen[0] } }; CK_ULONG ulCount = sizeof(Template1) / sizeof(CK_ATTRIBUTE); /* ** Initiate the object search C_FindObjectsInit initializes a search for token and session objects that match a template. hSession is the sessions handle; pTemplate points to a search template that specifies the attribute values to match; ulCount is the number of attributes in the search template. The matching criterion is an exact byte-for-byte match with all attributes in the template. To find all objects, set ulCount to 0. */ ddocDebug(3, "LocatePrivateKey", "LocatePrivateKey"); rv = (*ckFunc->C_FindObjectsInit)(hSession,Template1,ulCount); if(rv==CKR_OK) { // Get list of object handles rv = (*ckFunc->C_FindObjects)(hSession,Objects,ulObjectCount, &ulObjectCount); ddocDebug(3, "LocatePrivateKey", "Find: %d count: %ld", rv, ulObjectCount); if(rv==CKR_OK) { // get labels of all possible private keys for(i = 0; i < ulObjectCount; i++) { hKeys[i] = Objects[i]; ulCount = sizeof(Template2) / sizeof(CK_ATTRIBUTE); // get key id length rv = (*ckFunc->C_GetAttributeValue)(hSession, hKeys[i], Template2, ulCount); if(rv == CKR_OK) { idLen[i] = Template2[0].ulValueLen; // now get key id data Template2[0].pValue = buf1; memset(buf1, 0, sizeof(buf1)); rv = (*ckFunc->C_GetAttributeValue)(hSession, hKeys[i], Template2, ulCount); ddocDebug(3, "LocatePrivateKey", "key: %d id %s len: %ld", i, buf1, idLen[i]); memcpy(idData[i], buf1, idLen[i]); } } // for i < ulObjectsCount } } // Remember to call C_FindObjectsFinal to terminate the search rv = (*ckFunc->C_FindObjectsFinal)(hSession); return rv; }
//============================================================ // Locates and reads users certificate from smartcard // slot - number of the slot for decryption key. On ID card allways 0 // ppCert - address for newly allocated certificate pointer // return error code or ERR_OK //============================================================ EXP_OPTION int findUsersCertificate(int slot, X509** ppCert) { int err = ERR_OK, l1, l2; LIBHANDLE pLibrary = 0; CK_RV rv = 0; CK_SLOT_ID slotids[20], slId; CK_OBJECT_HANDLE hCert; CK_SESSION_HANDLE hSession = 0; CK_ULONG certLen; CK_BYTE certData[2048]; char driver[100]; *ppCert = 0; snprintf(driver, sizeof(driver), "DIGIDOC_DRIVER_%d_FILE", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1)); ddocDebug(3, "findUsersCertificate", "Slot: %d Driver nr: %d - %s", slot, ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1), ConfigItem_lookup(driver)); err = loadAndTestDriver(ConfigItem_lookup(driver), &pLibrary, (CK_SLOT_ID*)slotids, 20, (CK_ULONG)slot); if(err) return err; // find the right slotid for(l1 = l2 = 0; l1 < 20; l1++) { if(slotids[l1] != INVALID_SLOTIID) { if(l2 == slot) slId = slotids[l1]; l2++; } } // open session hSession = OpenSession(slId, NULL); if (hSession == CK_INVALID_HANDLE) { SET_LAST_ERROR(ERR_PKCS_LOGIN); return ERR_PKCS_LOGIN; } ddocDebug(3, "findUsersCertificate", "OpenSession ok, hSession = %d", (int)hSession); // get cert memset(certData, 0, sizeof(certData)); certLen = sizeof(certData); hCert = LocateCertificate(hSession, certData, &certLen, 0, 0, 0); ddocDebug(3, "findUsersCertificate", "hCert = %d, len: %d", (int)hCert, certLen); if (hCert == (CK_OBJECT_HANDLE)-1) { err = ERR_PKCS_CERT_LOC; SET_LAST_ERROR(err); } // set cert data if(certLen) err = ddocDecodeX509Data(ppCert, certData, certLen); ddocDebug(3, "findUsersCertificate", "RV: %d, cert: %s", (int)rv, (*ppCert ? "OK" : "NULL")); if(hSession) closePKCS11Library(pLibrary, hSession); return err; }
//-------------------------------------------------- // Helper function to read OCSP_RESPONSE from binary input data // ppResp - address of newly allocated OCSP_RESPONSE object // pMBufInData - input data // returns error code or ERR_OK //-------------------------------------------------- int ddocOcspReadOcspResp(OCSP_RESPONSE** ppResp, DigiDocMemBuf* pMBufInData) { int err = ERR_OK; unsigned char* p1; RETURN_IF_NULL_PARAM(ppResp); RETURN_IF_NULL_PARAM(pMBufInData); RETURN_IF_NULL_PARAM(pMBufInData->pMem); ddocDebug(4, "ddocOcspReadOcspResp", "converting: %d bytes to OCSP_RESPONSE", pMBufInData->nLen); p1 = (unsigned char*)pMBufInData->pMem; d2i_OCSP_RESPONSE(ppResp, (const unsigned char**)&p1, pMBufInData->nLen); ddocDebug(4, "ddocOcspReadOcspResp", "OCSP_RESPONSE: %s", (*ppResp ? "OK" : "ERR")); return err; }
//============================================================ // Decodes base64 (PEM) OCSP_RESPONSE data and returns a OCSP_RESPONSE object // ppResp - pointer to a buffer to receive newly allocated OCSP_RESPONSE pointer // data - (PEM) OCSP_RESPONSE data // len - length of data in bytes //============================================================ EXP_OPTION int ddocDecodeOCSPResponsePEMData(OCSP_RESPONSE **ppResp, const byte* data, int len) { byte* p1 = 0; int l1 = 0, err = ERR_OK; // check input params RETURN_IF_NULL_PARAM(data); RETURN_IF_NULL_PARAM(ppResp); // mark as not read yet *ppResp = 0; // allocate memory for decoding l1 = len; // should be enough as it shrinks p1 = (byte*)malloc(l1); RETURN_IF_BAD_ALLOC(p1); memset(p1, 0, l1); // decode base64 data decode((const byte*)data, len, p1, &l1); // decode OCSP err = ddocDecodeOCSPResponseData(ppResp, p1, l1); // cleanup if(p1) free(p1); ddocDebug(3, "ddocDecodeOCSPResponsePEMData", "Decoding %d bytes PEM data - OSCP_RESPONSE %s", len, (*ppResp ? "OK" : "ERROR")); return err; }
//-------------------------------------------------- // Converts xml symbols to corresponding escapes // src - string with xml special sybols // returns string with esacpes //-------------------------------------------------- char* escape2xmlsym(const char* src) { char* dest = 0, c; int i, j, l, k; l = strlen(src); dest = (char*)malloc(l+1); SET_LAST_ERROR_RETURN_IF_NOT(dest, ERR_BAD_ALLOC, NULL); memset(dest, 0, l+1); for(i = j = 0; i < l; i++, j++) { if(src[i] == '&') { k = findEscape(src + i, &c); if(k && c) { dest[j] = c; i += k - 1; } else dest[j] = src[i]; } else dest[j] = src[i]; } ddocDebug(4, "escape2xmlsym", "%s --> %s", src, dest); return dest; }
//============================================================ // Attempts to load and initialize on PKCS#11 driver DLL. //============================================================ EXP_OPTION LIBHANDLE initPKCS11Library(const char* libName) { LIBHANDLE pLibrary = 0; CK_C_GetFunctionList pC_GetFunctionList; CK_RV rv; // load PKCS#11 driver ddocDebug(3, "initPKCS11Library", "Loading driver: %s\n", libName); #ifdef WIN32 pLibrary = LoadLibrary((LPCSTR)libName); #else pLibrary = dlopen(libName, RTLD_NOW); #endif if(pLibrary != NULL) { // printf("Resolve PKCS#11 function index!\n"); // Get function pointer to C_GetFunctionList #ifdef WIN32 pC_GetFunctionList = (CK_C_GetFunctionList)GetProcAddress(/*(HINSTANCE__*)*/pLibrary, "C_GetFunctionList"); #else pC_GetFunctionList = (CK_C_GetFunctionList)dlsym(pLibrary, "C_GetFunctionList"); #endif if(pC_GetFunctionList != NULL) { ddocDebug(3, "initPKCS11Library", "Getting PKCS#11 func!\n"); // Get function pointers to all PKCS #11 functions rv = (*pC_GetFunctionList)(&ckFunc); if(rv == CKR_OK) { ddocDebug(3, "initPKCS11Library", "Initializing PKCS#11 library:"); // Initalize Cryptoki rv = (*ckFunc->C_Initialize)(0); ddocDebug(3, "initPKCS11Library", "Initlialized: %d", (int)rv); if(rv != CKR_OK) { ddocDebug(2, "initPKCS11Library", "Error initializing library!\n"); pLibrary = NULL; // error initializing the library } } else { ddocDebug(2, "initPKCS11Library", "Error getting PKCS#11 func!"); pLibrary = NULL; // error getting function pointers } } else { ddocDebug(2, "initPKCS11Library", "Error resolving PKCS#11 function index!"); pLibrary = NULL; // error getting function list function } } else { #ifdef WIN32 ddocDebug(2, "initPKCS11Library", "Error loading driver : %s", libName); #else ddocDebug(2, "initPKCS11Library", "Error loading driver : %s", dlerror()); #endif } return pLibrary; }
//============================================================ // Cleanup PKCS#11 library session //============================================================ EXP_OPTION void closePKCS11Library(LIBHANDLE pLibrary, CK_SESSION_HANDLE hSession) { CK_RV rv; // close session if(hSession > 0) { ddocDebug(3, "closePKCS11Library", "Closing PKCS#11 session!"); rv = (*ckFunc->C_CloseSession)(hSession); } // finalize library rv = (*ckFunc->C_Finalize)(0); // remove .so from memory ddocDebug(3, "closePKCS11Library", "Closing PKCS#11 library!\n"); if(pLibrary) #ifdef WIN32 FreeLibrary(/*(HINSTANCE__*)*/pLibrary); #else dlclose(pLibrary); #endif }
//-------------------------------------------------- // Helper function to write OCSP_RESPONSE to binary output data // pResp - address of OCSP_RESPONSE object // pMBufOutData - output data // returns error code or ERR_OK //-------------------------------------------------- int ddocOcspWriteOcspResp(OCSP_RESPONSE* pResp, DigiDocMemBuf* pMBufOutData) { int err = ERR_OK, l1; unsigned char* p1; RETURN_IF_NULL_PARAM(pResp); RETURN_IF_NULL_PARAM(pMBufOutData); pMBufOutData->pMem = NULL; pMBufOutData->nLen = 0; // find out how big a buffer we need l1 = i2d_OCSP_RESPONSE(pResp, NULL); ddocDebug(4, "ddocOcspReadOcspResp", "converting: %d bytes from OCSP_RESPONSE", l1); // alloc mem err = ddocMemSetLength(pMBufOutData, l1 + 50); p1 = (unsigned char*)pMBufOutData->pMem; l1 = i2d_OCSP_RESPONSE(pResp, &p1); pMBufOutData->nLen = l1; ddocDebug(4, "ddocOcspReadOcspResp", "Converted data: %d", l1); return err; }
//============================================================ // Sign a string using a private key referred by the supplied handle. // hSession - card session handle // hPrivateKey - private key handle // Signature - buffer for signature // ulSignatureLen - signature buffer length // sigData - data to be signed //============================================================ CK_RV SignData(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPrivateKey, CK_BYTE* Signature, CK_ULONG* ulSignatureLen, CK_BYTE* sigData, CK_ULONG dataLen) { // Set up mechanism for PKCS #1 signing CK_MECHANISM Mechanism = { CKM_RSA_PKCS, 0, 0 }; // Initiate the signature operation CK_RV rv = (*ckFunc->C_SignInit)(hSession,&Mechanism,hPrivateKey); if(rv == CKR_OK) { // Kommentaar: Realiseeritud meetodi CKM_RSA_PKCS jaoks. rv = (*ckFunc->C_Sign)(hSession, sigData, dataLen, Signature, ulSignatureLen); if(rv != CKR_OK) ddocDebug(1, "SignData", "Error signing - sess: %uld pkey: %uld slen: %uld dlen: %uld. RV = %uld\n", hSession, hPrivateKey, ulSignatureLen, dataLen, rv); } // if C_SignInit else ddocDebug(1, "SignData", "Error initing sign session. RV = %ld", rv); ddocDebug(3, "SignData", "RV = %ld", rv); return rv; }
//-------------------------------------------------- // Decodes a single hex digit // h - hex digit // return binary value //-------------------------------------------------- byte h2b(char h) { int i; for(i = 0; i < 16; i++) { if(g_hexChars[i] == h || g_hexChars[i] == toupper(h)) return (byte)i; } // if not found then return an error ddocDebug(1, "h2b", "Invalid hex byte: %c", h); SET_LAST_ERROR(ERR_BAD_PARAM); return 0; // MSTERN: incorrect, VS - yes return -1 if not found. This is an error code }
//============================================================ // Opens smart card session. // slotId - id of the sert slot // pin - card pin // return session id or -1 for failure //============================================================ CK_SESSION_HANDLE OpenSession(CK_SLOT_ID slotId, const char *pin) { CK_SESSION_HANDLE hSession = 0; /* Ainult SERIAL_SESSION toetatud, Digiallkirja andvat privaatvo~tit kasutav sessioon on initsialiseeritud CKS_RO_USER_FUNCTIONS staatusesse, seda on tehtud Netscape lolli- tamiseks, et see igal vo~imalikul ja vo~imatul juhul ei ku"siks pin'i vo~tme jaoks mida ta niiehknii kasutada ei oska. Selle jaoks tuleb vajaduse korral ikka C_Login va"lja kutsuda. */ CK_RV rv = (*ckFunc->C_OpenSession)(slotId, CKF_SERIAL_SESSION,0,0,&hSession); ddocDebug(3, "OpenSession", "Open sess for slot id: %u - sess: %uld RV = %u", slotId, hSession, rv); if(rv == CKR_OK && pin) { // don't login if pin is null. Session can be used also to read certs. /* Kommentaar: Ainult CKU_USER toetatud. */ rv = (*ckFunc->C_Login)(hSession, CKU_USER, (unsigned char*)pin, strlen(pin)); ddocDebug(3, "OpenSession", "Login for slot id: %u - sess: %uld RV = %u", slotId, hSession, rv); if(rv != CKR_OK) hSession = CK_INVALID_HANDLE; // mark session bad! } // Return the session handle and exit return hSession; }
////////////////////////////////////////////////////////// // DigiDoc file handling methods //AA 2004/05/20 - ei saanud salvestada faili, kui kataloogis olid täppidega tähed STDMETHODIMP CComSignedDoc::createSignedDoc(BSTR szOutputFile, BSTR szOldFileName, long *pRetError) { USES_CONVERSION; char *p1 = 0; if(m_pSignedDoc) { p1 = GetBSTR(szOutputFile); ddocDebug(3, "CComSignedDoc::createSignedDoc", "Writing to: %s", p1); *pRetError = ::createSignedDoc(m_pSignedDoc, (::SysStringLen(szOldFileName) > 0) ? GetBSTR(szOldFileName) : NULL, p1); ddocDebug(3, "CComSignedDoc::createSignedDoc", "Wrote"); if(m_szDigiDocFile) { ddocDebug(3, "CComSignedDoc::createSignedDoc", "Free: %s", m_szDigiDocFile); free(m_szDigiDocFile); m_szDigiDocFile = 0; } ddocDebug(3, "CComSignedDoc::createSignedDoc", "Assign: %s", p1); m_szDigiDocFile = strdup(p1); } return S_OK; }
//============================================================ // Decodes binary (DER) OCSP_RESPONSE data and returns a OCSP_RESPONSE object // ppResp - pointer to a buffer to receive newly allocated OCSP_RESPONSE pointer // data - (DER) OCSP_RESPONSE data // len - length of data in bytes //============================================================ EXP_OPTION int ddocDecodeOCSPResponseData(OCSP_RESPONSE **ppResp, const byte* data, int len) { BIO* b1 = 0; // check input params RETURN_IF_NULL_PARAM(data); RETURN_IF_NULL_PARAM(ppResp); // mark as not read yet *ppResp = 0; // create BIO b1 = BIO_new_mem_buf((void*)data, len); RETURN_IF_NOT(b1, ERR_NULL_POINTER); // decode OCSP *ppResp = d2i_OCSP_RESPONSE_bio(b1, NULL); BIO_free(b1); ddocDebug(3, "ddocDecodeOCSPResponseData", "Decoding %d bytes DER data - OCSP_RESPONSE %s", len, (*ppResp ? "OK" : "ERROR")); RETURN_IF_NOT(*ppResp, ERR_OCSP_UNKNOWN_TYPE); return ERR_OK; }
EXP_OPTION void addError(int code, char *fileName, int line, char *assertion) { //no errors found yet. Set a trace-back mark to the end of array. //printf("Error : %d at %s line %d, assertion %s\n", code, fileName, line, assertion); ThreadErrors *threadErrors; THREAD_ID Tid = getTid(); //Find our identity threadErrors = findThreadErrorsByTid(Tid); // printf("addError init: tid=%ld, threadErrors=%p\n", Tid, threadErrors); if (threadErrors == NULL) { //This Tid has no entry in ThreadErrors table threadErrors = addThreadErrorsByTid(Tid); // MEMLEAK: ??? if (threadErrors == NULL) return; // What else can we do? } // printf("addError step 1 : tid=%ld, threadErrors=%p\n", Tid, threadErrors); if(threadErrors->currentErrorIdx < 0) resetError(&(threadErrors->ddocLastErrors[ERROR_BUF_LENGTH - 1])); threadErrors->currentErrorIdx++; //index at the end -> roll it over to the beginning if(threadErrors->currentErrorIdx == ERROR_BUF_LENGTH) threadErrors->currentErrorIdx = 0; //set the information ddocDebug(4, "addError", "Index: %d Error : %d at %s line %d, assertion %s", threadErrors->currentErrorIdx, code, fileName, line, assertion); threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].code = code; threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].fileName = fileName; threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].line = line; threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].assertion = assertion; //index at the end? Set the traceback mark to the beginning if(threadErrors->currentErrorIdx == ERROR_BUF_LENGTH - 1) resetError(&(threadErrors->ddocLastErrors[0])); else //set the traceback mark to the next position resetError(&(threadErrors->ddocLastErrors[threadErrors->currentErrorIdx + 1])); threadErrors->readErrorIdx = threadErrors->currentErrorIdx; }
//-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // pSigDoc - signed document object if exists. Can be NULL // szFileName - digidoc filename // szDataFileName - name of the file where to store embedded data. // szDocId - DataFile Id atribute value // szCharset - convert DataFile content to charset //-------------------------------------------------- EXP_OPTION int ddocExtractDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset) { FILE *fIn = 0, *fOut = 0; int err = ERR_OK, i, nRead, lt, la, lc, j, ld, lb, l, eState = 0, fs = 0; long len, lExtr = 0, lSize = 0; char chars[1050], tag[100], attr[100], con[1030], dec[70], b64line[70]; unsigned char b64 = 0, nNc = 0, bFound = 0; void *pBuf; EVP_ENCODE_CTX ectx; #ifdef WIN32 wchar_t *convFileName = 0, *convDataFileName = 0; i= 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "ddocExtractDataFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i); i= 0; err = utf82unicode((const char*)szDataFileName, (char**)&convDataFileName, &i); ddocDebug(3, "ddocExtractDataFile", "dfile: %s, conv-dfile: %s len: %d", szDataFileName, convDataFileName, i); #endif RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(szDataFileName); RETURN_IF_NULL_PARAM(szDocId); RETURN_IF_NULL_PARAM(szCharset); clearErrors(); ddocDebug(3, "ddocExtractDataFile", "SigDoc: %s, docid: %s, digidoc: %s, file: %s, charset: %s", (pSigDoc ? "OK" : "NULL"), szDocId, szFileName, szDataFileName, szCharset); if(szCharset && !strcmp(szCharset, "NO-CHANGE")) nNc = 1; // try reading from memory if already cached? nRead = ddocGetDataFileCachedData(pSigDoc, szDocId, &pBuf, &len); if(pBuf) { // gotcha ddocDebug(3, "ddocSaxExtractDataFile", "Using cached data: %d bytes", len); #ifdef WIN32 if((fOut = _wfopen(convDataFileName, L"wb")) != NULL) { #else if((fOut = fopen(szDataFileName, "wb")) != NULL) { #endif fwrite(pBuf, 1, len, fOut); fclose(fOut); } else { free(pBuf); ddocDebug(1, "ddocSaxExtractDataFile", "Error writing file: %s", szDataFileName); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); } free(pBuf); return nRead; } // open ddoc file #ifdef WIN32 if((fIn = _wfopen(convFileName, L"rb")) != NULL) { #else if((fIn = fopen(szFileName, "rb")) != NULL) { #endif ddocDebug(3, "ddocExtractDataFile", "Opened ddoc-file: %s", szFileName); do { nRead = fread(chars, 1, 1024, fIn); chars[nRead] = 0; ddocDebug(6, "ddocExtractDataFile", "Parsing %d bytes: \n%s\n", nRead, chars); // handle read data for(i = 0; i < nRead; i++) { switch(eState) { case ST_START: // search '<?xml' if(chars[i] == '<' && !strncmp(chars+i, "<?xml", 5)) { eState = ST_XML; i += 4; } break; case ST_XML: // search '<' if(chars[i] == '<') { eState = ST_TAG_NM; lt = 0; tag[lt] = 0; } break; case ST_TAG_NM: // read tag name if(isalnum(chars[i]) || chars[i] == ':' || chars[i] == '/') { if(lt < sizeof(tag)-1) { tag[lt] = chars[i]; tag[++lt] = 0; } else { ddocDebug(1, "ddocSaxExtractDataFile", "Invalid xml tag-len > %d", sizeof(tag)); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } } else if(chars[i] == '>') { // tag ended - content eState = ST_CON; } else { // expecting atributes eState = ST_TAG_WS; } break; case ST_TAG_WS: if(chars[i] == '>') { if(bFound) { eState = ST_DF_CON; if(b64) EVP_DecodeInit(&ectx); } else eState = ST_CON; // tag endded - content lc = 0; con[lc] = 0; } else if(isalnum(chars[i])) { eState = ST_ATTR_NM; // attr name started la = 0; attr[la] = chars[i]; attr[++la] = 0; } break; case ST_ATTR_NM: if(isalnum(chars[i])) { if(la < (int)sizeof(attr)-1) { attr[la] = chars[i]; attr[++la] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr name: %s", attr); break; //19.11.08 added support for ' } else if(chars[i] == '\"'/*|| chars[i] == '\''*/) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; fs = 2; } else if(chars[i] == '\'' && fs==0) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; fs = 1; } else { eState = ST_ATTR_WS; } break; case ST_ATTR_WS: //19.11.08 added support for ' if(chars[i] == '\"'/*|| chars[i] == '\''*/) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; } else if(chars[i] == '\'' && fs==1) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; } else { eState = ST_TAG_WS; } break; case ST_ATTR_CON: //19.11.08 added support for ' if(chars[i] != '\"' /*&& chars[i] != '\''*/) { if(lc < (int)sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr content: %s", attr); } else if(chars[i] == '\'' && fs==1) { if(lc < (int)sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr content: %s", attr); } else { eState = ST_TAG_WS; // attribute value complete if(!strcmp(tag, "DataFile")) { // ddocDebug(3, "ddocSaxExtractDataFile", "DataFile start, attr: %s", attr); if(!strcmp(attr, "ContentType")) { b64 = (!strcmp(con, "EMBEDDED_BASE64")) ? 1 : 0; lb = 0; b64line[0] = 0; } if(!strcmp(attr, "Size") && bFound) { lSize = atol(con); } if(!strcmp(attr, "Id")) { ddocDebug(3, "ddocSaxExtractDataFile", "Found Id: %s searching id: %s", con, szDocId); if(!strcmp(con, szDocId)) { bFound = 1; #ifdef WIN32 fOut = _wfopen(convDataFileName, L"wb"); ddocDebug(3, "ddocSaxExtractDataFile", "Opening file: %s handle: %s", convDataFileName, (fOut ? "OK" : "NULL")); #else fOut = fopen(szDataFileName, "wb"); ddocDebug(3, "ddocSaxExtractDataFile", "Opening file: %s handle: %s", szDataFileName, (fOut ? "OK" : "NULL")); #endif if(!fOut) { SET_LAST_ERROR(ERR_FILE_WRITE); err = ERR_FILE_WRITE; return err; } } } } } break; case ST_CON: if(chars[i] == '<') { eState = ST_TAG_NM; lt = 0; tag[lt] = 0; } else { //con[lc] = chars[i]; //con[++lc] = 0; } break; case ST_DF_START: // find tag end if(chars[i] == '>') { eState = ST_DF_CON; lc = 0; con[lc] = 0; if(b64) EVP_DecodeInit(&ectx); } break; case ST_DF_CON: if(chars[i] == '<') { eState = ST_DF_TAG; lt = 0; tag[lt] = 0; } else { if(lc < (int)sizeof(con) - 1) { if(b64 && !nNc) { for(l = 0; l < lc; ) { while(lb < 64 && l < lc && l < sizeof(con)) { if(con[l] != '\n' && con[l] != '\r') b64line[lb++] = con[l]; l++; } if(lb == 64) { b64line[lb++] = '\n'; b64line[lb] = 0; ld = sizeof(dec); dec[0] = 0; EVP_DecodeUpdate(&ectx, (unsigned char*)dec, &ld, (unsigned char*)b64line, lb); lExtr += ld; if(ld > 0) fwrite(dec, 1, ld, fOut); lb = 0; } } } else if(nNc || !b64) { lExtr += lc; fwrite(con, 1, lc, fOut); } lc = 0; } if(lc < sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } } break; case ST_DF_TAG: if(/*isalnum(chars[i]) || chars[i] == ':' || chars[i] == '/' ||*/ chars[i] != '>') { if(lt < sizeof(tag)-1) { tag[lt] = chars[i]; tag[++lt] = 0; } else { ddocDebug(1, "ddocSaxExtractDataFile", "Invalid xml tag-len > %d", sizeof(tag)); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } } else { // DF intenal tag name ready if(!strcmp(tag, "/DataFile")) { // end of DF eState = ST_DF_END; } else { // wrong tag - this is content if(lc < sizeof(con)-1) { con[lc] = '<'; for(j = 0; j < lt; j++) con[++lc] = tag[j]; con[++lc] = '>'; con[++lc] = 0; } eState = ST_DF_CON; } } if(eState != ST_DF_END) break; case ST_DF_END: if(b64 && !nNc) { if(lc > 0) { for(l = 0; l < lc; ) { while(lb < 64 && l < lc) { if(con[l] != '\n' && con[l] != '\r') b64line[lb++] = con[l]; l++; } b64line[lb++] = '\n'; b64line[lb] = 0; ld = sizeof(dec); dec[0] = 0; EVP_DecodeUpdate(&ectx, (unsigned char*)dec, &ld, (unsigned char*)b64line, lb); lExtr += ld; if(ld > 0) fwrite(dec, 1, ld, fOut); lb = 0; } } ld = 0; dec[ld] = 0; EVP_DecodeFinal(&ectx, (unsigned char*)dec, &ld); lExtr += ld; if(ld) fwrite(dec, 1, ld, fOut); } else if(nNc || !b64) { if(lc) { lExtr += lc; fwrite(con, 1, lc, fOut); lc = 0; } } i = sizeof(chars); //AM 24.09.08 RIK eState = ST_DF_END_END; break; } } //AM 24.09.08 RIK ST_DF_END to ST_DF_END_END_END } while(nRead > 0 && !err && eState < ST_DF_END_END); } else { ddocDebug(1, "ddocExtractDataFile", "Error reading file: %s", szFileName); SET_LAST_ERROR(ERR_FILE_READ); } if(fIn) fclose(fIn); if(fOut) fclose(fOut); if(!nNc && lSize != lExtr) { ddocDebug(1, "ddocExtractDataFile", "Warning! Extracted: %ld bytes but expected: %ld bytes", lExtr, lSize); //SET_LAST_ERROR(ERR_FILE_READ); //err = ERR_FILE_READ; } if(!bFound) { ddocDebug(1, "ddocExtractDataFile", "DF: %s not found", szDocId); SET_LAST_ERROR(ERR_FILE_WRITE); err = ERR_FILE_WRITE; } ddocDebug(3, "ddocExtractDataFile", "Extracted DF: %s to %s size: %ld expected: %ld", szDocId, szDataFileName, lExtr, lSize); #ifdef WIN32 free(convFileName); free(convDataFileName); #endif return err; }
//============================================================ // Decrypts RSA encrypted data with the private key // slot - number of the slot for decryption key. On ID card allways 0 // pin - corresponding pin for the key. On ID card - PIN1 // encData - encrypted data // encLen - length of encrypted data // decData - buffer for decrypted data // encLen - length of buffer. Will be modified by amount of decrypted data // return error code or ERR_OK //============================================================ EXP_OPTION int decryptWithEstID(int slot, const char* pin, const char* encData, int encLen, char* decData, int *decLen) { int err = ERR_OK, l1, l2; LIBHANDLE pLibrary = 0; CK_ULONG keyIdLen[20]; CK_RV rv; CK_SLOT_ID slotids[20], slId; CK_SESSION_HANDLE hSession = 0; CK_OBJECT_HANDLE hPrivateKey, hKeys[20]; char keyId[20][20]; char driver[100]; CK_MECHANISM Mechanism = { CKM_RSA_PKCS, 0, 0 }; CK_ULONG outlen; ddocDebug(3, "decryptWithEstID", "slot: %d enc-data: %d bytes buffer size: %d", slot, encLen, *decLen); snprintf(driver, sizeof(driver), "DIGIDOC_DRIVER_%d_FILE", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1)); ddocDebug(3, "decryptWithEstID", "Driver nr: %d - %s", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1), ConfigItem_lookup(driver)); err = loadAndTestDriver(ConfigItem_lookup(driver), &pLibrary, (CK_SLOT_ID*)slotids, 20, (CK_ULONG)slot); if(err) return err; // find the right slotid for(l1 = l2 = 0; l1 < 20; l1++) { if(slotids[l1] != INVALID_SLOTIID) { if(l2 == slot) slId = slotids[l1]; l2++; } } // open session hSession = OpenSession(slId, pin); if (hSession == CK_INVALID_HANDLE) { SET_LAST_ERROR(ERR_PKCS_LOGIN); return ERR_PKCS_LOGIN; } ddocDebug(3, "decryptWithEstID", "OpenSession ok, hSession = %d", (int)hSession); // get private key for(l1 = 0; l1 < 20; l1++) { memset(keyId[l1], 0, 20); keyIdLen[l1] = 0; } err = LocatePrivateKey(hSession, keyId, keyIdLen, hKeys); hPrivateKey = hKeys[0]; //??? //ddocDebug(3, "decryptWithEstID", "Priv key: %s", keyId); //if (hPrivateKey == CK_INVALID_HANDLE) { SET_LAST_ERROR(ERR_PKCS_PK); return ERR_PKCS_PK; } // init decrypt rv = (*ckFunc->C_DecryptInit)(hSession, &Mechanism, hPrivateKey); ddocDebug(3, "decryptWithEstID", "DecryptInit: %d", (int)rv); if(rv != CKR_OK) SET_LAST_ERROR_RETURN(ERR_DENC_DECRYPT, ERR_DENC_DECRYPT) // decrypt data outlen = *decLen; rv = (*ckFunc->C_Decrypt)(hSession, (CK_BYTE_PTR)encData, (CK_ULONG)encLen, (CK_BYTE_PTR)decData, (CK_ULONG_PTR)&outlen); *decLen = outlen; ddocDebug(3, "decryptWithEstID", "RV: %d, dec-len: %d", (int)rv, *decLen); if(hSession) closePKCS11Library(pLibrary, hSession); if(rv != CKR_OK) SET_LAST_ERROR_RETURN(ERR_DENC_DECRYPT, ERR_DENC_DECRYPT) return err; }
//============================================================ // Calculates and stores a signature for this SignatureInfo object // Uses EstEID card to sign the info // pSigInfo - signature info object // nSigType - signature type code // keyfile - RSA key file // passwd - key password // certfile - certificate file //============================================================ EXP_OPTION int calculateSignatureWithEstID(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int slot, const char* passwd) { int err = ERR_OK, nKey; LIBHANDLE pLibrary = 0; CK_ULONG certLen, sigLen, padDigLen; CK_RV rv; CK_SLOT_ID slotids[20], slId = 0; CK_SESSION_HANDLE hSession = 0; CK_OBJECT_HANDLE hPrivateKey, hKeys[20], hCert; char keyId[20][20]; CK_ULONG keyIdLen[20]; CK_BYTE certData[2048]; CK_BYTE sigDig[100], padDig[130]; CK_BYTE signature[256]; CK_BYTE padding[] = { 48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20 }; CK_BYTE padding256[] = { 48, 49, 48, 13, 6, 9, 96, 134, 72, 1 ,101, 3, 4, 2, 1, 5, 0, 4, 32}; //CK_BYTE padding256[] = { 48, 33, 48, 13, 6, 9, 96, 134, 72, 1 ,101, 3, 4, 2, 1, 5, 0, 4, 32}; char* buf1; int l1, l2; X509* x509; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pSigDoc); // try active driver driver first snprintf((char*)signature, sizeof(signature), "DIGIDOC_DRIVER_%d_FILE", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1)); for(l1 = 0; l1 < 20; l1++) slotids[l1] = INVALID_SLOTIID; // initialize err = loadAndTestDriver(ConfigItem_lookup((const char*)signature), &pLibrary, (CK_SLOT_ID*)slotids, 20, (CK_ULONG)slot); ddocDebug(3, "calculateSignatureWithEstID", "Driver handle: %d err = %d slot: %d", pLibrary, err, slot); RETURN_IF_NOT(err == ERR_OK, err); // inittialize slId = INVALID_SLOTIID; // not found yet //err = ddocLocateSlotWithSignatureCert(pLibrary, slotids, // &slId, (char*)signature, sizeof(signature)); // find suitable slotid for(l1 = 0; l1 < 20; l1++) { if(slotids[l1] != INVALID_SLOTIID) ddocDebug(3, "calculateSignatureWithEstID", "Slot idx: %d = %d", l1, slotids[l1]); if(slotids[l1] != INVALID_SLOTIID && l1 == slot) { slId = slotids[l1]; ddocDebug(3, "calculateSignatureWithEstID", "Select idx: %d slot: %d", l1, slId); } } // open session if(slId != INVALID_SLOTIID) { hSession = OpenSession(slId, passwd); ddocDebug(3, "calculateSignatureWithEstID", "Open sess for slot: %d sess = %uld\n", slId, hSession); if (hSession == CK_INVALID_HANDLE) { err = ERR_PKCS_LOGIN; SET_LAST_ERROR(err); return err; } ddocDebug(3, "calculateSignatureWithEstID", "OpenSession ok, hSession = %d\n", (int)hSession); // get private key for(l1 = 0; l1 < 20; l1++) { memset(keyId[l1], 0, 20); keyIdLen[l1] = 0; } err = LocatePrivateKey(hSession, keyId, keyIdLen, hKeys); //ddocDebug(3, "calculateSignatureWithEstID", "Priv key: %s", keyId); //if (hPrivateKey == CK_INVALID_HANDLE) { err = ERR_PKCS_PK; SET_LAST_ERROR(err); return err; } // get cert memset(certData, 0, sizeof(certData)); certLen = sizeof(certData); hCert = LocateCertificate(hSession, certData, &certLen, keyId, keyIdLen, &nKey); hPrivateKey = hKeys[nKey]; ddocDebug(3, "calculateSignatureWithEstID", "selected priv-key: %ld pos %d id: %s", hPrivateKey, nKey, keyId[nKey]); ddocDebug(3, "calculateSignatureWithEstID", "Cert-len: %ld", certLen); //printf("Cert: %s", certData); if (hCert == (CK_OBJECT_HANDLE)-1) { err = ERR_PKCS_CERT_LOC; SET_LAST_ERROR(err); return err; } // set cert data err = ddocDecodeX509Data(&x509, certData, certLen); if (!x509) { err = ERR_PKCS_CERT_DECODE; } // save cert in file if(ConfigItem_lookup_int("DEBUG_LEVEL", 1) > 3) saveCert(x509, "signer.pem", FILE_FORMAT_PEM); //AM 07.03.08 setSignatureCert for BDOC if(!strcmp(pSigDoc->szFormat, BDOC_XML_1_NAME)) { setSignatureCertBDOC(pSigInfo, x509); }else{ setSignatureCert(pSigInfo, x509); } //AM 12.03.08 //VS 23.02.2010 - not necessary? /*if(!strcmp(pSigDoc->szFormat, BDOC_XML_1_NAME)) { findCAForCertificate(&ppCA, x509); err = bdocSigInfo_addCert(pSigInfo, ppCA, CERTID_TYPE_CA_CERTID); }*/ // FIXME createTimestamp(pSigDoc, (char*)sigDig, sizeof(sigDig)); setString((char**)&(pSigInfo->szTimeStamp), (const char*)sigDig, -1); // Signed properties digest buf1 = createXMLSignedProperties(pSigDoc, pSigInfo, 0); //dumpInFile("sigprop-sign1.txt", buf1); if (!buf1) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err; } mbuf1.pMem = canonicalizeXML((char*)buf1, strlen(buf1)); mbuf1.nLen = strlen((const char*)mbuf1.pMem); ddocDebugWriteFile(4, "sigprop-signed.txt", &mbuf1); l2 = sizeof(sigDig); //AM 24.04.08 if(!strcmp(pSigDoc->szFormat, BDOC_XML_1_NAME)) err = calculateDigest((const byte*)mbuf1.pMem, mbuf1.nLen, BDOC_DIGEST, sigDig, &l2); else err = calculateDigest((const byte*)mbuf1.pMem, mbuf1.nLen, DIGEST_SHA1, sigDig, &l2); free(buf1); ddocMemBuf_free(&mbuf1); if (err != ERR_OK) { SET_LAST_ERROR(err); return err; } ddocSigInfo_SetSigPropDigest(pSigInfo, (const char*)sigDig, l2); ddocSigInfo_SetSigPropRealDigest(pSigInfo, (const char*)sigDig, l2); // create signed info //AM 11.03.08 createXMLSignedInfo for BDOC if(!strcmp(pSigDoc->szFormat, BDOC_XML_1_NAME)) buf1 = createXMLSignedInfoBDoc(pSigDoc, pSigInfo); else buf1 = createXMLSignedInfo(pSigDoc, pSigInfo); if (!buf1) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err ; } // get digest l2 = sizeof(sigDig); /*if(!strcmp(pSigDoc->szFormat, BDOC_XML_1_NAME)) err = calculateDigest((const byte*)buf1, strlen(buf1), BDOC_DIGEST, sigDig, &l2); else*/ err = calculateDigest((const byte*)buf1, strlen(buf1), DIGEST_SHA1, sigDig, &l2); free(buf1); if (err != ERR_OK) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err; } ddocSigInfo_SetSigInfoRealDigest(pSigInfo, (const char*)sigDig, l2); // sign data sigLen = sizeof(signature); memset(signature, 0, sizeof(signature)); // pad PKCS#1 ver 1 /*if(!strcmp(pSigDoc->szFormat, BDOC_XML_1_NAME) && BDOC_DIGEST==DIGEST_SHA256) { padDigLen = 51; memset(padDig, 0, sizeof(padDig)); memcpy(padDig, padding256, 19); memcpy(padDig + 19, sigDig, l2); } else {*/ padDigLen = 35; memset(padDig, 0, sizeof(padDig)); memcpy(padDig, padding, 15); memcpy(padDig + 15, sigDig, l2); //} //rv = RSA_padding_add_PKCS1_type_1(padDig, padDigLen, sigDig, l2); //rv = RSA_padding_check_PKCS1_type_1(sigDig, l2, padDig, padDigLen, padDigLen+1); // checkErrors(); // sign data rv = SignData(hSession, hPrivateKey, signature, &sigLen, padDig, padDigLen); if (rv != CKR_OK) { err = ERR_PKCS_SIGN_DATA; SET_LAST_ERROR(err); return err; } // set signature value ddocSigInfo_SetSignatureValue(pSigInfo, (const char*)signature, (int)sigLen); } // if slotid found if(hSession) closePKCS11Library(pLibrary, hSession); return err; }
int ddocLocateSlotWithSignatureCert(LIBHANDLE pLibrary, CK_SLOT_ID* slotids, CK_SLOT_ID* pSlotId, X509** ppCert, char idData[20], int* pIdLen, int nSlot, int* pIdx) { int err = ERR_PRIVKEY_READ, i, j, nMatch, l3; CK_RV rv; CK_SESSION_HANDLE hSession = 0; CK_OBJECT_HANDLE objects[10]; CK_BYTE buf2[20], buf3[40]; CK_ULONG ulObjectCount = sizeof(objects)/sizeof(CK_OBJECT_HANDLE), ulCount = 0, l1 = 0, l2 = 0; CK_OBJECT_CLASS ObjClass = CKO_CERTIFICATE; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) } }; CK_ATTRIBUTE Template2[] = { { CKA_VALUE, (void*)0, l1 }, { CKA_ID, (void*)0, sizeof(buf2)} }; char buf1[3000]; X509* pCert; RETURN_IF_NULL_PARAM(pLibrary); RETURN_IF_NULL_PARAM(pSlotId); RETURN_IF_NULL_PARAM(slotids); RETURN_IF_NULL_PARAM(idData); RETURN_IF_NULL_PARAM(ppCert); // mark as not found memset(idData, 0, *pIdLen); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Driver handle: %d err = %d", pLibrary, err); // now check every slot for(i = 0, nMatch = 0; (i < 20) && !(*ppCert); i++) { if(slotids[i] != INVALID_SLOTIID) { ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Checking slot nr: %d id: %d", i, slotids[i]); // open session to slot but no login since we just need the cert rv = (*ckFunc->C_OpenSession)(slotids[i], CKF_SERIAL_SESSION,0,0,&hSession); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Login rv: %ld session: %ld", rv, hSession); if(rv == CKR_OK) { ulCount = sizeof(Template1)/sizeof(CK_ATTRIBUTE); rv = (*ckFunc->C_FindObjectsInit)(hSession, Template1, ulCount); if(rv == CKR_OK) { rv = (*ckFunc->C_FindObjects)(hSession, objects, ulObjectCount, &ulObjectCount); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "slot id: %ld, objects: %ld", slotids[i], ulObjectCount); if(rv == CKR_OK && ulObjectCount > 0) { ulCount = sizeof(Template2) / sizeof(CK_ATTRIBUTE); for(j = 0; j < (int)ulObjectCount; j++) { l1 = sizeof(buf1); memset(buf1, 0, l1); l2 = sizeof(buf2); memset(buf2, 0, l2); //Template2[0].pValue = 0; // check length first rv = (*ckFunc->C_GetAttributeValue)(hSession, objects[j], Template2, ulCount); if(rv == CKR_OK && Template2[0].ulValueLen < sizeof(buf1)) { l1 = Template2[0].ulValueLen; // now get cert data Template2[0].pValue = buf1; Template2[1].pValue = buf2; rv = (*ckFunc->C_GetAttributeValue)(hSession, objects[j], Template2, ulCount); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "slot id: %ld, object: %ld cert-len: %ld rv: %ld", slotids[i], j, l1, rv); pCert = 0; err = ddocDecodeX509Data(&pCert, (const byte*)buf1, l1); if(pCert) { if(ddocCertCheckKeyUsage(pCert, KUIDX_NON_REPUDIATION)) { if((!nSlot || nSlot == nMatch) && !(*ppCert)) { l3 = sizeof(buf3); memset(buf3, 0, l3); bin2hex((const byte*)buf2, (int)Template2[1].ulValueLen, (char*)buf3, &l3); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Selecting slot: %d id: %d key-id %s", i, slotids[i], buf3); *pSlotId = slotids[i]; *pIdx = i; // keep this cert for signing if(*ppCert) X509_free(*ppCert); (*ppCert) = pCert; pCert = NULL; // mark as used memcpy(idData, buf2, Template2[1].ulValueLen); *pIdLen = Template2[1].ulValueLen; err = ERR_OK; // found it } else { // useable slot but not a match by slot id ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Useable slot: %d but search: %d", nMatch, nSlot); nMatch++; } } // if non-repu cert } // if pCert if(pCert) X509_free(pCert); pCert = 0; } // if get-attribute ok } // for j < ulObjectCount } // if found any certs } // if find-init ok rv = (*ckFunc->C_FindObjectsFinal)(hSession); } // if login ok rv = (*ckFunc->C_CloseSession)(hSession); } // if slotid } // for i return err; }
int ddocLocateSlotWithSignatureCert(LIBHANDLE pLibrary, CK_SLOT_ID* slotids, CK_SLOT_ID* pSlotId, char* pLabel, CK_ULONG nLabelLen) { int err = ERR_OK, i, j; CK_RV rv; CK_SESSION_HANDLE hSession = 0; CK_OBJECT_HANDLE objects[10]; CK_ULONG ulObjectCount = sizeof(objects)/sizeof(CK_OBJECT_HANDLE), ulCount = 0, l1 = 0; CK_OBJECT_CLASS ObjClass = CKO_CERTIFICATE; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) } }; CK_ATTRIBUTE Template2[] = { { CKA_VALUE, (void*)0, l1 } //, { CKA_ID, (void*)pLabel, nLabelLen } }; char buf1[3000]; X509* pCert; RETURN_IF_NULL_PARAM(pLibrary); RETURN_IF_NULL_PARAM(pSlotId); RETURN_IF_NULL_PARAM(slotids); RETURN_IF_NULL_PARAM(pLabel); // mark as not found *pSlotId = INVALID_SLOTIID; ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Driver handle: %d err = %d", pLibrary, err); // now check every slot for(i = 0; i < 20; i++) { if(slotids[i] != INVALID_SLOTIID) { ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Checking slot nr: %d id: %d", i, slotids[i]); // open session to slot but no login since we just need the cert rv = (*ckFunc->C_OpenSession)(slotids[i], CKF_SERIAL_SESSION,0,0,&hSession); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Login rv: %ld session: %ld", rv, hSession); if(rv == CKR_OK) { ulCount = sizeof(Template1)/sizeof(CK_ATTRIBUTE); rv = (*ckFunc->C_FindObjectsInit)(hSession, Template1, ulCount); if(rv == CKR_OK) { rv = (*ckFunc->C_FindObjects)(hSession, objects, ulObjectCount, &ulObjectCount); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "slot id: %ld, objects: %ld", slotids[i], ulObjectCount); if(rv == CKR_OK && ulObjectCount > 0) { ulCount = sizeof(Template2) / sizeof(CK_ATTRIBUTE); for(j = 0; j < (int)ulObjectCount; j++) { l1 = sizeof(buf1); memset(buf1, 0, l1); //Template2[0].pValue = 0; // check length first rv = (*ckFunc->C_GetAttributeValue)(hSession, objects[j], Template2, ulCount); if(rv == CKR_OK && Template2[0].ulValueLen < sizeof(buf1)) { l1 = Template2[0].ulValueLen; // now get cert data Template2[0].pValue = buf1; rv = (*ckFunc->C_GetAttributeValue)(hSession, objects[j], Template2, ulCount); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "slot id: %ld, object: %ld cert-len: %ld rv: %ld", slotids[i], j, l1, rv); pCert = 0; err = ddocDecodeX509Data(&pCert, (const byte*)buf1, l1); if(pCert) ddocDebug(3, "ddocLocateSlotWithSignatureCert", "flags: %ld kusage: %ld xkusage: %ld ku-dig-sign: %d ku-non-repud: %d ku-ex: %d non-rep-ex: %d", pCert->ex_flags, pCert->ex_kusage, pCert->ex_xkusage, pCert->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE, pCert->ex_kusage & X509v3_KU_NON_REPUDIATION, pCert->ex_xkusage & X509v3_KU_DIGITAL_SIGNATURE, pCert->ex_xkusage & X509v3_KU_NON_REPUDIATION); if(pCert) X509_free(pCert); } } // for j < ulObjectCount } // if found any certs } // if find-init ok rv = (*ckFunc->C_FindObjectsFinal)(hSession); } // if login ok rv = (*ckFunc->C_CloseSession)(hSession); } // if slotid } // for i return err; }
//============================================================ // Calculates and stores a signature for this SignatureInfo object // Uses EstEID card to sign the info // pSigInfo - signature info object // nSigType - signature type code // keyfile - RSA key file // passwd - key password // certfile - certificate file //============================================================ EXP_OPTION int calculateSignatureWithEstID(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int slot, const char* passwd) { int err = ERR_OK, nKey; LIBHANDLE pLibrary = 0; CK_ULONG certLen, sigLen, padDigLen; CK_RV rv; CK_SLOT_ID slotids[20], slId = 0; CK_SESSION_HANDLE hSession = 0; CK_OBJECT_HANDLE hPrivateKey = 0, hKeys[20], hCert; char keyId[20][20], kId[20]; CK_ULONG keyIdLen[20]; CK_BYTE certData[2048]; CK_BYTE sigDig[100], padDig[130]; CK_BYTE signature[256]; CK_BYTE padding[] = { 48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20 }; //CK_BYTE padding256[] = { 48, 49, 48, 13, 6, 9, 96, 134, 72, 1 ,101, 3, 4, 2, 1, 5, 0, 4, 32}; //CK_BYTE padding256[] = { 48, 33, 48, 13, 6, 9, 96, 134, 72, 1 ,101, 3, 4, 2, 1, 5, 0, 4, 32}; char* buf1; int l1, l2, kILen; X509* x509 = 0; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pSigDoc); // try active driver driver first snprintf((char*)signature, sizeof(signature), "DIGIDOC_DRIVER_%d_FILE", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1)); for(l1 = 0; l1 < 20; l1++) slotids[l1] = INVALID_SLOTIID; // initialize err = loadAndTestDriver(ConfigItem_lookup((const char*)signature), &pLibrary, (CK_SLOT_ID*)slotids, 20, (CK_ULONG)slot); ddocDebug(3, "calculateSignatureWithEstID", "Driver handle: %d err = %d slot: %d", pLibrary, err, slot); RETURN_IF_NOT(err == ERR_OK, err); // inittialize slId = INVALID_SLOTIID; // not found yet // try key-usage check if(ConfigItem_lookup_int("KEY_USAGE_CHECK", 1)) { kILen = sizeof(kId); ddocDebug(3, "calculateSignatureWithEstID", "Find slot by key-usage, slot: %d", slot); err = ddocLocateSlotWithSignatureCert(pLibrary, slotids, &slId, &x509, kId, &kILen, slot, &l1); ddocDebug(3, "calculateSignatureWithEstID", "Select by key-usage slot idx: %d = %d err: %d key-id: %s, kid-len: %d", l1, slId, err, kId, kILen); if(err != ERR_OK || l1 < 0 || l1 >= 20) { SET_LAST_ERROR(ERR_SIGNERS_CERT_NON_REPU); return ERR_SIGNERS_CERT_NON_REPU; } } else { ddocDebug(3, "calculateSignatureWithEstID", "Find slot by slot idx: %d", slot); for(l1 = 0; (l1 < 20) && (slId == INVALID_SLOTIID); l1++) { if(slotids[l1] != INVALID_SLOTIID) ddocDebug(3, "calculateSignatureWithEstID", "Slot idx: %d = %d", l1, slotids[l1]); if(slotids[l1] != INVALID_SLOTIID && l1 == slot) { slId = slotids[l1]; ddocDebug(3, "calculateSignatureWithEstID", "Select idx: %d slot: %d", l1, slId); } // if slotid } // for } // use default if not found by key-id or direct if(slId == INVALID_SLOTIID) { l1 = ConfigItem_lookup_int("DIGIDOC_SIGNATURE_SLOT", 0); if(slotids[l1] != INVALID_SLOTIID) { ddocDebug(3, "calculateSignatureWithEstID", "Select default slot idx: %d = %d", l1, slotids[l1]); slId = slotids[l1]; } } // open session if(slId != INVALID_SLOTIID) { hSession = OpenSession(slId, passwd); ddocDebug(3, "calculateSignatureWithEstID", "Open sess for slot: %d sess = %d", slId, hSession); if (hSession == CK_INVALID_HANDLE) { err = ERR_PKCS_LOGIN; SET_LAST_ERROR(err); return err; } ddocDebug(3, "calculateSignatureWithEstID", "OpenSession ok, hSession1 = %d", (int)hSession); if(!x509) { ddocDebug(3, "calculateSignatureWithEstID", "Cert ok"); // get private key for(l1 = 0; l1 < 20; l1++) { memset(keyId[l1], 0, 20); keyIdLen[l1] = 0; } err = LocatePrivateKey(hSession, keyId, keyIdLen, hKeys); //ddocDebug(3, "calculateSignatureWithEstID", "Priv key: %s", keyId); // // get cert memset(certData, 0, sizeof(certData)); certLen = sizeof(certData); hCert = LocateCertificate(hSession, certData, &certLen, keyId, keyIdLen, &nKey); hPrivateKey = hKeys[nKey]; ddocDebug(3, "calculateSignatureWithEstID", "selected priv-key: %ld pos %d id: %s", hPrivateKey, nKey, keyId[nKey]); ddocDebug(3, "calculateSignatureWithEstID", "Cert-len: %ld", certLen); //printf("Cert: %s", certData); if (hCert == (CK_OBJECT_HANDLE)-1) { err = ERR_PKCS_CERT_LOC; SET_LAST_ERROR(err); return err; } // set cert data err = ddocDecodeX509Data(&x509, certData, certLen); } else { // cert already found //kILen = sizeof(kId); ddocDebug(3, "calculateSignatureWithEstID", "Locate priv key2 id: %s, len: %d, hkey: %d", kId, kILen, hPrivateKey); err = LocatePrivateKeyWithId(hSession, (CK_BYTE_PTR)kId, kILen, &hPrivateKey); ddocDebug(3, "calculateSignatureWithEstID", "Priv key-id: %s len: %d hkey: %d err: %d", kId, kILen, hPrivateKey, err); } ddocDebug(3, "calculateSignatureWithEstID", "Priv key: %d err: %d", hPrivateKey, err); if (hPrivateKey == CK_INVALID_HANDLE) { err = ERR_PKCS_PK; SET_LAST_ERROR(err); return err; } if (!x509) { err = ERR_PKCS_CERT_DECODE; } // save cert in file if(ConfigItem_lookup_int("DEBUG_LEVEL", 1) > 3) saveCert(x509, "signer.pem", FILE_FORMAT_PEM); setSignatureCert(pSigInfo, x509); // FIXME createTimestamp(pSigDoc, (char*)sigDig, sizeof(sigDig)); setString((char**)&(pSigInfo->szTimeStamp), (const char*)sigDig, -1); // Signed properties digest buf1 = createXMLSignedProperties(pSigDoc, pSigInfo, 0); //dumpInFile("sigprop-sign1.txt", buf1); if (!buf1) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err; } mbuf1.pMem = canonicalizeXML((char*)buf1, strlen(buf1)); mbuf1.nLen = strlen((const char*)mbuf1.pMem); ddocDebugWriteFile(4, "sigprop-signed.txt", &mbuf1); l2 = sizeof(sigDig); err = calculateDigest((const byte*)mbuf1.pMem, mbuf1.nLen, DIGEST_SHA1, sigDig, &l2); free(buf1); ddocMemBuf_free(&mbuf1); if (err != ERR_OK) { SET_LAST_ERROR(err); return err; } ddocSigInfo_SetSigPropDigest(pSigInfo, (const char*)sigDig, l2); ddocSigInfo_SetSigPropRealDigest(pSigInfo, (const char*)sigDig, l2); // create signed info buf1 = createXMLSignedInfo(pSigDoc, pSigInfo); if (!buf1) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err ; } // get digest l2 = sizeof(sigDig); err = calculateDigest((const byte*)buf1, strlen(buf1), DIGEST_SHA1, sigDig, &l2); free(buf1); if (err != ERR_OK) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err; } ddocSigInfo_SetSigInfoRealDigest(pSigInfo, (const char*)sigDig, l2); // sign data sigLen = sizeof(signature); memset(signature, 0, sizeof(signature)); // pad PKCS#1 ver 1 padDigLen = 35; memset(padDig, 0, sizeof(padDig)); memcpy(padDig, padding, 15); memcpy(padDig + 15, sigDig, l2); //rv = RSA_padding_add_PKCS1_type_1(padDig, padDigLen, sigDig, l2); //rv = RSA_padding_check_PKCS1_type_1(sigDig, l2, padDig, padDigLen, padDigLen+1); // checkErrors(); // sign data rv = SignData(hSession, hPrivateKey, signature, &sigLen, padDig, padDigLen); if (rv != CKR_OK) { err = ERR_PKCS_SIGN_DATA; SET_LAST_ERROR(err); return err; } // set signature value ddocSigInfo_SetSignatureValue(pSigInfo, (const char*)signature, (int)sigLen); ddocDebug(3, "calculateSignatureWithEstID", "Sig-len: %ld", sigLen); } // if slotid found if(hSession) closePKCS11Library(pLibrary, hSession); return err; }
//============================================================ // Locates a certificate on the token on basis of its CKA_LABEL attribute. // hSession - card session handle // label - key label // return objects handle or -1 for failure //============================================================ CK_OBJECT_HANDLE LocateCertificate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR certData, CK_ULONG_PTR certLen, char idData[20][20], CK_ULONG idLen[20], int* pSelKey) { CK_OBJECT_HANDLE Objects[10]; CK_ULONG ulObjectCount = sizeof(Objects)/sizeof(CK_OBJECT_HANDLE), i, j; CK_BYTE buf1[20]; CK_OBJECT_HANDLE hCert = CK_INVALID_HANDLE; CK_RV rv; // Set up a template to search for Certificate token objects // in the given session and thus slot CK_OBJECT_CLASS ObjClass = CKO_CERTIFICATE; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) }, { CKA_ID, (void*)0, 0 } }; CK_ATTRIBUTE Template3[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) }, }; CK_ATTRIBUTE Template2[] = { { CKA_VALUE, (void*)0, *certLen }, { CKA_ID, (void*)0, 0 } }; CK_ULONG ulCount = 0; if(idLen) ulCount = sizeof(Template1)/sizeof(CK_ATTRIBUTE); else ulCount = sizeof(Template3)/sizeof(CK_ATTRIBUTE); *certLen = 0; /* ** Initiate the object search C_FindObjectsInit initializes a search for token and session objects that match a template. hSession is the sessions handle; pTemplate points to a search template that specifies the attribute values to match; ulCount is the number of attributes in the search template. The matching criterion is an exact byte-for-byte match with all attributes in the template. To find all objects, set ulCount to 0. */ for(j = 0; j < 20 && !(*certLen); j++) { if(idLen && idLen[j]) { memset(buf1, 0, sizeof(buf1)); memcpy(buf1, idData[j], idLen[j]); Template1[1].pValue = buf1; Template1[1].ulValueLen = idLen[j]; } rv = (*ckFunc->C_FindObjectsInit)(hSession, (idLen ? Template1 : Template3), 1); //ulCount); if(rv==CKR_OK) { rv = (*ckFunc->C_FindObjects)(hSession,Objects,ulObjectCount, &ulObjectCount); ddocDebug(3, "LocateCertificate", "search key-id: %s, found: %ld rv: %ld", buf1, ulObjectCount, rv); if(rv==CKR_OK) { // pick the first cert that is valid // list and ignore any other for(i = 0; i < ulObjectCount; i++) { hCert = Objects[i]; memset(certData, 0, *certLen); ulCount = sizeof(Template2) / sizeof(CK_ATTRIBUTE); // get cert length *certLen = 0; Template2[1].pValue = buf1; Template2[1].ulValueLen = sizeof(buf1); rv = (*ckFunc->C_GetAttributeValue)(hSession, hCert, Template2, ulCount); ddocDebug(3, "LocateCertificate", "cert-id: %s", buf1); if(rv == CKR_OK && (!idLen || (idLen && !memcmp(idData[j], buf1, idLen[1])))) { *certLen = Template2[0].ulValueLen; // now get cert data Template2[0].pValue = certData; rv = (*ckFunc->C_GetAttributeValue)(hSession, hCert, Template2, ulCount); ddocDebug(3, "LocateCertificate", "cert-len: %ld", *certLen); if(*certLen > 0 && pSelKey) { *pSelKey = j; break; // found it } } // if rv == CKR_OK } // for i < ulObjectCount } // if rv } // if rv rv = (*ckFunc->C_FindObjectsFinal)(hSession); } // for j if(hCert == CK_INVALID_HANDLE) *certLen = 0; return hCert; }
//============================================================ // Initializes NotaryInfo object with data from OCSP object // pSigDoc - digidoc main object pointer // pNotary - NotaryInfo object to be initialized // resp - OCSP response object // notCert - Notary cert object // return error code //============================================================ int initializeNotaryInfoWithOCSP(SignedDoc *pSigDoc, NotaryInfo *pNotary, OCSP_RESPONSE *resp, X509 *notCert, int initDigest) { int n, err = ERR_OK; char buf[500]; OCSP_RESPBYTES *rb = NULL; OCSP_BASICRESP *br = NULL; OCSP_RESPDATA *rd = NULL; OCSP_RESPID *rid = NULL; // OCSP_CERTSTATUS *cst = NULL; OCSP_SINGLERESP *single = NULL; OCSP_CERTID *cid = NULL; X509_EXTENSION *nonce; //AM 26.09.08 DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(resp); // check the OCSP Response validity switch(OCSP_response_status(resp)) { case OCSP_RESPONSE_STATUS_SUCCESSFUL: // OK break; case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_MALFORMED); case OCSP_RESPONSE_STATUS_INTERNALERROR: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_INTERNALERR); case OCSP_RESPONSE_STATUS_TRYLATER: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_TRYLATER); case OCSP_RESPONSE_STATUS_SIGREQUIRED: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_SIGREQUIRED); case OCSP_RESPONSE_STATUS_UNAUTHORIZED: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_UNAUTHORIZED); default: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_UNSUCCESSFUL); } RETURN_IF_NULL_PARAM(resp->responseBytes);; rb = resp->responseBytes; if(OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_UNKNOWN_TYPE); if((br = OCSP_response_get1_basic(resp)) == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_BASIC_RESP); rd = br->tbsResponseData; if(ASN1_INTEGER_get(rd->version) != 0) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_WRONG_VERSION); n = sk_OCSP_SINGLERESP_num(rd->responses); if(n != 1) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_ONE_RESPONSE); single = sk_OCSP_SINGLERESP_value(rd->responses, 0); RETURN_IF_NULL(single); cid = single->certId; RETURN_IF_NULL(cid); ddocDebug(4, "initializeNotaryInfoWithOCSP", "CertStatus-type: %d", single->certStatus->type); //printf("TYPE: %d\n", single->certStatus->type); if(single->certStatus->type != 0) { ddocDebug(4, "initializeNotaryInfoWithOCSP", "errcode: %d", handleOCSPCertStatus(single->certStatus->type)); SET_LAST_ERROR_RETURN_CODE(handleOCSPCertStatus(single->certStatus->type)); } //Removed 31.10.2003 //if(single->singleExtensions) // SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_SINGLE_EXT); if(!rd->responseExtensions || (sk_X509_EXTENSION_num(rd->responseExtensions) != 1) || ((nonce = sk_X509_EXTENSION_value(rd->responseExtensions, 0)) == NULL)) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); i2t_ASN1_OBJECT(buf,sizeof(buf),nonce->object); if(strcmp(buf, OCSP_NONCE_NAME)) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); rid = rd->responderId; if(rid->type == V_OCSP_RESPID_NAME) { pNotary->nRespIdType = RESPID_NAME_TYPE; } else if(rid->type == V_OCSP_RESPID_KEY) { pNotary->nRespIdType = RESPID_KEY_TYPE; } else { SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_WRONG_RESPID); } // producedAt err = asn1time2str(pSigDoc, rd->producedAt, buf, sizeof(buf)); setString(&(pNotary->timeProduced), buf, -1); n = sizeof(buf); if(rid->type == V_OCSP_RESPID_NAME) { //X509_NAME_oneline(rid->value.byName,buf,n); //AM 26.09.08 err = ddocCertGetDNFromName(rid->value.byName, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); err = ddocNotInfo_SetResponderId(pNotary, (char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); } if(rid->type == V_OCSP_RESPID_KEY) { err = ddocNotInfo_SetResponderId(pNotary, (const char*)rid->value.byKey->data, rid->value.byKey->length); } // digest type i2t_ASN1_OBJECT(buf,sizeof(buf),cid->hashAlgorithm->algorithm); setString(&(pNotary->szDigestType), buf, -1); // signature algorithm i2t_ASN1_OBJECT(buf,sizeof(buf),br->signatureAlgorithm->algorithm); setString(&(pNotary->szSigType), buf, -1); // notary cert if(notCert && !err) err = addNotaryInfoCert(pSigDoc, pNotary, notCert); // save the response in memory err = ddocNotInfo_SetOCSPResponse_Value(pNotary, resp); // get the digest from original OCSP data if(initDigest && notCert) { err = calcNotaryDigest(pSigDoc, pNotary); } if(br != NULL) OCSP_BASICRESP_free(br); if (err != ERR_OK) SET_LAST_ERROR(err); return err; }
//-------------------------------------------------- // Writes encrypted data to a file // pEncData - encrypted data object [REQUIRED] // szFileName - name of the file to write the data [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencGenEncryptedData_writeToFile(DEncEncryptedData* pEncData, const char* szFileName) { int err = ERR_OK; DigiDocMemBuf mbufEncData; FILE* hFile; #ifdef WIN32 wchar_t *convFileName = 0; int i= 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "ddocGenEncryptedData_writeToFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i); #else char convFileName[1024]; ddocConvertFileName( convFileName, sizeof(convFileName), szFileName ); #endif ddocDebug(3, "dencGenEncryptedData_writeToFile", "filename: %s", szFileName); RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(szFileName) // start of element mbufEncData.pMem = 0; mbufEncData.nLen = 0; err = dencGenEncryptedData_toXML(pEncData, &mbufEncData); #ifdef WIN32 if(!err && (hFile = _wfopen(convFileName, L"wb")) != NULL) { #else if(!err && (hFile = fopen(convFileName, "wb")) != NULL) { #endif fwrite(mbufEncData.pMem, mbufEncData.nLen, 1, hFile); fclose(hFile); } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); ddocDebug(1, "dencGenEncryptedData_writeToFile", "Error writing encrypted document"); } // cleanup ddocMemBuf_free(&mbufEncData); return err; } //-------------------------------------------------- // Generates the header of XML for <EncryptedData> element // This contains everything upto the start of base64 encoded cipher data // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedData_header_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf) { int err = ERR_OK; char* p; int i, n; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncData) // xml header err = ddocMemAppendData(pBuf, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>", -1); if(err) return err; // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptedData"); if(err) return err; // xmlns:denc //p = dencEncryptedData_GetXmlNs(pEncData); //if(p) err = ddocGen_addAtribute(pBuf, "xmlns:denc", DENC_XMLNS_XMLENC); if(err) return err; // Id atribute p = (char*)dencEncryptedData_GetId(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // Type atribute p = (char*)dencEncryptedData_GetType(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "Type", p); if(err) return err; // MimeType atribute p = (char*)dencEncryptedData_GetMimeType(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "MimeType", p); if(err) return err; // Encoding ??? // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // <EncryptionMethod> p = (char*)dencEncryptedData_GetEncryptionMethod(pEncData); if(p) { err = ddocGen_startElemBegin(pBuf, "denc:EncryptionMethod"); if(err) return err; err = ddocGen_addAtribute(pBuf, "Algorithm", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocGen_endElem(pBuf, "denc:EncryptionMethod"); if(err) return err; } n = dencEncryptedData_GetEncryptedKeyCount(pEncData); if(n > 0) { // <KeyInfo> err = ddocGen_startElemBegin(pBuf, "ds:KeyInfo"); if(err) return err; // xmlns ??? err = ddocGen_addAtribute(pBuf, "xmlns:ds", DENC_XMLNS_XMLDSIG); if(err) return err; err = ddocGen_startElemEnd(pBuf); if(err) return err; // <EncryptedKey> for(i = 0; i < n; i++) { DEncEncryptedKey* pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i); if(pEncKey) { err = dencGenEncryptedKey_toXML(pEncKey, pBuf); if(err) return err; } } // end of element <KeyInfo> err = ddocGen_endElem(pBuf, "ds:KeyInfo"); if(err) return err; } // encrypted data err = ddocGen_startElem(pBuf, "denc:CipherData"); if(err) return err; err = ddocGen_startElem(pBuf, "denc:CipherValue"); // here would come the base64 encoded cipher data return err; }
//-------------------------------------------------- // Calculates file size // szFileName - file name // lFileLen - pointer to a buffer where to store the file length // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int calculateFileSize(const char* szFileName, long* lFileLen) { FILE* hFile = 0; #ifdef WIN32 int i = 0, err = ERR_OK; wchar_t *convFileName = 0; #endif RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(lFileLen); if(!szFileName || !strlen(szFileName)) return 0; #ifdef WIN32 err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "calculateFileSize", "Opening FILE: %s, conv-file: %s len: %d", szFileName, convFileName, i); if((hFile = _wfopen(convFileName,L"rb")) != NULL) { #else if((hFile = fopen(szFileName,"rb")) != NULL) { #endif fseek(hFile, 0, SEEK_END); (*lFileLen) = ftell(hFile); ddocDebug(3, "calculateFileSize", "Closing FILE: %s, size: %ld", szFileName, (*lFileLen)); fclose(hFile); } // if - fopen else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); #ifdef WIN32 if(convFileName) free(convFileName); #endif return ERR_OK; } //-------------------------------------------------- // Calculates files SHA1-RSA signature // szFileName - file name // nDigestType - digest type. Supports only SHA1 (0) // pSigBuf - buffer to store the signature // nSigLen - buffer size, must be at least 128 // will be updated by actual signature length // keyfile - name of the private key file // passwd - private key password // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int calculateFileSignature(const char* szFileName, int nDigestType, byte* pSigBuf, int* nSigLen, const char *keyfile, const char* passwd) { int err = ERR_OK; EVP_MD_CTX ctx; byte buf[FILE_BUFSIZE]; int i; FILE *f = NULL; EVP_PKEY* pkey = NULL; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(pSigBuf); RETURN_IF_NULL_PARAM(nSigLen); RETURN_IF_NULL_PARAM(keyfile); RETURN_IF_NULL_PARAM(passwd); memset(pSigBuf, 0, *nSigLen); if(nDigestType == DIGEST_SHA1) { if(*nSigLen >= SIGNATURE_LEN) { if((err = ReadPrivateKey(&pkey, keyfile, passwd, FILE_FORMAT_PEM)) == ERR_OK) { if((f = fopen(szFileName,"rb")) != NULL) { EVP_SignInit(&ctx, EVP_sha1()); for (;;) { i = fread(buf, sizeof(char), FILE_BUFSIZE, f); if (i <= 0) break; EVP_SignUpdate (&ctx, buf, (unsigned long)i); } err = EVP_SignFinal(&ctx, pSigBuf, (unsigned int*)nSigLen, pkey); if(err == ERR_LIB_NONE) err = ERR_OK; fclose(f); EVP_PKEY_free(pkey); } // if - fopen else err = ERR_FILE_READ; } else err = ERR_PRIVKEY_READ; } else err = ERR_SIGNATURE_LEN; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); return err; }
//-------------------------------------------------- // sends an OCSP_REQUES object to remore server and // retrieves the OCSP_RESPONSE object // resp - buffer to store the new responses pointer // req - request objects pointer // url - OCSP responder URL //-------------------------------------------------- int ddocPullUrl(const char* url, DigiDocMemBuf* pSendData, DigiDocMemBuf* pRecvData, const char* proxyHost, const char* proxyPort) { BIO* cbio = 0, *sbio = 0; SSL_CTX *ctx = NULL; char *host = NULL, *port = NULL, *path = "/", buf[200]; int err = ERR_OK, use_ssl = -1, rc; long e; //RETURN_IF_NULL_PARAM(pSendData); // may be null if nothing to send? RETURN_IF_NULL_PARAM(pRecvData); RETURN_IF_NULL_PARAM(url); ddocDebug(4, "ddocPullUrl", "URL: %s, in: %d bytes", url, pSendData->nLen); //there is an HTTP proxy - connect to that instead of the target host if (proxyHost != 0 && *proxyHost != '\0') { host = (char*)proxyHost; if(proxyPort != 0 && *proxyPort != '\0') port = (char*)proxyPort; path = (char*)url; } else { if(OCSP_parse_url((char*)url, &host, &port, &path, &use_ssl) == 0) { ddocDebug(1, "ddocPullUrl", "Failed to parse the URL"); return ERR_WRONG_URL_OR_PROXY; } } if((cbio = BIO_new_connect(host)) != 0) { ddocDebug(4, "ddocPullUrl", "Host: %s port: %s", host, port); if(port != NULL) { BIO_set_conn_port(cbio, port); } if(use_ssl == 1) { ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); sbio = BIO_new_ssl(ctx, 1); cbio = BIO_push(sbio, cbio); } if ((rc = BIO_do_connect(cbio)) > 0) { ddocDebug(4, "ddocPullUrl", "Connected: %d", rc); if(pSendData && pSendData->nLen && pSendData->pMem) { rc = BIO_write(cbio, pSendData->pMem, pSendData->nLen); ddocDebug(4, "ddocPullUrl", "Sent: %d bytes, got: %d", pSendData->nLen, rc); } do { memset(buf, 0, sizeof(buf)); rc = BIO_read(cbio, buf, sizeof(buf)-1); ddocDebug(4, "ddocPullUrl", "Received: %d bytes\n", rc); if(rc > 0) err = ddocMemAppendData(pRecvData, buf, rc); } while(rc > 0); ddocDebug(4, "ddocPullUrl", "Total received: %d bytes\n", pRecvData->nLen); } else { //if no connection e = checkErrors(); if(ERR_GET_REASON(e) == BIO_R_BAD_HOSTNAME_LOOKUP || ERR_GET_REASON(e) == OCSP_R_SERVER_WRITE_ERROR) err = ERR_CONNECTION_FAILURE; else err = (host != NULL) ? ERR_WRONG_URL_OR_PROXY : ERR_CONNECTION_FAILURE; } BIO_free_all(cbio); if (use_ssl != -1) { OPENSSL_free(host); OPENSSL_free(port); OPENSSL_free(path); SSL_CTX_free(ctx); } } else err = ERR_CONNECTION_FAILURE; return(err); }