//-------------------------------------------------- // Helper function to assign zero terminated strings // and release old content if necessary // dest - destination address // src - new data to be assigned //-------------------------------------------------- EXP_OPTION int ddocMemAssignString(char** dest, const char* src) { RETURN_IF_NULL_PARAM(dest); RETURN_IF_NULL_PARAM(src); if(*dest) free(*dest); *dest = (char*)strdup(src); if(!dest) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) else return ERR_OK; }
//-------------------------------------------------- // Helper function to set buffer length as required // It will fill acquired mem with zeros. // pBuf - address of memory buffer pointer // len - new length of buffer //-------------------------------------------------- EXP_OPTION int ddocMemSetLength(DigiDocMemBuf* pBuf, long len) { long addLen = len; RETURN_IF_NULL_PARAM(pBuf); addLen = len - pBuf->nLen; // ddocDebug(7, "ddocMemSetLength", "Len: %ld", addLen); pBuf->pMem = realloc(pBuf->pMem, pBuf->nLen + addLen + 1); if(!pBuf->pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC); memset((char*)pBuf->pMem + pBuf->nLen, 0, addLen+1); pBuf->nLen += addLen; // ddocDebug(8, "ddocMemSetLength", "BUFFER Len: %ld data:\'%s\'", pBuf->nLen, pBuf->pMem); return ERR_OK; }
//-------------------------------------------------- // Helper function to append data to a memory buffer // and grow it as required. // pBuf - address of memory buffer pointer // data - new data to be appended // len - length of data or -1 for zero terminated strings //-------------------------------------------------- EXP_OPTION int ddocMemAppendData(DigiDocMemBuf* pBuf, const char* data, long len) { long addLen = len; RETURN_IF_NULL_PARAM(pBuf); RETURN_IF_NULL_PARAM(data); if(addLen == -1) addLen = strlen(data); // ddocDebug(7, "ddocAppendData", "Len: %ld data: \'%s\'", addLen, data); pBuf->pMem = realloc(pBuf->pMem, pBuf->nLen + addLen + 1); if(!pBuf->pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC); memset((char*)pBuf->pMem + pBuf->nLen, 0, addLen+1); memcpy((char*)pBuf->pMem + pBuf->nLen, data, addLen); pBuf->nLen += addLen; // ddocDebug(8, "ddocAppendData", "BUFFER Len: %ld data:\'%s\'", pBuf->nLen, pBuf->pMem); return ERR_OK; }
//============================================================ // 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; }
//-------------------------------------------------- // Generates XML for <EncryptedData> element // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedData_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf) { int err = ERR_OK, l1; 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 if(pEncData->mbufEncryptedData.pMem && pEncData->mbufEncryptedData.nLen) { l1 = 2 * pEncData->mbufEncryptedData.nLen; p = (char*)malloc(l1); if(!p) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(p, 0, l1); encode((const byte*)pEncData->mbufEncryptedData.pMem, pEncData->mbufEncryptedData.nLen, (byte*)p, &l1); ddocDebug(4, "dencGenEncryptedData_toXML", "Input data: %d base64: %d", pEncData->mbufEncryptedData.nLen, l1); if(p && l1) { err = ddocGen_startElem(pBuf, "denc:CipherData"); if(err) return err; err = ddocGen_startElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocMemAppendData(pBuf, p, -1); free(p); p = 0; if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherData"); if(err) return err; } } // <EncryptionProperties> if(dencEncryptedData_GetEncryptionPropertiesCount(pEncData) > 0) err = dencGenEncryptionProperties_toXML(pEncData, pBuf); if(err) return err; // end of element <EncryptedData> err = ddocGen_endElem(pBuf, "denc:EncryptedData"); return err; }
//-------------------------------------------------- // Generates XML for <EncryptedKey> element // pEncKey - encrypted key object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedKey_toXML(DEncEncryptedKey* pEncKey, DigiDocMemBuf* pBuf) { int err = ERR_OK, l1; char* p; X509* pCert; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncKey) // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptedKey"); if(err) return err; // Id atribute p = (char*)dencEncryptedKey_GetId(pEncKey); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // Recipient atribute p = (char*)dencEncryptedKey_GetRecipient(pEncKey); if(p) err = ddocGen_addAtribute(pBuf, "Recipient", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // <EncryptionMethod> p = (char*)dencEncryptedKey_GetEncryptionMethod(pEncKey); if(p) { err = ddocGen_startElemBegin(pBuf, "denc:EncryptionMethod"); if(err) return err; err = ddocGen_addAtribute(pBuf, "Algorithm", p); if(err) return err; err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocGen_endElem(pBuf, "denc:EncryptionMethod"); if(err) return err; } // <KeyInfo> err = ddocGen_startElem(pBuf, "ds:KeyInfo"); if(err) return err; // <KeyName> p = (char*)dencEncryptedKey_GetKeyName(pEncKey); if(p) { err = ddocGen_startElem(pBuf, "ds:KeyName"); if(err) return err; err = ddocMemAppendData(pBuf, p, -1); if(err) return err; err = ddocGen_endElem(pBuf, "ds:KeyName"); if(err) return err; } // <X509Data>/<X509Certificate> pCert = dencEncryptedKey_GetCertificate(pEncKey); if(pCert) { err = ddocGen_startElem(pBuf, "ds:X509Data"); if(err) return err; err = ddocGen_startElem(pBuf, "ds:X509Certificate"); if(err) return err; p = 0; err = getCertPEM(pCert, 0, &p); if(err) { if(p) free(p); return err; } if(p) { err = ddocMemAppendData(pBuf, p, -1); free(p); p = 0; if(err) return err; } err = ddocGen_endElem(pBuf, "ds:X509Certificate"); if(err) return err; err = ddocGen_endElem(pBuf, "ds:X509Data"); if(err) return err; } // end of element <KeyInfo> err = ddocGen_endElem(pBuf, "ds:KeyInfo"); if(err) return err; // transport key if(pEncKey->mbufTransportKey.pMem && pEncKey->mbufTransportKey.nLen) { l1 = 2 * pEncKey->mbufTransportKey.nLen; p = (char*)malloc(l1); if(!p) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(p, 0, l1); encode((const byte*)pEncKey->mbufTransportKey.pMem, pEncKey->mbufTransportKey.nLen, (byte*)p, &l1); if(p && l1) { err = ddocGen_startElem(pBuf, "denc:CipherData"); if(err) return err; err = ddocGen_startElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocMemAppendData(pBuf, p, -1); free(p); p = 0; if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherData"); if(err) return err; } } // <CarriedKeyName> p = (char*)dencEncryptedKey_GetCarriedKeyName(pEncKey); if(p) { err = ddocGen_startElem(pBuf, "denc:CarriedKeyName"); if(err) return err; err = ddocMemAppendData(pBuf, p, -1); if(err) return err; err = ddocGen_endElem(pBuf, "denc:CarriedKeyName"); if(err) return err; } // end of element <EncryptedKey> err = ddocGen_endElem(pBuf, "denc:EncryptedKey"); return err; }