/* sqAddPfxCertToStore: Adds a PFX certificate to MY certificate store. Arguments: pfxData - the contents of the PFX certificate file pfxLen - the length of the PFX certificate file passData - the utf8 encoded password for the file passLen - the size of the password Returns: 1 on success, 0 on failure */ static sqInt sqAddPfxCertToStore(char *pfxData, sqInt pfxLen, char *passData, sqInt passLen) { PCCERT_CONTEXT pContext; HCERTSTORE pfxStore, myStore; CRYPT_DATA_BLOB blob; WCHAR widePass[4096]; /* Verify that this is a PFX file */ blob.cbData = pfxLen; blob.pbData = pfxData; if(!PFXIsPFXBlob(&blob)) return 0; /* Not a PFX blob */ /* Verify that the password is all right */ widePass[0] = 0; if(passLen > 0) { DWORD wideLen = MultiByteToWideChar(CP_UTF8, 0, passData, passLen, widePass, 4095); widePass[wideLen] = 0; } if(!PFXVerifyPassword(&blob, widePass, 0)) return 0; /* Invalid password */ /* Import the PFX blob into a temporary store */ pfxStore = PFXImportCertStore(&blob, widePass, 0); if(!pfxStore) return 0; /* And copy the certificates to MY store */ myStore = CertOpenSystemStore(0, "MY"); pContext = NULL; while(pContext = CertEnumCertificatesInStore(pfxStore, pContext)) { CertAddCertificateContextToStore(myStore, pContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL); } CertCloseStore(myStore, 0); CertCloseStore(pfxStore, 0); return 1; }
void PfxCertificate::init( ByteBuffer pfxBlob, const tstring & password, const tstring & certName) { CRYPT_DATA_BLOB blob = {0}; blob.cbData = static_cast<DWORD>(pfxBlob.getLength()); blob.pbData = (BYTE*) pfxBlob.getPtr(); BOOL recognizedPFX = PFXIsPFXBlob(&blob); DWORD dwErr = GetLastError(); RCF_VERIFY( recognizedPFX, Exception(_RcfError_ApiError("PFXIsPFXBlob()"), dwErr)); std::wstring wPassword = RCF::toWstring(password); // For Windows 98, the flag CRYPT_MACHINE_KEYSET is not valid. mPfxStore = PFXImportCertStore( &blob, wPassword.c_str(), CRYPT_MACHINE_KEYSET | CRYPT_EXPORTABLE); dwErr = GetLastError(); RCF_VERIFY( mPfxStore, Exception(_RcfError_ApiError("PFXImportCertStore()"), dwErr)); PCCERT_CONTEXT pCertStore = NULL; // Tempting to use CERT_FIND_ANY for the case where there is just a single // certificate in the PFX file. However, doing so appears to not load the // private key information. So we use CERT_FIND_SUBJECT_STR instead, and // require the certificate name to be passed in. DWORD dwFindType = CERT_FIND_SUBJECT_STR; std::wstring wCertName = RCF::toWstring(certName); const void * pvFindPara = wCertName.c_str(); pCertStore = CertFindCertificateInStore( mPfxStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, dwFindType, pvFindPara, pCertStore); dwErr = GetLastError(); RCF_VERIFY( pCertStore, Exception(_RcfError_ApiError("CertFindCertificateInStore()"), dwErr)); BOOL bFreeHandle; HCRYPTPROV hProv; DWORD dwKeySpec; BOOL bResult = CryptAcquireCertificatePrivateKey( pCertStore, 0, NULL, &hProv, &dwKeySpec, &bFreeHandle); dwErr = GetLastError(); RCF_VERIFY( bResult, Exception(_RcfError_ApiError("CryptAcquireCertificatePrivateKey()"), dwErr)); mpCert = pCertStore; }
void SslCredential::loadPrivCertStore() { // Get a handle to the system store or pkcs#12 file qpid::sys::ssl::SslOptions& opts = qpid::sys::ssl::SslOptions::global; if (opts.certFilename.empty()) { // opening a system store, names are not case sensitive std::string store = opts.certStore.empty() ? "my" : opts.certStore; std::transform(store.begin(), store.end(), store.begin(), ::tolower); // map confusing GUI name to actual registry store name if (store == "personal") store = "my"; certStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL, CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, store.c_str()); if (!certStore) { HRESULT status = GetLastError(); loadError.set(Msg() << "Could not open system certificate store: " << store, status); return; } QPID_LOG(debug, "SslConnector using certifcates from system store: " << store); } else { // opening the store from file and populating it with a private key HANDLE certFileHandle = NULL; certFileHandle = CreateFile(opts.certFilename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == certFileHandle) { HRESULT status = GetLastError(); loadError.set(Msg() << "Failed to open the file holding the private key: " << opts.certFilename, status); return; } std::vector<BYTE> certEncoded; DWORD certEncodedSize = 0L; const DWORD fileSize = GetFileSize(certFileHandle, NULL); if (INVALID_FILE_SIZE != fileSize) { certEncoded.resize(fileSize); bool result = false; result = ReadFile(certFileHandle, &certEncoded[0], fileSize, &certEncodedSize, NULL); if (!result) { // the read failed, return the error as an HRESULT HRESULT status = GetLastError(); CloseHandle(certFileHandle); loadError.set(Msg() << "Reading the private key from file failed " << opts.certFilename, status); return; } } else { HRESULT status = GetLastError(); loadError.set(Msg() << "Unable to read the certificate file " << opts.certFilename, status); return; } CloseHandle(certFileHandle); CRYPT_DATA_BLOB blobData; blobData.cbData = certEncodedSize; blobData.pbData = &certEncoded[0]; // get passwd from file and convert to null terminated wchar_t (Windows UCS2) std::string passwd = getPasswd(opts.certPasswordFile); if (loadError.pending()) return; int pwlen = passwd.length(); std::vector<wchar_t> pwUCS2(pwlen + 1, L'\0'); int nwc = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, passwd.data(), pwlen, &pwUCS2[0], pwlen); if (!nwc) { HRESULT status = GetLastError(); loadError.set("Error converting password from UTF8", status); return; } certStore = PFXImportCertStore(&blobData, &pwUCS2[0], 0); if (certStore == NULL) { HRESULT status = GetLastError(); loadError.set("Failed to open the certificate store", status); return; } QPID_LOG(debug, "SslConnector using certificate from pkcs#12 file: " << opts.certFilename); } }
/** * gnutls_system_key_add_x509: * @crt: the certificate to be added * @privkey: the key to be added * @label: the friendly name to describe the key * @cert_url: if non-NULL it will contain an allocated value with the certificate URL * @key_url: if non-NULL it will contain an allocated value with the key URL * * This function will added the given key and certificate pair, * to the system list. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.4.0 **/ int gnutls_system_key_add_x509(gnutls_x509_crt_t crt, gnutls_x509_privkey_t privkey, const char *label, char **cert_url, char **key_url) { HCERTSTORE store = NULL; CRYPT_DATA_BLOB pfx; gnutls_datum_t _pfx = { NULL, 0 }; gnutls_pkcs12_t p12 = NULL; gnutls_pkcs12_bag_t bag1 = NULL, bag2 = NULL; uint8_t id[MAX_WID_SIZE]; size_t id_size; gnutls_datum_t kid; int ret; if (ncrypt_init == 0) return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); if (label == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); id_size = sizeof(id); ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size); if (ret < 0) return gnutls_assert_val(ret); kid.data = id; kid.size = id_size; /* the idea: import the cert and private key into PKCS #12 * format, export it into pfx, and import it into store */ ret = gnutls_pkcs12_init(&p12); if (ret < 0) return gnutls_assert_val(ret); ret = gnutls_pkcs12_bag_init(&bag1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_bag_set_crt(bag1, crt); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_bag_set_key_id(bag1, 0, &kid); if (ret < 0) { gnutls_assert(); goto cleanup; } if (label) gnutls_pkcs12_bag_set_friendly_name(bag1, 0, label); ret = gnutls_pkcs12_bag_init(&bag2); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_bag_set_privkey(bag2, privkey, NULL, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_bag_set_key_id(bag2, 0, &kid); if (ret < 0) { gnutls_assert(); goto cleanup; } if (label) gnutls_pkcs12_bag_set_friendly_name(bag2, 0, label); ret = gnutls_pkcs12_set_bag(p12, bag1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_set_bag(p12, bag2); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_generate_mac(p12, "123456"); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_export2(p12, GNUTLS_X509_FMT_DER, &_pfx); if (ret < 0) { gnutls_assert(); goto cleanup; } pfx.cbData = _pfx.size; pfx.pbData = _pfx.data; store = PFXImportCertStore(&pfx, L"123456", 0); if (store == NULL) { gnutls_assert(); ret = GNUTLS_E_INVALID_REQUEST; goto cleanup; } if (cert_url || key_url) { unsigned char sha[20]; CRYPT_HASH_BLOB blob; const CERT_CONTEXT *cert = NULL; gnutls_datum_t data; ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, data.data, data.size, sha); gnutls_free(data.data); if (ret < 0) { gnutls_assert(); goto cleanup; } blob.cbData = sizeof(sha); blob.pbData = sha; cert = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH, &blob, NULL); if (cert == NULL) { gnutls_assert(); ret = GNUTLS_E_KEY_IMPORT_FAILED; goto cleanup; } ret = get_win_urls(cert, cert_url, key_url, NULL, NULL); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = 0; cleanup: if (p12 != NULL) gnutls_pkcs12_deinit(p12); if (bag1 != NULL) gnutls_pkcs12_bag_deinit(bag1); if (bag2 != NULL) gnutls_pkcs12_bag_deinit(bag2); if (store != NULL) CertCloseStore(store, 0); gnutls_free(_pfx.data); return ret; }