//-------------------------------------------------- // Helper function to assign data to a memory buffer // and release old content if necessary // 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 ddocMemAssignData(DigiDocMemBuf* pBuf, const char* data, long len) { RETURN_IF_NULL_PARAM(pBuf); RETURN_IF_NULL_PARAM(data); // ddocDebug(7, "ddocAssignData", "Len: %d data: \'%s\'", len, data); if(pBuf->pMem) free(pBuf->pMem); pBuf->pMem = 0; pBuf->nLen = 0; return ddocMemAppendData(pBuf, data, len); }
//-------------------------------------------------- // Helper function to return OCSP_RESPONSE in base64 form // Memory buffer will be resized as necessary. // Caller must release output buffer. // pNotary - Notary object // bHeaders - 1= with headers, 0=no headers // pMBufOutData - output data // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocGetOcspBase64(NotaryInfo *pNotary, int bHeaders, DigiDocMemBuf* pMBufOutData) { const DigiDocMemBuf *pMBuf = 0; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pMBufOutData); pMBufOutData->pMem = 0; pMBufOutData->nLen = 0; mbuf1.pMem = 0; mbuf1.nLen = 0; pMBuf = ddocNotInfo_GetOCSPResponse(pNotary); RETURN_IF_NULL(pMBuf); if(bHeaders) { ddocMemAppendData(pMBufOutData, "-----BEGIN OCSP RESPONSE-----\n", -1); ddocEncodeBase64(pMBuf, &mbuf1); ddocMemAppendData(pMBufOutData, (const char*)mbuf1.pMem, mbuf1.nLen); ddocMemAppendData(pMBufOutData, "\n-----END OCSP RESPONSE-----", -1); ddocMemBuf_free(&mbuf1); } else ddocEncodeBase64(pMBuf, pMBufOutData); return ERR_OK; }
//-------------------------------------------------- // Replaces a substring with another substring // pBuf1 - memory buffer to search in // pBuf2 - memory buffer to write converted value to // search - search value // replacement - replacement value //-------------------------------------------------- EXP_OPTION int ddocMemReplaceSubstr(DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2, const char* search, const char* replacement) { int err = ERR_OK, i, n; RETURN_IF_NULL_PARAM(pBuf1); RETURN_IF_NULL_PARAM(pBuf1->pMem); RETURN_IF_NULL_PARAM(pBuf2); RETURN_IF_NULL_PARAM(search); RETURN_IF_NULL_PARAM(replacement); //ddocDebug(7, "ddocMemReplaceSubstr", "Replace: \'%s\' with: \'%s\' in: \'%s\'", // search, replacement, (const char*)pBuf1->pMem); ddocMemBuf_free(pBuf2); n = strlen(search); for(i = 0; !err && (i < pBuf1->nLen); i++) { if(!strncmp((char*)pBuf1->pMem + i, search, n)) { // match err = ddocMemAppendData(pBuf2, replacement, -1); i += strlen(search) - 1; } else { // no match err = ddocMemAppendData(pBuf2, (char*)pBuf1->pMem + i, 1); } } return err; }
//-------------------------------------------------- // Generates XML for <EncryptionProperty> element // pEncProperty - encryption property object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptionProperty_toXML(DEncEncryptionProperty* pEncProperty, DigiDocMemBuf* pBuf) { int err = ERR_OK; char* p = 0, *p1 = 0; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncProperty) // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptionProperty"); if(err) return err; // Id atribute p = (char*)dencEncryptionProperty_GetId(pEncProperty); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // Target atribute p = (char*)dencEncryptionProperty_GetTarget(pEncProperty); if(p) err = ddocGen_addAtribute(pBuf, "Target", p); if(err) return err; // Name atribute p = (char*)dencEncryptionProperty_GetName(pEncProperty); if(p) err = ddocGen_addAtribute(pBuf, "Name", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // content p = (char*)dencEncryptionProperty_GetContent(pEncProperty); if(p) { escapeXMLSymbols(p, -1, &p1); err = ddocMemAppendData(pBuf, p1, -1); free(p1); } if(err) return err; err = ddocGen_endElem(pBuf, "denc:EncryptionProperty"); 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); }
//-------------------------------------------------- // 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; }
//-------------------------------------------------- // 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; }