# 機能設計書 174-乱数生成

## 概要

本ドキュメントは、libuv の `uv_random()` 関数によるプラットフォーム固有のソースからの暗号学的に安全な乱数生成機能について、その設計仕様を記載する。

### 本機能の処理概要

`uv_random()` は、プラットフォーム固有の暗号学的に安全な乱数ソースからランダムなバイト列を生成し、指定されたバッファに書き込む関数である。コールバック指定時は非同期（スレッドプール経由）で実行され、コールバックがNULLの場合は同期的に実行される。

**業務上の目的・背景**：暗号鍵生成、セッションID生成、トークン生成、ソルト生成など、セキュリティ上重要な場面では予測困難な乱数が必要である。各OSが提供する暗号学的乱数ソース（Linux の getrandom()、macOS の getentropy()、Windows の BCryptGenRandom() 等）はAPIが異なるため、本機能はクロスプラットフォームで統一された暗号学的乱数生成APIを提供する。

**機能の利用シーン**：暗号鍵の生成、セッショントークンの生成、UUID/GUIDの生成、暗号化ソルトの生成、CSPRNGが必要なあらゆる場面で利用される。

**主要な処理内容**：
1. 入力パラメータのバリデーション（buflen上限チェック、flagsチェック）
2. コールバック有無による同期/非同期実行の分岐
3. プラットフォーム固有の暗号学的乱数ソースからのバイト列生成
4. 非同期時はスレッドプール経由で実行し、完了時にコールバックを呼び出し

**関連システム・外部連携**：
- Linux: `getrandom()` または `/dev/urandom`、さらにフォールバックとして `sysctl()`
- macOS/OpenBSD/Android 28+: `getentropy()`
- FreeBSD: `getrandom()`
- NetBSD: `sysctl()`
- Windows: `uv__random_winrandom()`（BCryptGenRandom相当）
- AIX/QNX: `/dev/random`
- PASE: `/dev/urandom`

**権限による制御**：特別な権限は不要である。ただしLinuxの一部環境では `/dev/urandom` へのアクセス権限が必要な場合がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | その他ユーティリティ | 主機能 | uv_random()による暗号学的に安全な乱数生成のAPI定義 |

## 機能種別

データ生成処理（暗号学的に安全な乱数バイト列の生成）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes（非同期時） | イベントループ。同期実行時は使用されないがNULLは不可 | - |
| req | uv_random_t* | Yes（非同期時） | リクエストハンドル | - |
| buf | void* | Yes | 乱数を格納するバッファ | - |
| buflen | size_t | Yes | バッファの長さ（バイト数） | 0x7FFFFFFFu を超える場合 UV_E2BIG |
| flags | unsigned | Yes | フラグ。将来の拡張用で、現在は 0 のみ有効 | 0 以外の場合 UV_EINVAL |
| cb | uv_random_cb | No | 完了コールバック。NULLの場合は同期実行 | - |

### 入力データソース

OSカーネルが管理する暗号学的乱数ソース。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| buf | void* | 生成された乱数バイト列（バッファに直接書き込み） |
| 戻り値 | int | 同期実行時: 成功 0、失敗時は負のエラーコード。非同期時: 0（リクエスト投入成功） |
| cb(req, status, buf, buflen) | - | 非同期完了時に呼び出されるコールバック |

### 出力先

指定されたバッファ(buf)に乱数バイト列を書き込み。非同期時はコールバックで通知。

## 処理フロー

### 処理シーケンス

