必要最小限の自己署名で zoom の 仮想カメラ (mac-obs-virtual-camera) を使えるようにしてみた。

# はじめに
OBS-Studio で 仮想カメラ (mac-obs-virtual-camera) が使えるようになったので、zoom でも使ってみたいですよね。
https://qiita.com/kitazaki/items/b196301b3a154fcb5a59

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/85a4f532-dc00-3e98-c04b-c77d483e11c6.png" width=50%">

# 仮想カメラを使える環境
- macOS (High Sierra 10.13.6)  
→ 最新の zoom (2020 年 5 月 4 日現在、5.0.1) でも仮想カメラを使用可能。

## 仮想カメラを使えない環境
- macOS (Mojave 10.14.6)  
→ zoom (6.4.10以降)で仮想カメラを使用不可。

## 仮想カメラを使えるようにする手段
調べた限りで大きく 2 種類の方法がありました。

- オリジナルのコード署名を削除する。

```bash
$ codesign --remove-signature /Applications/zoom.us.app/
```

- オリジナルのコード署名を自己署名のものに全て変更する。

```bash
$ codesign --force --deep-verify --sign [自己署名の名前] /Applications/zoom.us.app/
```

(参考)
https://qiita.com/atsn/items/40cb1314c9ddff13d572
https://qiita.com/ketal/items/1aa3bdb0ea7eddd087d4
https://note.com/junky/n/neeeeddf57bde#DHjiV

# 必要最小限の自己署名とは
そもそも何が要因で zoom の仮想カメラが使用できなくなったかを知る必要があります。
事の発端は zoom のバージョン 4.6.9 → 4.6.10 で Blackmagic Design のキャプチャーデバイスが使用できなくなったことのようです。

(参考)
[https://i.reddit.com/r/VIDEOENGINEERING/comments/fy7xi3/fyi_zoom_v4610_breaks_blackmagic_capture_devices/]

これは由々しき事態で、私自身もオンライン配信で Blackmagic Design の ATEM mini / mini pro や AVer Media AVT-C878 などのキャプチャーデバイスを多用するので、使用できなくなったら非常に困ります。

※ 最新の zoom (2020 年 5 月 4 日現在、5.0.1) で問題なく使用できることを確認。
<img width="75%" alt="BMD2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f77ee29d-428b-09f3-8009-7ff23785a5bc.png">
<img width="75%" alt="AverMedia.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c43fb1d6-2132-5e26-39df-e316098b3594.png">

記事を読み進めると、CoreMediaIO プラグインを用いている仮想カメラは「Library Validation Entitlement」が有効になったことで使用できなくなったことが分かります。

(参考)
https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_disable-library-validation

つまり、「Library Validation Entitlement」を無効化すれば仮想カメラが使えることになります。

## Entitlement の変更と自己署名
ここからは実際の手順です。

### 自己署名の作成
まず、キーチェーンを開きます。
<img width="50%" alt="keychain.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/28369ecd-afe7-cf8c-d4d2-c971fce41782.png">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/fe1cac9d-4af8-7a97-bf4d-a26c1eaa1894.png" width="50%">

「キーチェーンアクセス」→「証明書アシスタント」→「証明書を作成」の順に選択する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/fbc5a163-c7a2-764a-17a0-3f2ba7a75a9d.png" width="50%">

名前: (任意) → 今回は my-zoom としました。
固有名のタイプ: 自己署名ルート
証明書のタイプ: コード署名
→作成をクリックする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/64c38a10-a536-6972-02df-754e3668ddee.png" width="50%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/98b49d57-d57e-bc8d-f2a6-898c9dbb0b91.png" width="50%">

### Entitlementの変更
次に Entitlement を変更します。
開発ツール Xcode と Command Line Tools がインストールされている前提で手順を記載します。

```bash
$ cp -a /Applications/zoom.us.app ./
$ codesign -d --entitlements :- zoom.us.app > entitlements.plist
```
entitlements.plist に Disable Library Validation キーを追加します。

(変更前)

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.automation.apple-events</key>
	<true/>
	<key>com.apple.security.device.audio-input</key>
	<true/>
	<key>com.apple.security.device.camera</key>
	<true/>
</dict>
</plist>
```

(変更後)

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.automation.apple-events</key>
	<true/>
	<key>com.apple.security.device.audio-input</key>
	<true/>
	<key>com.apple.security.device.camera</key>
	<true/>
	<key>com.apple.security.cs.disable-library-validation</key>
	<true/>
</dict>
</plist>
```

### 自己署名
-s オプションに作成した自己署名の名前 (今回は my-zoom) を指定して codesign コマンドを実行します。

```bash
$ codesign -s "my-zoom" -f --options=runtime --entitlements entitlements.plist --timestamp zoom.us.app
```

Entitlement 以外のコード署名に変更がない (何も出力されない) ことが確認できます。

```bash
$ diff /Applications/zoom.us.app/Contents/_CodeSignature/CodeResources ./zoom.us.app/Contents/_CodeSignature/CodeResources
```

## 自己署名した zoom の起動
自己署名した zoom を起動して仮想カメラ (OBS Virtual Camera) を選択できるようになったことを確認します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/2d044552-d43e-abe2-76b2-44aa3f3370c0.png" width="75%">

## セキュリティ上の考慮点
なぜ仮想カメラを使用してはいけないのか？という疑問は CVE-2020-11470 で報告されています。
「ユーザー権限を持つローカルプロセスが巧妙に細工されたライブラリをロードして、ユーザーへの通知無しにカメラとマイクへのアクセスを取得できてしまう点」とのこと。

(参考)
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11470