/* 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;
}
Exemplo n.º 2
0
    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; 
    }
Exemplo n.º 3
0
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);
    }
}
Exemplo n.º 4
0
/**
 * 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;
}