```
1. バリデーション
   └─ buflen > 0x7FFFFFFFu なら UV_E2BIG を返す
   └─ flags != 0 なら UV_EINVAL を返す
2. 同期/非同期判定
   ├─ cb == NULL（同期モード）
   │   └─ uv__random() を直接呼び出して結果を返す
   └─ cb != NULL（非同期モード）
       └─ リクエストを初期化
       └─ スレッドプールにワークを投入
3. [非同期] スレッドプールでの処理
   └─ uv__random_work() が uv__random() を呼び出し
4. [非同期] 完了処理
   └─ uv__random_done() がコールバックを呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{buflen > 0x7FFFFFFF?}
    B -->|Yes| C[UV_E2BIG を返す]
    B -->|No| D{flags != 0?}
    D -->|Yes| E[UV_EINVAL を返す]
    D -->|No| F{cb == NULL?}
    F -->|Yes| G[uv__random で同期実行]
    G --> H[結果を返す]
    F -->|No| I[リクエスト初期化]
    I --> J[スレッドプールに投入]
    J --> K[uv__random_work で乱数生成]
    K --> L[uv__random_done でコールバック呼出]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-174-01 | バッファサイズ上限 | buflen は 0x7FFFFFFFu（約2GB）以下 | 常時 |
| BR-174-02 | フラグ制限 | flags は 0 のみ有効。将来の拡張用に予約 | 常時 |
| BR-174-03 | 同期/非同期切替 | cb が NULL なら同期実行、非NULLなら非同期実行 | 常時 |
| BR-174-04 | プラットフォーム固有ソース | 各OSの暗号学的乱数ソースを優先的に使用し、利用不可の場合はフォールバック | 常時 |

### 計算ロジック

プラットフォーム固有の乱数ソース選択ロジック（src/random.c L31-70）:
1. PASE: `/dev/urandom` を読み取り
2. AIX/QNX: `/dev/random` を読み取り
3. macOS/OpenBSD/Android 28+: `getentropy()` を試行、失敗時は `/dev/urandom` にフォールバック
4. NetBSD: `sysctl()` を使用
5. FreeBSD/Linux: `getrandom()` を試行、失敗時は `/dev/urandom` にフォールバック
6. Linux（追加）: `/dev/urandom` も失敗した場合は `sysctl()` にフォールバック
7. Windows: `uv__random_winrandom()` を使用

## データベース操作仕様

### 操作別データベース影響一覧

該当なし。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_E2BIG | パラメータエラー | buflen > 0x7FFFFFFFu | バッファサイズを2GB以下にする |
| UV_EINVAL | パラメータエラー | flags != 0 | flags に 0 を指定する |
| UV_ENOSYS | システムエラー | プラットフォームのAPI（getentropy等）が利用不可 | フォールバック処理で自動対応 |
| UV_EACCES等 | システムエラー | Linux で /dev/urandom へのアクセス権限不足 | sysctl へのフォールバックで自動対応 |

### リトライ仕様

プラットフォーム固有のフォールバック機構により、優先ソースが利用不可の場合は代替ソースに自動的にフォールバックする。

## トランザクション仕様

該当なし。

## パフォーマンス要件

同期モードでは乱数生成が完了するまでブロックする。暗号学的乱数ソースの性能はプラットフォームとエントロピープールの状態に依存する。非同期モードではスレッドプール（UV__WORK_CPU）で実行されるため、イベントループはブロックされない。

## セキュリティ考慮事項

- 生成される乱数は暗号学的に安全であり、各プラットフォームが提供するCSPRNG（暗号学的擬似乱数生成器）を使用する。
- セキュリティ上重要な用途（暗号鍵生成等）に使用可能。
- バッファの内容は使用後に適切にクリアすることが推奨される。

## 備考

- `uv_random_t` はリクエスト型であり、`UV_REQ_FIELDS` マクロによる共通フィールドを持つ。
- 非同期実行時のワーク種別は `UV__WORK_CPU` であり、CPUバウンドワークとしてスレッドプールで処理される。
- Linux ではフォールバック階層が最も深く、getrandom -> /dev/urandom -> sysctl の3段階がある。

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | uv_random_t 構造体の定義（1791-1801行目）。UV_REQ_FIELDS, loop, status, buf, buflen, cb, work_req |
| 1-2 | uv.h | `include/uv.h` | uv_random_cb コールバック型の定義（352-354行目） |

**読解のコツ**: `uv_random_t` はリクエスト型で、`UV_REQ_FIELDS` マクロにより共通のリクエストフィールド（data等）を持つ。`work_req` フィールドにより `uv__work_submit()` でスレッドプールに投入可能。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | API宣言（1803-1808行目） |

**主要処理フロー**:
1. **1803-1808行目**: 関数シグネチャ。flagsは将来の拡張用で現在は0のみ（コメントに明記）

#### Step 3: メイン実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | random.c | `src/random.c` | `uv_random()` 関数の実装（94-123行目）と内部関数 `uv__random()`（31-70行目） |

**主要処理フロー**:
- **100-101行目**: buflen > 0x7FFFFFFFu のチェック、UV_E2BIG を返す
- **103-104行目**: flags != 0 のチェック、UV_EINVAL を返す
- **106-107行目**: cb == NULL なら `uv__random()` を直接呼び出して同期実行
- **109-120行目**: 非同期実行。リクエスト初期化、フィールドセット、`uv__work_submit()` でスレッドプール投入
- **31-70行目**: `uv__random()` - プラットフォーム分岐による乱数ソース選択

#### Step 4: スレッドプールワーカーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | random.c | `src/random.c` | `uv__random_work()`（73-78行目）と `uv__random_done()`（81-91行目） |

**主要処理フロー**:
- **73-78行目**: ワーカー関数。`container_of` で uv_random_t を取得し `uv__random()` を呼び出す
- **81-91行目**: 完了関数。リクエスト解除、ステータスチェック、コールバック呼び出し

#### Step 5: プラットフォーム固有実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | random-getrandom.c | `src/unix/random-getrandom.c` | Linux/FreeBSD の getrandom() ラッパー |
| 5-2 | random-getentropy.c | `src/unix/random-getentropy.c` | macOS/OpenBSD の getentropy() ラッパー |
| 5-3 | random-devurandom.c | `src/unix/random-devurandom.c` | /dev/urandom 読み取り実装 |
| 5-4 | random-sysctl-linux.c | `src/unix/random-sysctl-linux.c` | Linux sysctl フォールバック |

### プログラム呼び出し階層図

```
uv_random(loop, req, buf, buflen, flags, cb)
    |
    +-- [同期モード: cb == NULL]
    |   +-- uv__random(buf, buflen)
    |       +-- [プラットフォーム分岐]
    |           +-- uv__random_getrandom()       [Linux/FreeBSD]
    |           +-- uv__random_getentropy()       [macOS/OpenBSD]
    |           +-- uv__random_devurandom()       [フォールバック]
    |           +-- uv__random_sysctl()           [NetBSD/Linux]
    |           +-- uv__random_readpath()         [AIX/QNX/PASE]
    |           +-- uv__random_winrandom()        [Windows]
    |
    +-- [非同期モード: cb != NULL]
        +-- uv__req_init()
        +-- uv__work_submit()
            +-- uv__random_work()
            |   +-- uv__random(buf, buflen)
            +-- uv__random_done()
                +-- cb(req, status, buf, buflen)
