// get signers id-code EXP_OPTION int getSignerCode(const SignatureInfo* pSigInfo, char* buf) { int err, l1; X509* cert; char buf1[500], *p; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(buf); cert = getSignCertData(pSigInfo); if (!cert) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); l1 = sizeof(buf1); err = getCertSubjectName(cert, buf1, &l1); if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err); err = ERR_CERT_READ; p = strstr(buf1, "CN="); if (p) { p = strchr(p, ','); if(p) { p = strchr(p+1, ','); if(p) { strncpy(buf, p+1, 11); buf[11] = 0; err = ERR_OK; } } else { // no comma -> no id-code ! buf[0] = 0; // is this really an error ? err = ERR_WRONG_CERT; } } if (err != ERR_OK) SET_LAST_ERROR(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; }
EXP_OPTION int getSignerCN(const SignatureInfo* pSigInfo, char* buf, int bUTF8) { int err = ERR_OK, l1; X509* cert; char buf1[500], *p, *p2, buf2[500]; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(buf); cert = getSignCertData(pSigInfo); if (!cert) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); l1 = sizeof(buf1); err = getCertSubjectName(cert, buf1, &l1); if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err); if(!bUTF8) { l1 = sizeof(buf2); utf82ascii(buf1, buf2, &l1); strncpy(buf1, buf2, sizeof(buf1)); } err = ERR_CERT_READ; p = strstr(buf1, "CN="); if (p) { p += 3; p2 = strchr(p, '/'); if(!p2) p2 = p + strlen(p); if (p2) { strncpy(buf, p, p2-p); buf[p2-p] = 0; err = ERR_OK; } } if (err != ERR_OK) SET_LAST_ERROR(err); return err; }
//============================================================ // 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; }
// get signers first name EXP_OPTION int getSignerFirstName(const SignatureInfo* pSigInfo, char* buf) { int err = ERR_OK, l1; X509* cert; char buf1[500], *p, *p2, *p1; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(buf); cert = getSignCertData(pSigInfo); if (!cert) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); l1 = sizeof(buf1); err = getCertSubjectName(cert, buf1, &l1); if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err); p = strstr(buf1, "CN="); if (p) { p1 = strchr(p, ','); if(!p1) p1 = strchr(p, '/'); if (p1) { p1 += 1; p2 = strchr(p1, ','); if(!p2) p2 = strchr(p1, '/'); if(p2) { strncpy(buf, p1, p2-p1); buf[p2-p1] = 0; err = ERR_OK; } } } if (err != ERR_OK) SET_LAST_ERROR(err); return err; }
//-------------------------------------------------- // Calculates files SHA1 digest // szFileName - file name // nDigestType - digest type. Supports only SHA1 (0) // pDigestBuf - buffer to store the digest // nDigestLen - buffer size, must be at least 20 // will be updated by actual digest length // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int calculateDigest(const byte* data, int nDataLen, int nDigestType, byte* pDigestBuf, int* nDigestLen) { int err = ERR_OK; RETURN_IF_NULL_PARAM(data); RETURN_IF_NULL_PARAM(pDigestBuf); RETURN_IF_NULL_PARAM(nDigestLen); memset(pDigestBuf, 0, *nDigestLen); if(nDigestType == DIGEST_SHA1) { if(*nDigestLen >= SHA_DIGEST_LENGTH) { *nDigestLen = SHA_DIGEST_LENGTH; SHA1(data, nDataLen, pDigestBuf); } }//AM 22.04.08 else if(nDigestType == DIGEST_SHA256) { if(*nDigestLen >= SHA256_DIGEST_LENGTH) { *nDigestLen = SHA256_DIGEST_LENGTH; SHA256(data, nDataLen, pDigestBuf); } else err = ERR_DIGEST_LEN; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); return err; }
//-------------------------------------------------- // Generates XML for <EncryptionProperties> element // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptionProperties_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf) { int err = ERR_OK; char* p; int n, i; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncData) // count the prperties - do nothing if none exist n = dencEncryptedData_GetEncryptionPropertiesCount(pEncData); if(!n) return err; // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptionProperties"); if(err) return err; // Id atribute p = (char*)dencEncryptedData_GetEncryptionPropertiesId(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // content for(i = 0; i < n; i++) { DEncEncryptionProperty* pEncProp = dencEncryptedData_GetEncryptionProperty(pEncData, i); if(pEncProp) err = dencGenEncryptionProperty_toXML(pEncProp, pBuf); if(err) return err; } // end of element err = ddocGen_endElem(pBuf, "denc:EncryptionProperties"); return err; }
//============================================================ // Converts OCSP_RESPONSE to PEM form with or without the headers // pResp - OCSP_RESPONSE // bHeaders - 1= with headers, 0=no headers // buf - output buffer newly allocated // returns error code //============================================================ EXP_OPTION int getOcspPEM(OCSP_RESPONSE* pResp, int bHeaders, char** buf) { int l1, l2; char *p1, *p2; RETURN_IF_NULL_PARAM(buf); RETURN_IF_NULL_PARAM(pResp); l1 = i2d_OCSP_RESPONSE(pResp, NULL); p1 = (char*)malloc(l1+10); RETURN_IF_BAD_ALLOC(p1); p2 = p1; i2d_OCSP_RESPONSE(pResp, (unsigned char**)&p2); l2 = l1 * 2 + 200; *buf = (char*)malloc(l2); if(*buf == NULL) { free(p1); RETURN_IF_BAD_ALLOC(*buf); } memset(*buf, 0, l2); if(bHeaders) strncpy(*buf, "-----BEGIN OCSP RESPONSE-----\n", l2); encode((const byte*)p1, l1, (byte*)strchr(*buf, 0), &l2); if(bHeaders) strncat(*buf, "\n-----END OCSP RESPONSE-----", l2 - strlen(*buf)); free(p1); return ERR_OK; }
//-------------------------------------------------- // 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; }
//-------------------------------------------------- // 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); }
//============================================================ // Sets the signatures certificate and calculates // certificate digest & serial number // pSigInfo - signature info object // cert - certficate //============================================================ EXP_OPTION int setSignatureCert(SignatureInfo* pSigInfo, X509* cert) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(cert); err = ddocSigInfo_addCert(pSigInfo, cert, CERTID_TYPE_SIGNERS_CERTID); // release old content if it exists ddocMemBuf_free(&(pSigInfo->mbufOrigContent)); return ERR_OK; }
//============================================================ // Sets the signatures certificate and calculates // certificate digest & serial number // pSigInfo - signature info object // certFile - certficate file in PEM //============================================================ EXP_OPTION int setSignatureCertFile(SignatureInfo* pSigInfo, const char* certFile) { X509 *cert = NULL; int err = ERR_OK; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(certFile); err = ReadCertificate(&cert, certFile); RETURN_IF_NOT(err == ERR_OK, err); return setSignatureCert(pSigInfo, cert);; }
//-------------------------------------------------- // 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 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; }
//============================================================ // Calculates NotaryInfo digest if possible // pSigDoc - digidoc main object pointer // pNotary - NotaryInfo object to be initialized // return error code //============================================================ int calcNotaryDigest(SignedDoc* pSigDoc, NotaryInfo* pNotary) { int err = ERR_OK, l1; char buf1[25]; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pSigDoc); l1 = sizeof(buf1); err = calculateNotaryInfoDigest(pSigDoc, pNotary, (byte*)buf1, &l1); //err = calculateOcspBasicResponseDigest(br, buf1, &l1); if(!err) { err = ddocNotInfo_SetOcspDigest(pNotary, buf1, l1); } 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; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(lFileLen); if((hFile = fopen(szFileName,"rb")) != NULL) { fseek(hFile, 0, SEEK_END); *lFileLen = ftell(hFile); fclose(hFile); } // if - fopen else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); 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; }
//-------------------------------------------------- // Compares memory buffers // pBuf1 - memory buffer to value 1 // pBuf2 - memory buffer to value 2 // return 0 if both buffers are equal, 1 if not equal //-------------------------------------------------- EXP_OPTION int ddocMemCompareMemBufs(DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2) { int err = ERR_OK, i; RETURN_IF_NULL_PARAM(pBuf1); RETURN_IF_NULL_PARAM(pBuf1->pMem); RETURN_IF_NULL_PARAM(pBuf2); RETURN_IF_NULL_PARAM(pBuf2->pMem); if(pBuf1->nLen != pBuf2->nLen) return 1; for(i = 0; (i < pBuf1->nLen); i++) { if(((char*)pBuf1->pMem)[i] != ((char*)pBuf2->pMem)[i]) return 1; } return 0; }
//============================================================ // Get the path part of full file name //============================================================ EXP_OPTION int getFileNamePath(const char* szFileName, char* szPath, int len) { int nFound = 0, i, err = ERR_OK; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(szPath); strncpy(szPath, szFileName, len); for(i = strlen(szPath); i >= 0; i--) { if(szPath[i] == '\\') { szPath[i+1] = 0; nFound = 1; break; } } if(!nFound) szPath[0] = 0; return err; }
//-------------------------------------------------- // Helper function to free/cleanup memory buffer // This does not attempt to release the buffer object // itself but only it's contents. // pBuf - memory buffer pointer //-------------------------------------------------- EXP_OPTION int ddocMemBuf_free(DigiDocMemBuf* pBuf) { RETURN_IF_NULL_PARAM(pBuf); if(pBuf->pMem) free(pBuf->pMem); pBuf->pMem = 0; pBuf->nLen = 0; 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; }
//============================================================ // Writes an OCSP Response to a file in DER format // szFileName - OCSP response file name // resp - OCSP response object //============================================================ int WriteOCSPResponse(const char* szFileName, const OCSP_RESPONSE* resp) { BIO* bout = 0; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(resp); if((bout = BIO_new_file(szFileName, "wb")) != NULL) { #if OPENSSL_VERSION_NUMBER > 0x00908000 ASN1_i2d_bio((int (*)(void*, unsigned char**))i2d_OCSP_RESPONSE, bout, (unsigned char*)resp); #else ASN1_i2d_bio((int (*)())i2d_OCSP_RESPONSE, bout, (unsigned char*)resp); #endif //i2d_OCSP_RESPONSE_bio((unsigned char*)bout, resp); BIO_free(bout); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); return ERR_OK; }
//-------------------------------------------------- // Generates the trailer of XML for <EncryptedData> element // These are all the XML constructs following the // base64 encoded cipher data. // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedData_trailer_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncData) // here ends the base64 encoded cipher data 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; }
//============================================================ // 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; }
//-------------------------------------------------- // 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; }
//============================================================ // Reads in an OCSP Request file in DER format // szFileName - OCSP Request file name //============================================================ int ReadOCSPRequest(OCSP_REQUEST **newOCSP_REQUEST, const char* szFileName) { BIO *bin = NULL; OCSP_REQUEST *req = NULL; int err = ERR_OK; RETURN_IF_NULL_PARAM(*newOCSP_REQUEST); RETURN_IF_NULL_PARAM(szFileName); if((bin = BIO_new_file(szFileName, "rb")) != NULL) { req = d2i_OCSP_REQUEST_bio(bin, NULL); BIO_free(bin); if (req == NULL) { err = ERR_OCSP_WRONG_VERSION; } } else err =ERR_FILE_READ; if (err != ERR_OK) SET_LAST_ERROR(err); *newOCSP_REQUEST = req; 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; }
//============================================================ // Gets a new temporary filename // buf - filename buffer //============================================================ EXP_OPTION int getTempFileName(char* szFileName, int len) { int f = 0; char* pFileName = 0; RETURN_IF_NULL_PARAM(szFileName); memset(szFileName, 0, len); #ifdef WIN32 pFileName = _tempnam(0, "ddoc"); #else pFileName = tempnam(0, "ddoc"); #endif strncpy(szFileName, pFileName, len); free(pFileName); return ERR_OK; }
//-------------------------------------------------- // Calculates input datas SHA1-RSA signature // data - input data // dlen - input data length // 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 signData(const byte* data, int dlen, byte* pSigBuf, int* nSigLen, int nDigestType, const char *keyfile, const char* passwd) { int err = ERR_OK; EVP_MD_CTX ctx; EVP_PKEY* pkey; RETURN_IF_NULL_PARAM(data); 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) { EVP_SignInit(&ctx, EVP_sha1()); EVP_SignUpdate (&ctx, data, (unsigned long)dlen); err = EVP_SignFinal(&ctx, pSigBuf, (unsigned int*)nSigLen, pkey); if(err == ERR_LIB_NONE) err = ERR_OK; EVP_PKEY_free(pkey); } 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; }
//-------------------------------------------------- // Converts timestamp (time_t) value to a struct // tm value. Caller must provide address of tm struct. // This function is used because loacltime() is not // thread-safe and win32 has no equvalent of localtime_r(). // pTime - time_t value address // pTmStruct - struct tm address // bLocal - 1=localtime_r, 0=gmtime_r // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocLocalTime(time_t* pTime, struct tm* pTmStruct, int bLocal) { #ifdef WIN32 struct tm *pTm; #endif RETURN_IF_NULL_PARAM(pTime); RETURN_IF_NULL_PARAM(pTmStruct); #ifdef WIN32 EnterCriticalSection(&cs_ddocLocaltime); if(bLocal) pTm = localtime(pTime); else pTm = gmtime(pTime); *pTmStruct = *pTm; LeaveCriticalSection(&cs_ddocLocaltime); #else if(bLocal) localtime_r(pTime, pTmStruct); else gmtime_r(pTime, pTmStruct); #endif return ERR_OK; }