/** * Reads a certificate from a file, returning a context or a the handle to a * temporary memory store. * * @returns true on success, false on failure (error message written). * @param pszCertFile The name of the file containing the * certificates. * @param ppOutCtx Where to return the certificate context. * @param phSrcStore Where to return the handle to the temporary * memory store. */ static bool readCertFile(const char *pszCertFile, PCCERT_CONTEXT *ppOutCtx, HCERTSTORE *phSrcStore) { *ppOutCtx = NULL; *phSrcStore = NULL; bool fRc = false; void *pvFile; size_t cbFile; int rc = RTFileReadAll(pszCertFile, &pvFile, &cbFile); if (RT_SUCCESS(rc)) { *ppOutCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (PBYTE)pvFile, (DWORD)cbFile); if (*ppOutCtx) fRc = true; else { /** @todo figure out if it's some other format... */ RTMsgError("CertCreateCertificateContext returned %s parsing the content of '%s'", errorToString(GetLastError()), pszCertFile); } } else RTMsgError("RTFileReadAll failed on '%s': %Rrc", pszCertFile, rc); RTFileReadAllFree(pvFile, cbFile); return fRc; }
/** * Grows the buffer of a write stream. * * @returns IPRT status code. * @param pStream The stream. Must be in write mode. * @param cbAppending The minimum number of bytes to grow the buffer * with. */ static int scmStreamGrowBuffer(PSCMSTREAM pStream, size_t cbAppending) { size_t cbAllocated = pStream->cbAllocated; cbAllocated += RT_MAX(0x1000 + cbAppending, cbAllocated); cbAllocated = RT_ALIGN(cbAllocated, 0x1000); void *pvNew; if (!pStream->fFileMemory) { pvNew = RTMemRealloc(pStream->pch, cbAllocated); if (!pvNew) return pStream->rc = VERR_NO_MEMORY; } else { pvNew = RTMemDupEx(pStream->pch, pStream->off, cbAllocated - pStream->off); if (!pvNew) return pStream->rc = VERR_NO_MEMORY; RTFileReadAllFree(pStream->pch, pStream->cbAllocated); pStream->fFileMemory = false; } pStream->pch = (char *)pvNew; pStream->cbAllocated = cbAllocated; return VINF_SUCCESS; }
RTDECL(int) RTCrPemFreeSections(PCRTCRPEMSECTION pSectionHead) { while (pSectionHead != NULL) { PRTCRPEMSECTION pFree = (PRTCRPEMSECTION)pSectionHead; pSectionHead = pSectionHead->pNext; if (pFree->pMarker) { if (pFree->pbData) { RTMemFree(pFree->pbData); pFree->pbData = NULL; pFree->cbData = 0; } if (pFree->pszPreamble) { RTMemFree(pFree->pszPreamble); pFree->pszPreamble = NULL; pFree->cchPreamble = 0; } } else { RTFileReadAllFree(pFree->pbData, pFree->cbData); Assert(!pFree->pszPreamble); } pFree->pbData = NULL; pFree->cbData = 0; } return VINF_SUCCESS; }
/** * Frees the resources associated with the stream. * * Nothing is happens to whatever the stream was initialized from or dumped to. * * @param pStream The stream to delete. */ void ScmStreamDelete(PSCMSTREAM pStream) { if (pStream->pch) { if (pStream->fFileMemory) RTFileReadAllFree(pStream->pch, pStream->cbAllocated); else RTMemFree(pStream->pch); pStream->pch = NULL; } pStream->cbAllocated = 0; if (pStream->paLines) { RTMemFree(pStream->paLines); pStream->paLines = NULL; } pStream->cLinesAllocated = 0; }
/** The verbosity level. */ static unsigned g_cVerbosityLevel = 1; static const char *errorToString(DWORD dwErr) { switch (dwErr) { #define MY_CASE(a_uConst) case a_uConst: return #a_uConst; MY_CASE(CRYPT_E_MSG_ERROR); MY_CASE(CRYPT_E_UNKNOWN_ALGO); MY_CASE(CRYPT_E_OID_FORMAT); MY_CASE(CRYPT_E_INVALID_MSG_TYPE); MY_CASE(CRYPT_E_UNEXPECTED_ENCODING); MY_CASE(CRYPT_E_AUTH_ATTR_MISSING); MY_CASE(CRYPT_E_HASH_VALUE); MY_CASE(CRYPT_E_INVALID_INDEX); MY_CASE(CRYPT_E_ALREADY_DECRYPTED); MY_CASE(CRYPT_E_NOT_DECRYPTED); MY_CASE(CRYPT_E_RECIPIENT_NOT_FOUND); MY_CASE(CRYPT_E_CONTROL_TYPE); MY_CASE(CRYPT_E_ISSUER_SERIALNUMBER); MY_CASE(CRYPT_E_SIGNER_NOT_FOUND); MY_CASE(CRYPT_E_ATTRIBUTES_MISSING); MY_CASE(CRYPT_E_STREAM_MSG_NOT_READY); MY_CASE(CRYPT_E_STREAM_INSUFFICIENT_DATA); MY_CASE(CRYPT_I_NEW_PROTECTION_REQUIRED); MY_CASE(CRYPT_E_BAD_LEN); MY_CASE(CRYPT_E_BAD_ENCODE); MY_CASE(CRYPT_E_FILE_ERROR); MY_CASE(CRYPT_E_NOT_FOUND); MY_CASE(CRYPT_E_EXISTS); MY_CASE(CRYPT_E_NO_PROVIDER); MY_CASE(CRYPT_E_SELF_SIGNED); MY_CASE(CRYPT_E_DELETED_PREV); MY_CASE(CRYPT_E_NO_MATCH); MY_CASE(CRYPT_E_UNEXPECTED_MSG_TYPE); MY_CASE(CRYPT_E_NO_KEY_PROPERTY); MY_CASE(CRYPT_E_NO_DECRYPT_CERT); MY_CASE(CRYPT_E_BAD_MSG); MY_CASE(CRYPT_E_NO_SIGNER); MY_CASE(CRYPT_E_PENDING_CLOSE); MY_CASE(CRYPT_E_REVOKED); MY_CASE(CRYPT_E_NO_REVOCATION_DLL); MY_CASE(CRYPT_E_NO_REVOCATION_CHECK); MY_CASE(CRYPT_E_REVOCATION_OFFLINE); MY_CASE(CRYPT_E_NOT_IN_REVOCATION_DATABASE); MY_CASE(CRYPT_E_INVALID_NUMERIC_STRING); MY_CASE(CRYPT_E_INVALID_PRINTABLE_STRING); MY_CASE(CRYPT_E_INVALID_IA5_STRING); MY_CASE(CRYPT_E_INVALID_X500_STRING); MY_CASE(CRYPT_E_NOT_CHAR_STRING); MY_CASE(CRYPT_E_FILERESIZED); MY_CASE(CRYPT_E_SECURITY_SETTINGS); MY_CASE(CRYPT_E_NO_VERIFY_USAGE_DLL); MY_CASE(CRYPT_E_NO_VERIFY_USAGE_CHECK); MY_CASE(CRYPT_E_VERIFY_USAGE_OFFLINE); MY_CASE(CRYPT_E_NOT_IN_CTL); MY_CASE(CRYPT_E_NO_TRUSTED_SIGNER); MY_CASE(CRYPT_E_MISSING_PUBKEY_PARA); MY_CASE(CRYPT_E_OSS_ERROR); default: { PCRTCOMERRMSG pWinComMsg = RTErrCOMGet(dwErr); if (pWinComMsg) return pWinComMsg->pszDefine; static char s_szErr[32]; RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr); return s_szErr; } } } #if 0 /* hacking */ static RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore) { /* * Open the source. */ void *pvFile; size_t cbFile; int rc = RTFileReadAll(pszFilename, &pvFile, &cbFile); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileReadAll failed on '%s': %Rrc", pszFilename, rc); RTEXITCODE rcExit = RTEXITCODE_FAILURE; PCCERT_CONTEXT pCertCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (PBYTE)pvFile, (DWORD)cbFile); if (pCertCtx) { /* * Open the destination. */ HCERTSTORE hDstStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, NULL /* hCryptProv = default */, /*CERT_SYSTEM_STORE_LOCAL_MACHINE*/ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, pwszStore); if (hDstStore != NULL) { #if 0 DWORD dwContextType; if (CertAddSerializedElementToStore(hDstStore, pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded, CERT_STORE_ADD_NEW, 0 /* dwFlags (reserved) */, CERT_STORE_ALL_CONTEXT_FLAG, &dwContextType, NULL)) { RTMsgInfo("Successfully added '%s' to the '%ls' store (ctx type %u)", pszFilename, pwszStore, dwContextType); rcExit = RTEXITCODE_SUCCESS; } else RTMsgError("CertAddSerializedElementToStore returned %s", errorToString(GetLastError())); #else if (CertAddCertificateContextToStore(hDstStore, pCertCtx, CERT_STORE_ADD_NEW, NULL)) { RTMsgInfo("Successfully added '%s' to the '%ls' store", pszFilename, pwszStore); rcExit = RTEXITCODE_SUCCESS; } else RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError())); #endif CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG); } else RTMsgError("CertOpenStore returned %s", errorToString(GetLastError())); CertFreeCertificateContext(pCertCtx); } else RTMsgError("CertCreateCertificateContext returned %s", errorToString(GetLastError())); RTFileReadAllFree(pvFile, cbFile); return rcExit; #if 0 CRYPT_DATA_BLOB Blob; Blob.cbData = (DWORD)cbData; Blob.pbData = (PBYTE)pvData; HCERTSTORE hSrcStore = PFXImportCertStore(&Blob, L"", ) #endif }
RTDECL(int) RTCrPemReadFile(const char *pszFilename, uint32_t fFlags, PCRTCRPEMMARKER paMarkers, size_t cMarkers, PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo) { AssertReturn(!fFlags, VERR_INVALID_FLAGS); size_t cbContent; uint8_t *pbContent; int rc = RTFileReadAllEx(pszFilename, 0, 64U*_1M, RTFILE_RDALL_O_DENY_WRITE, (void **)&pbContent, &cbContent); if (RT_SUCCESS(rc)) { PRTCRPEMSECTION pSection = (PRTCRPEMSECTION)RTMemAllocZ(sizeof(*pSection)); if (pSection) { /* * Try locate the first section. */ size_t offBegin, offEnd, offResume; PCRTCRPEMMARKER pMatch; if ( !rtCrPemIsBinaryFile(pbContent, cbContent) && rtCrPemFindMarkerSection(pbContent, cbContent, 0 /*offStart*/, paMarkers, cMarkers, &pMatch, &offBegin, &offEnd, &offResume) ) { PCRTCRPEMSECTION *ppNext = ppSectionHead; for (;;) { //pSection->pNext = NULL; pSection->pMarker = pMatch; //pSection->pbData = NULL; //pSection->cbData = 0; //pSection->pszPreamble = NULL; //pSection->cchPreamble = 0; *ppNext = pSection; ppNext = &pSection->pNext; /* Decode the section. */ /** @todo copy the preamble as well. */ rc = rtCrPemDecodeBase64(pbContent + offBegin, offEnd - offBegin, (void **)&pSection->pbData, &pSection->cbData); if (RT_FAILURE(rc)) { pSection->pbData = NULL; pSection->cbData = 0; break; } /* More sections? */ if ( offResume + 12 >= cbContent || offResume >= cbContent || !rtCrPemFindMarkerSection(pbContent, cbContent, offResume, paMarkers, cMarkers, &pMatch, &offBegin, &offEnd, &offResume) ) break; /* No. */ /* Ok, allocate a new record for it. */ pSection = (PRTCRPEMSECTION)RTMemAllocZ(sizeof(*pSection)); if (RT_UNLIKELY(!pSection)) { rc = VERR_NO_MEMORY; break; } } if (RT_SUCCESS(rc)) { RTFileReadAllFree(pbContent, cbContent); return rc; } RTCrPemFreeSections(*ppSectionHead); } else { /* * No PEM section found. Return the whole file as one binary section. */ //pSection->pNext = NULL; //pSection->pMarker = NULL; pSection->pbData = pbContent; pSection->cbData = cbContent; //pSection->pszPreamble = NULL; //pSection->cchPreamble = 0; *ppSectionHead = pSection; return VINF_SUCCESS; } } else rc = VERR_NO_MEMORY; RTFileReadAllFree(pbContent, cbContent); } *ppSectionHead = NULL; return rc; }