```

### データフロー図

```
[入力]                    [処理]                          [出力]

buf, buflen ────────▶ uv_random() ────────────────▶ buf(乱数で充填)
flags                    |
cb                       +-- バリデーション
                         +-- 同期/非同期判定
                         +-- OS乱数ソースから読取
                         +-- バッファ書込               ──▶ 戻り値/コールバック
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | API宣言、uv_random_t・uv_random_cb の型定義 |
| random.c | `src/random.c` | ソース | uv_random() メイン実装、プラットフォーム分岐ロジック |
| random-getrandom.c | `src/unix/random-getrandom.c` | ソース | Linux/FreeBSD の getrandom() ラッパー |
| random-getentropy.c | `src/unix/random-getentropy.c` | ソース | macOS/OpenBSD の getentropy() ラッパー |
| random-devurandom.c | `src/unix/random-devurandom.c` | ソース | /dev/urandom 読み取り実装 |
| random-sysctl-linux.c | `src/unix/random-sysctl-linux.c` | ソース | Linux sysctl フォールバック |
| netbsd.c | `src/unix/netbsd.c` | ソース | NetBSD の sysctl 実装 |
| internal.h | `src/unix/internal.h` | ヘッダー | 内部関数宣言 |
| uv-common.h | `src/uv-common.h` | ヘッダー | 共通内部定義 |
