前説
QUICにちょっと興味あるから、qicoquicちょっとビルドしてみようぜ!みたいな記事です
手を出すなら王道のQUICHEやらMsQuicのが良いんじゃね、という気もしますが、
純粋なQUIC実装になっていて、確認しやすそうだったのでこちらにしました
参考にした資料はこちら
picoquic
Private Octopus and QUIC
ということで、軽くビルド関連の資料を読んでみた感じ、
picoquicはpicotlsに依存しており、qicotlsはOpenSSLに依存しているようです
今回はビルドが少しだけ面倒なOpenSSLではなく、LibreSSL4.1を使用することにしました
(LibreSSLのX25519がqicotlsで非対応になっているようなので、qicotlsに別途パッチを当てています)
また、最小限ビルドのようなものにすればOpenSSLも不要っぽいのですが、
とりあえずサンプルやテストが動作するものを使ってみたかったのでそのままビルドしております
今回は家のノートPCにOpenSSLのビルド環境が整っていなかったのでLibreSSLを採用する非公式チャートとなっております…
一般的な環境であればOpenSSLを採用するチャートが大変にオススメです
(ビルドが高速で簡単に静的リンクの状態に持ち込めるので、LibreSSLも悪くない選択だと思っています)
事前に必要なものをインストールしておく
Visual Studio
当記事の手順は最新のVisual Studio 2022 Communityで確認しています
「C++によるデスクトップ開発」が必要になります
cmake
LibreSSLのビルドにはcmakeが必要になります
以下のURLからcmakeをダウンロードしてインストールします
https://cmake.org/download/
https://github.com/Kitware/CMake/releases/download/v3.31.8/cmake-3.31.8-windows-x86_64.msi
テスト環境ではこのバージョンを使っていました
LibreSSLのビルド
LibreSSLをビルドするには、VisualStudio開発環境が必要です
x64 Native Tools Command Prompt for VS 2022
等のVisualStudio開発環境で実行しましょう
LibreSSLからファイルを取得します
https://www.libressl.org/
今回は4.1のパッケージを使用しました
https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-4.1.0.tar.gz
ダウンロードして展開し、展開したディレクトリに移動します
LibreSSLのビルドは以下のコマンドで行います
cmake -S . -B build -G "Visual Studio 17 2022" -DCMAKE_INSTALL_PREFIX=c:\libressl
CMAKE_INSTALL_PREFIXはLibreSSLをインストールするディレクトリを指定しています、
管理者権限が必要なフォルダにインストールする設定がデフォルトになっているようなので必要に応じて対処してください
cd build
MSBuild LibreSSL.sln /t:rebuild /p:Configuration=Release -m
ビルド成功したらそのままインストールします
MSBuild INSTALL.vcxproj /t:build /p:Configuration=Release
インストールが終わったら、OpenSSLとして環境変数を登録します
CMAKE_INSTALL_PREFIXで指定したパスを設定します
setx OPENSSL64DIR c:\libressl
次にOpenSSLとLibreSSLでは提供されるファイル名が異なっているため、OpenSSL合わせで統一します
c:\libressl\crypto.lib -> c:\libressl\libcrypto.lib
コピーしたり、シンボリックリンクを作成したりしてください
picotlsをビルドする
をチェックアウト、picotls\picotlsvs\picotlsvs.slnを開きビルドします
(※X25519がサポートされていない状態でのビルド結果となります)
git clone https://github.com/h2o/picotls.git
チェックアウトだけではファイルがすべてそろっていないことがあるようなので、テスト関連のビルド時にエラーが出た場合は、サブモジュール更新を行う必要があるようです
cd picotls
git submodule init
git submodule update
picoquicをビルドする
をpicotlsの兄弟フォルダとしてチェックアウトします
(↓のような関係性になるように配置します)
git clone https://github.com/private-octopus/picoquic.git
picoquic\picoquic.sln を開いてビルドしますが、
LibreSSLでビルドした場合、qicotlsでX25519がサポートされていない状態となるため
変数未定義によりビルドエラーになってしまいます
picotlsを若干修正する
二箇所ほど修正するとビルドが通るようになります、
正しいコードなのかは不勉強なためイマイチ分かっておらず……
(OpenSSLの通過テストと同じ結果やからまあええやろ…の精神ぐらいで生存させていただいております)
修正そのものはこちらのリポジトリから取得できます
https://github.com/kei-y/picotls/tree/f350eab_with_libressl-4.1.0
diff --git a/include/picotls/openssl.h b/include/picotls/openssl.h
index 49c1cf2..6eba68c 100644
--- a/include/picotls/openssl.h
+++ b/include/picotls/openssl.h
@@ -60,7 +60,7 @@ extern ptls_key_exchange_algorithm_t ptls_openssl_secp521r1;
#ifdef EVP_PKEY_ED25519
#define PTLS_OPENSSL_HAVE_ED25519 1
#endif
-#if defined(NID_X25519) && !defined(LIBRESSL_VERSION_NUMBER)
+#if defined(NID_X25519)
#define PTLS_OPENSSL_HAVE_X25519 1
#define PTLS_OPENSSL_HAS_X25519 1 /* deprecated; use HAVE_ */
extern ptls_key_exchange_algorithm_t ptls_openssl_x25519;
diff --git a/lib/openssl.c b/lib/openssl.c
index 01fcfce..408bdb7 100644
diff --git a/lib/openssl.c b/lib/openssl.c
index 01fcfce..408bdb7 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -558,6 +558,14 @@ static int evp_keyex_on_exchange(ptls_key_exchange_context_t **_ctx, int release
#undef X25519_KEY_SIZE
#endif
+#if defined(LIBRESSL_VERSION_NUMBER)
+ const int key_type = EVP_PKEY_id(ctx->privkey);
+
+ if ((evppeer = EVP_PKEY_new_raw_public_key(key_type, NULL, peerkey.base, peerkey.len)) == NULL) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+#else
if ((evppeer = EVP_PKEY_new()) == NULL) {
ret = PTLS_ERROR_NO_MEMORY;
goto Exit;
@@ -570,6 +578,7 @@ static int evp_keyex_on_exchange(ptls_key_exchange_context_t **_ctx, int release
ret = PTLS_ERROR_LIBRARY;
goto Exit;
}
+#endif
if ((evpctx = EVP_PKEY_CTX_new(ctx->privkey, NULL)) == NULL) {
ret = PTLS_ERROR_LIBRARY;
goto Exit;
@@ -627,12 +636,40 @@ static int evp_keyex_init(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange
}
*ctx = (struct st_evp_keyex_context_t){{algo, {NULL}, evp_keyex_on_exchange}, pkey};
+#if defined(LIBRESSL_VERSION_NUMBER)
+ size_t key_len;
+
+ // required key size
+ if (EVP_PKEY_get_raw_public_key(ctx->privkey, NULL, &key_len) == 0) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (key_len == 0) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+
+ if ((ctx->super.pubkey.base = OPENSSL_malloc(key_len)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ ctx->super.pubkey.len = key_len;
+
+ /* set public key */
+ if (EVP_PKEY_get_raw_public_key(ctx->privkey, ctx->super.pubkey.base, &ctx->super.pubkey.len) == 0) {
+ ret = PTLS_ERROR_LIBRARY;
+ OPENSSL_free(ctx->super.pubkey.base);
+ ctx->super.pubkey.base = NULL;
+ goto Exit;
+ }
+#else
/* set public key */
if ((ctx->super.pubkey.len = EVP_PKEY_get1_tls_encodedpoint(ctx->privkey, &ctx->super.pubkey.base)) == 0) {
ctx->super.pubkey.base = NULL;
ret = PTLS_ERROR_NO_MEMORY;
goto Exit;
}
+#endif
*_ctx = &ctx->super;
ret = 0;
--
この変更を適応した状態でpicotlsのビルドを行いX25519関連の定義をアクティブにします
picotlsのビルドが通ったらqicoquicのビルドを再度行います
(こちらも記事作成段階ではvs2022環境でリンクエラーになるものがあったため、
https://github.com/kei-y/picoquic/tree/6b9a563_fix_x64_linkerror
微修正を行っています)
ビルドエラーが発生せず、VisualStudioのテストエクスプローラですべてのテストが成功することを確認しておしまいです、お疲れ様でした!
実際のビルドに使用したソースコード
ビルドに実際に使用したコードへのリンク
qicoquic
qicotls
libressl-4.1.0
最後に
公式マニュアルに非常に丁寧な資料があって良かったです
実家の帰省中にでも動作確認したり、内部コードを読み込んでみようと思います