diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..4505e63f --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,21 @@ +# Cargo configuration for specter +# Uses prebuilt BoringSSL libraries from lib/boringssl/ + +# Note: Environment variables for boring-sys are set via: +# - Local dev: source scripts/env.sh +# - CI: Set BORING_BSSL_PATH and BORING_BSSL_INCLUDE_PATH in workflow + +[build] +# Uncomment to use prebuilt BoringSSL by default +# rustflags = [] + +[env] +# These are relative to the manifest directory (where Cargo.toml lives) +# Unfortunately Cargo doesn't support relative paths in [env], so we use scripts instead + +# Target-specific linker settings for cross-compilation +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" + +[target.x86_64-unknown-linux-musl] +linker = "x86_64-linux-musl-gcc" diff --git a/.config/nextest.toml b/.config/nextest.toml index 588efc6a..faea6496 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -13,8 +13,8 @@ retries = 1 slow-timeout = { period = "60s", terminate-after = 2 } [profile.ci] -# CI profile with stricter settings -retries = 0 +# CI profile -- retry once to handle transient flakes +retries = 1 failure-output = "final" success-output = "never" diff --git a/.github/workflows/boringssl-release.yml b/.github/workflows/boringssl-release.yml new file mode 100644 index 00000000..3462d726 --- /dev/null +++ b/.github/workflows/boringssl-release.yml @@ -0,0 +1,94 @@ +name: BoringSSL Prebuilt Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Version tag (e.g., boringssl-prebuilt-v1)' + required: true + default: 'boringssl-prebuilt-v1' + +permissions: + contents: write + +jobs: + package: + name: Package prebuilt BoringSSL + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Verify libraries exist + run: | + echo "Checking for prebuilt libraries..." + ls -la lib/boringssl/ + + # Verify all expected targets + for target in aarch64-apple-darwin x86_64-apple-darwin \ + x86_64-unknown-linux-gnu x86_64-unknown-linux-musl \ + aarch64-unknown-linux-gnu \ + x86_64-pc-windows-msvc aarch64-pc-windows-msvc; do + if [[ -d "lib/boringssl/$target" ]]; then + echo "✓ $target" + ls -lh "lib/boringssl/$target/" + else + echo "✗ $target (missing)" + fi + done + + - name: Package archives + run: | + cd lib/boringssl + + # Create per-target archives + for target in */; do + target=${target%/} + [[ "$target" == "include" ]] && continue + + echo "Packaging $target..." + tar -czf "boringssl-${target}.tar.gz" include/ "$target/" + + # Also create zip for Windows + if [[ "$target" == *windows* ]]; then + zip -r "boringssl-${target}.zip" include/ "$target/" + fi + done + + # Create all-in-one archive + tar -czf boringssl-all-targets.tar.gz include/ */ + + ls -lh *.tar.gz *.zip 2>/dev/null || true + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ inputs.version }} + name: BoringSSL Prebuilt Libraries ${{ inputs.version }} + body: | + Prebuilt BoringSSL static libraries for use with `boring-sys` crate. + + ## Targets + - `aarch64-apple-darwin` - macOS ARM64 (Apple Silicon) + - `x86_64-apple-darwin` - macOS x86_64 + - `x86_64-unknown-linux-gnu` - Linux x86_64 (glibc) + - `x86_64-unknown-linux-musl` - Linux x86_64 (musl) + - `aarch64-unknown-linux-gnu` - Linux ARM64 (glibc) + - `x86_64-pc-windows-msvc` - Windows x86_64 + - `aarch64-pc-windows-msvc` - Windows ARM64 + + ## Usage + + Download the archive for your target and set environment variables: + + ```bash + export BORING_BSSL_PATH=/path/to/boringssl//build + export BORING_BSSL_INCLUDE_PATH=/path/to/boringssl/include + cargo build + ``` + + Or download `boringssl-all-targets.tar.gz` for all platforms. + files: | + lib/boringssl/*.tar.gz + lib/boringssl/*.zip + draft: false + prerelease: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8bbd59ec..4dbc6db9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,72 +8,121 @@ on: env: CARGO_TERM_COLOR: always RUST_BACKTRACE: 1 - # Disable incremental compilation in CI (sccache handles caching) CARGO_INCREMENTAL: 0 - # RUSTC_WRAPPER set after sccache is initialized (see step below) SCCACHE_GHA_ENABLED: "true" jobs: - ci: - name: CI - runs-on: macos-latest + test: + name: Test (macOS) + runs-on: macos-14 timeout-minutes: 20 steps: - - name: Checkout code - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Install Rust toolchain + - name: Install Rust uses: dtolnay/rust-toolchain@stable with: components: rustfmt - - name: Setup sccache - uses: mozilla-actions/sccache-action@v0.0.9 + - uses: mozilla-actions/sccache-action@v0.0.9 + - run: echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV - - name: Configure sccache for Rust - run: echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV - - - name: Cache cargo registry - uses: actions/cache@v4 + - uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-registry- + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Install cargo-nextest - uses: taiki-e/install-action@v2 + - uses: taiki-e/install-action@v2 with: tool: cargo-nextest - - name: Check formatting - run: cargo fmt -- --check + - name: Configure prebuilt BoringSSL + run: | + if [[ "$(uname -m)" == "arm64" ]]; then + echo "BORING_BSSL_PATH=${{ github.workspace }}/lib/boringssl/aarch64-apple-darwin/build" >> $GITHUB_ENV + else + echo "BORING_BSSL_PATH=${{ github.workspace }}/lib/boringssl/x86_64-apple-darwin/build" >> $GITHUB_ENV + fi + echo "BORING_BSSL_INCLUDE_PATH=${{ github.workspace }}/lib/boringssl/include" >> $GITHUB_ENV - - name: Run tests - run: cargo nextest run --all-features --profile ci + - run: cargo fmt -- --check + - run: cargo nextest run --all-features --profile ci - - name: Archive test results + - uses: actions/upload-artifact@v4 if: always() - uses: actions/upload-artifact@v4 with: name: nextest-results path: target/nextest/ci/junit.xml if-no-files-found: ignore - - name: Run fingerprint_validation example + - name: Run examples uses: nick-fields/retry@v3 with: - timeout_minutes: 2 + timeout_minutes: 3 max_attempts: 3 retry_wait_seconds: 10 - command: cargo run --example fingerprint_validation + command: | + cargo run --example fingerprint_validation + cargo run --example protocol_test - - name: Run protocol_test example - uses: nick-fields/retry@v3 + build-linux: + name: Build Linux (${{ matrix.target }}) + runs-on: macos-14 + strategy: + matrix: + target: + - aarch64-unknown-linux-gnu + - x86_64-unknown-linux-gnu + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable with: - timeout_minutes: 3 - max_attempts: 3 - retry_wait_seconds: 10 - command: cargo run --example protocol_test + targets: ${{ matrix.target }} + + - uses: taiki-e/install-action@v2 + with: + tool: just,cargo-zigbuild + + - name: Install zig + run: brew install zig + + - name: Build + run: | + chmod +x scripts/zig-cc-* scripts/zig-cxx-* + just zigbuild ${{ matrix.target }} + + build-windows: + name: Build Windows (${{ matrix.target }}) + runs-on: macos-14 + strategy: + matrix: + target: + - x86_64-pc-windows-msvc + - aarch64-pc-windows-msvc + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Install LLVM + run: brew install llvm + + - name: Add LLVM to PATH + run: echo "$(brew --prefix llvm)/bin" >> "$GITHUB_PATH" + + - uses: taiki-e/install-action@v2 + with: + tool: cargo-xwin + + - name: Build + run: cargo xwin build --release --target ${{ matrix.target }} --lib + env: + BORING_BSSL_PATH: ${{ github.workspace }}/lib/boringssl/${{ matrix.target }}/build + BORING_BSSL_INCLUDE_PATH: ${{ github.workspace }}/lib/boringssl/include diff --git a/.github/workflows/node-release.yml b/.github/workflows/node-release.yml index c9499670..c8da5fea 100644 --- a/.github/workflows/node-release.yml +++ b/.github/workflows/node-release.yml @@ -18,26 +18,14 @@ jobs: fail-fast: false matrix: settings: - # Native builds - host: macos-14 target: aarch64-apple-darwin - build: npm run build - host: macos-14 target: x86_64-apple-darwin - build: npm run build -- --target x86_64-apple-darwin - - host: ubuntu-latest + - host: macos-14 target: x86_64-unknown-linux-gnu - build: npm run build - - host: windows-2022 - target: x86_64-pc-windows-msvc - build: npm run build - # Cross-compilation with zig wrapper scripts (handles boring-sys/cmake) - - host: ubuntu-latest + - host: macos-14 target: aarch64-unknown-linux-gnu - build: npm run build -- --target aarch64-unknown-linux-gnu - cross: true - zig_target: aarch64-linux-gnu - libc_impl: glibc name: Build ${{ matrix.settings.target }} runs-on: ${{ matrix.settings.host }} steps: @@ -55,124 +43,15 @@ jobs: with: targets: ${{ matrix.settings.target }} - - name: Install dependencies - run: | - cd bindings/node - npm install - - # Install zig for cross-compilation builds - - name: Install Zig - if: matrix.settings.cross - uses: goto-bus-stop/setup-zig@v2 - with: - version: 0.13.0 - - - name: Install cargo-zigbuild - if: matrix.settings.cross - run: cargo install cargo-zigbuild - - # Make wrapper scripts executable - - name: Setup zig wrapper scripts - if: matrix.settings.cross - run: | - chmod +x .github/scripts/zig-cc-${{ matrix.settings.zig_target }} - chmod +x .github/scripts/zig-cxx-${{ matrix.settings.zig_target }} - - # All Linux builds need cmake + clang for bindgen - - name: Install build tools (Linux) - if: runner.os == 'Linux' - run: | - sudo apt-get update - sudo apt-get install -y cmake clang libclang-dev - - # Windows: Install NASM + Perl (required for BoringSSL build from source) - - name: Install build tools (Windows) - if: runner.os == 'Windows' - run: | - choco install -y nasm strawberryperl - echo "C:\Program Files\NASM" >> $env:GITHUB_PATH - echo "C:\Strawberry\perl\bin" >> $env:GITHUB_PATH - shell: pwsh - - - name: Build (native - Unix) - if: ${{ !matrix.settings.cross && runner.os != 'Windows' }} - run: | - cd bindings/node - ${{ matrix.settings.build }} - env: - MACOSX_DEPLOYMENT_TARGET: '10.13' - - - name: Build (native - Windows) - if: runner.os == 'Windows' - run: | - cd bindings/node - # Build with explicit target dir to prevent cmake-rs path mismatch - $env:CARGO_TARGET_DIR = "D:\a\specter\specter\target" - cargo build --release -vv 2>&1 | Tee-Object -FilePath build.log - # If cargo succeeds, run the actual napi build - npm run build - shell: pwsh - - - name: Upload Windows build log - if: runner.os == 'Windows' && always() - uses: actions/upload-artifact@v4 + - name: Install Linux cross-compilation tools + if: contains(matrix.settings.target, 'unknown-linux') + uses: taiki-e/install-action@v2 with: - name: windows-build-log - path: bindings/node/build.log - if-no-files-found: ignore + tool: cargo-zigbuild - - name: Build (cross-compile with zig) - if: matrix.settings.cross - run: | - # Get zig's lib directory for sysroot paths - ZIG_LIB=$(zig env | grep lib_dir | sed 's/.*"\([^"]*\)".*/\1/') - echo "ZIG_LIB=$ZIG_LIB" - - # Set bindgen clang args with zig's sysroot for the target - # Include paths: target-specific, generic linux, generic libc, and libc implementation - BINDGEN_ARGS="--target=${{ matrix.settings.zig_target }}" - BINDGEN_ARGS="$BINDGEN_ARGS -isystem $ZIG_LIB/libc/include/${{ matrix.settings.zig_target }}" - BINDGEN_ARGS="$BINDGEN_ARGS -isystem $ZIG_LIB/libc/include/any-linux-any" - BINDGEN_ARGS="$BINDGEN_ARGS -isystem $ZIG_LIB/libc/include/generic-${{ matrix.settings.libc_impl }}" - BINDGEN_ARGS="$BINDGEN_ARGS -isystem $ZIG_LIB/libc/${{ matrix.settings.libc_impl }}/include" - export BINDGEN_EXTRA_CLANG_ARGS="$BINDGEN_ARGS" - echo "BINDGEN_EXTRA_CLANG_ARGS=$BINDGEN_EXTRA_CLANG_ARGS" - - cd bindings/node - ${{ matrix.settings.build }} - env: - # Use wrapper scripts that translate --target flag for cmake/boring-sys - CC: ${{ github.workspace }}/.github/scripts/zig-cc-${{ matrix.settings.zig_target }} - CXX: ${{ github.workspace }}/.github/scripts/zig-cxx-${{ matrix.settings.zig_target }} - CC_${{ matrix.settings.target }}: ${{ github.workspace }}/.github/scripts/zig-cc-${{ matrix.settings.zig_target }} - CXX_${{ matrix.settings.target }}: ${{ github.workspace }}/.github/scripts/zig-cxx-${{ matrix.settings.zig_target }} - AR_${{ matrix.settings.target }}: zig ar - CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: ${{ github.workspace }}/.github/scripts/zig-cc-aarch64-linux-gnu - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: bindings-${{ matrix.settings.target }} - path: bindings/node/*.node - if-no-files-found: error - - build-musl: - name: Build x86_64-unknown-linux-musl - runs-on: ubuntu-latest - container: - image: messense/rust-musl-cross:x86_64-musl - steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js - run: | - curl -fsSL https://deb.nodesource.com/setup_20.x | bash - - apt-get install -y nodejs - - - name: Install build tools - run: | - apt-get update - apt-get install -y cmake clang libclang-dev perl golang + - name: Install Zig + if: contains(matrix.settings.target, 'unknown-linux') + run: brew install zig - name: Install dependencies run: | @@ -181,21 +60,49 @@ jobs: - name: Build run: | + set -euo pipefail + TARGET="${{ matrix.settings.target }}" cd bindings/node - npm run build -- --target x86_64-unknown-linux-musl + + if [[ "$TARGET" == *"unknown-linux"* ]]; then + chmod +x ../../scripts/zig-cc-* ../../scripts/zig-cxx-* + + case "$TARGET" in + aarch64-unknown-linux-gnu) + export CC="$GITHUB_WORKSPACE/scripts/zig-cc-aarch64-linux-gnu" + export CXX="$GITHUB_WORKSPACE/scripts/zig-cxx-aarch64-linux-gnu" + ;; + x86_64-unknown-linux-gnu) + export CC="$GITHUB_WORKSPACE/scripts/zig-cc-x86_64-linux-gnu" + export CXX="$GITHUB_WORKSPACE/scripts/zig-cxx-x86_64-linux-gnu" + ;; + esac + + export "CC_${TARGET//-/_}=$CC" + export "CXX_${TARGET//-/_}=$CXX" + export "AR_${TARGET//-/_}=ar" + + npm run build -- --target "$TARGET" --cross-compile + elif [[ "$TARGET" == "aarch64-apple-darwin" ]]; then + npm run build + else + npm run build -- --target "$TARGET" + fi env: - CARGO_BUILD_TARGET: x86_64-unknown-linux-musl + MACOSX_DEPLOYMENT_TARGET: '10.13' + BORING_BSSL_PATH: ${{ github.workspace }}/lib/boringssl/${{ matrix.settings.target }}/build + BORING_BSSL_INCLUDE_PATH: ${{ github.workspace }}/lib/boringssl/include - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: bindings-x86_64-unknown-linux-musl + name: bindings-${{ matrix.settings.target }} path: bindings/node/*.node if-no-files-found: error test: name: Test bindings - runs-on: ubuntu-latest + runs-on: macos-14 steps: - uses: actions/checkout@v4 @@ -209,11 +116,6 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable - - name: Install build tools - run: | - sudo apt-get update - sudo apt-get install -y cmake clang libclang-dev - - name: Install dependencies run: | cd bindings/node @@ -223,6 +125,11 @@ jobs: run: | cd bindings/node npm run build:debug + env: + MACOSX_DEPLOYMENT_TARGET: '10.13' + # Use prebuilt BoringSSL from repo + BORING_BSSL_PATH: ${{ github.workspace }}/lib/boringssl/aarch64-apple-darwin/build + BORING_BSSL_INCLUDE_PATH: ${{ github.workspace }}/lib/boringssl/include - name: Test run: | @@ -231,9 +138,9 @@ jobs: publish: name: Publish to npm - needs: [build, build-musl, test] - runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/tags/') + needs: [build, test] + runs-on: macos-14 + if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' permissions: contents: write id-token: write @@ -246,20 +153,23 @@ jobs: node-version: 20 registry-url: 'https://registry.npmjs.org' + - name: Install dependencies + run: | + cd bindings/node + npm install + - name: Download all artifacts uses: actions/download-artifact@v4 with: path: bindings/node/artifacts pattern: bindings-* - - name: Move artifacts + - name: Stage native packages run: | cd bindings/node - mkdir -p npm - for dir in artifacts/bindings-*/; do - cp "${dir}"*.node npm/ 2>/dev/null || true - done - ls -la npm/ + npm run create:npm-dirs + npm run artifacts + find npm -maxdepth 2 -type f | sort - name: Publish run: | @@ -267,3 +177,4 @@ jobs: npm publish --access public --provenance env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/python-release.yml b/.github/workflows/python-release.yml index 38d7dd17..ac335309 100644 --- a/.github/workflows/python-release.yml +++ b/.github/workflows/python-release.yml @@ -13,80 +13,6 @@ permissions: contents: read jobs: - linux: - runs-on: ubuntu-latest - strategy: - matrix: - target: [x86_64, aarch64] - steps: - - uses: actions/checkout@v4 - # QEMU required for aarch64 builds on x86_64 runners - - name: Setup QEMU - if: matrix.target == 'aarch64' - uses: docker/setup-qemu-action@v3 - - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.target }} - args: --release --out dist -m bindings/python/Cargo.toml - manylinux: manylinux_2_28 - before-script-linux: | - # Install cmake and clang for BoringSSL (bindgen needs libclang >= 5.0) - # manylinux_2_28 uses AlmaLinux 8 with dnf - # Also install perl which BoringSSL's build system requires - dnf install -y cmake clang clang-devel llvm-devel perl-IPC-Cmd - - name: Upload wheels - uses: actions/upload-artifact@v4 - with: - name: wheels-linux-${{ matrix.target }} - path: dist/*.whl - - musllinux: - runs-on: ubuntu-latest - strategy: - matrix: - target: [x86_64, aarch64] - steps: - - uses: actions/checkout@v4 - # QEMU required for aarch64 builds on x86_64 runners - - name: Setup QEMU - if: matrix.target == 'aarch64' - uses: docker/setup-qemu-action@v3 - - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.target }} - args: --release --out dist -m bindings/python/Cargo.toml - manylinux: musllinux_1_2 - before-script-linux: | - # Install cmake and clang for BoringSSL (bindgen needs libclang >= 5.0) - # Also install perl and go which BoringSSL's build system requires - apk add --no-cache cmake clang-dev clang-static llvm-dev musl-dev linux-headers perl go - - name: Upload wheels - uses: actions/upload-artifact@v4 - with: - name: wheels-musllinux-${{ matrix.target }} - path: dist/*.whl - - windows: - runs-on: windows-latest - strategy: - matrix: - target: [x64, x86] - steps: - - uses: actions/checkout@v4 - - name: Install build tools - run: | - choco install cmake nasm -y - echo "C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.target }} - args: --release --out dist -m bindings/python/Cargo.toml - - name: Upload wheels - uses: actions/upload-artifact@v4 - with: - name: wheels-windows-${{ matrix.target }} - path: dist/*.whl - macos: runs-on: macos-14 strategy: @@ -98,6 +24,10 @@ jobs: with: target: ${{ matrix.target }} args: --release --out dist -m bindings/python/Cargo.toml + env: + # Use prebuilt BoringSSL from repo + BORING_BSSL_PATH: ${{ github.workspace }}/lib/boringssl/${{ matrix.target }}/build + BORING_BSSL_INCLUDE_PATH: ${{ github.workspace }}/lib/boringssl/include - name: Upload wheels uses: actions/upload-artifact@v4 with: @@ -105,7 +35,7 @@ jobs: path: dist/*.whl sdist: - runs-on: ubuntu-latest + runs-on: macos-14 steps: - uses: actions/checkout@v4 - uses: PyO3/maturin-action@v1 @@ -119,7 +49,7 @@ jobs: path: dist/*.tar.gz test: - runs-on: ubuntu-latest + runs-on: macos-14 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -127,8 +57,8 @@ jobs: python-version: '3.11' - name: Install system dependencies run: | - sudo apt-get update - sudo apt-get install -y cmake clang libclang-dev + brew update + brew install cmake # maturin develop requires a virtualenv - create one explicitly - name: Create virtualenv and install deps run: | @@ -140,6 +70,10 @@ jobs: run: | . .venv/bin/activate maturin develop --release -m bindings/python/Cargo.toml + env: + # Use prebuilt BoringSSL from repo + BORING_BSSL_PATH: ${{ github.workspace }}/lib/boringssl/aarch64-apple-darwin/build + BORING_BSSL_INCLUDE_PATH: ${{ github.workspace }}/lib/boringssl/include - name: Run tests run: | . .venv/bin/activate @@ -149,8 +83,8 @@ jobs: release: name: Release runs-on: ubuntu-latest - needs: [linux, musllinux, windows, macos, sdist] - if: startsWith(github.ref, 'refs/tags/') + needs: [macos, sdist] + if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' permissions: id-token: write steps: @@ -166,3 +100,5 @@ jobs: - uses: pypa/gh-action-pypi-publish@release/v1 with: skip-existing: true + # Falls back to token if Trusted Publishing not configured + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.gitignore b/.gitignore index aba5b94f..825e5d9b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,13 @@ # Build artifacts target/ - - - - - - - - - +.boringssl-build/ +.boringssl-src/ + +# Agent files +CLAUDE.md +AGENTS.md +GEMINI.md +COPILOT.md +CURSOR.md +.worktrees/ +.omc/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fc43733..cd87d83e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [2.1.3] - 2026-04-24 + +### Fixed +- **Node.js npm packaging**: Switched the `specters` package to a platform-aware native binding layout. The root package now loads the matching optional native package instead of depending on a single bundled `.node` binary. The 2.1.3 npm packages support `darwin-arm64`, `darwin-x64`, `linux-arm64-gnu`, and `linux-x64-gnu`. +- **Node.js release workflow**: Restored and updated the Node release workflow so GitHub Actions builds supported native targets, stages artifacts into per-platform npm packages, and publishes the root package with matching optional dependencies. `linux-x64-musl` is not published in this release because the current prebuilt musl BoringSSL archive cannot link into a Node addon. +- **Version metadata**: Aligned Node binding package metadata with the current Specter release line. + +## [2.1.2] - 2026-03-30 + +### Added +- **Chrome 143-146 fingerprint profiles**: Added browser fingerprint support for Chrome 143, 144, 145, and 146 (current stable). Each version has correct Sec-Ch-Ua brand strings derived from the Chromium GREASE algorithm, version-specific User-Agent strings, and full header presets (navigation, AJAX, form). +- **Shared TLS constants**: TLS cipher suites, signature algorithms, curves, and extensions are identical across Chrome 142-146 and now use shared `CHROME_*` constants with backwards-compatible `CHROME_142_*` aliases. +- **`TlsFingerprint::chrome()` constructor**: Unified constructor for Chrome TLS fingerprints, with version-specific aliases (`chrome_143()` through `chrome_146()`). +- **Chrome version test suite**: Comprehensive tests validating Sec-Ch-Ua brand strings, UA version strings, TLS/HTTP2 identity, and header preset completeness for all Chrome versions. +- **Node.js and Python bindings**: `Chrome143`, `Chrome144`, `Chrome145`, `Chrome146` variants added to `FingerprintProfile` enum in both bindings. + +## [2.0.0] - 2026-02-05 + +### Added +- **Rust API**: Reqwest-like request builders with `Request`, `Body`, `Headers`, `RedirectPolicy`, and `IntoUrl`. +- **Response helpers**: Convenience accessors for status, headers, and body. + +### Changed +- **BREAKING**: Rust client API is now reqwest-like; request builder usage replaces prior direct request patterns. +- **BREAKING**: URL arguments now use `IntoUrl` (e.g., `&str` or `Url`), not `&String`. +- **Bindings**: Node and Python APIs updated to match the new request builder flow. + ## [1.3.0] - 2026-01-31 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 521ca8ba..b532d6f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,9 +110,9 @@ dependencies = [ [[package]] name = "boring" -version = "4.19.0" +version = "4.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbe9eda68fc7fbfb395aace52dfc37075928536ec2f149abce54dbd40e38d5" +checksum = "a732fa30cc654efcca7d4b39cc0e0b0a22df43a188fa8221ea9a24ddca718caf" dependencies = [ "bitflags", "boring-sys", @@ -123,11 +123,10 @@ dependencies = [ [[package]] name = "boring-sys" -version = "4.19.0" +version = "4.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c9f08dc17fab4192e5e6b0920e6c06eb9e3e4ab98b9cff00368dfe6d1e30c9" +checksum = "f922afb52d05239f8d4042ca1df15da9d340c2b58bfb5b8daf15acbf8d6e195e" dependencies = [ - "autocfg", "bindgen", "cmake", "fs_extra", @@ -228,15 +227,6 @@ dependencies = [ "cc", ] -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -281,22 +271,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ctor" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "debug_panic" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9377eb110cece2e9431deb8d7d2ec8c116510b896741f9f2bf02b352147aa2a6" - [[package]] name = "deranged" version = "0.5.5" @@ -413,95 +387,12 @@ dependencies = [ "winapi", ] -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -541,12 +432,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - [[package]] name = "hex" version = "0.4.3" @@ -695,15 +580,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "indoc" -version = "2.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" -dependencies = [ - "rustversion", -] - [[package]] name = "intrusive-collections" version = "0.9.7" @@ -839,64 +715,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "napi" -version = "2.16.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55740c4ae1d8696773c78fdafd5d0e5fe9bc9f1b071c7ba493ba5c413a9184f3" -dependencies = [ - "bitflags", - "ctor", - "napi-derive", - "napi-sys", - "once_cell", - "tokio", -] - -[[package]] -name = "napi-build" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d376940fd5b723c6893cd1ee3f33abbfd86acb1cd1ec079f3ab04a2a3bc4d3b1" - -[[package]] -name = "napi-derive" -version = "2.16.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cbe2585d8ac223f7d34f13701434b9d5f4eb9c332cccce8dee57ea18ab8ab0c" -dependencies = [ - "cfg-if", - "convert_case", - "napi-derive-backend", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "napi-derive-backend" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1639aaa9eeb76e91c6ae66da8ce3e89e921cd3885e99ec85f4abacae72fc91bf" -dependencies = [ - "convert_case", - "once_cell", - "proc-macro2", - "quote", - "regex", - "semver", - "syn", -] - -[[package]] -name = "napi-sys" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3" -dependencies = [ - "libloading", -] - [[package]] name = "nom" version = "7.1.3" @@ -982,24 +800,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "portable-atomic" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" - [[package]] name = "potential_utf" version = "0.1.4" @@ -1039,91 +845,14 @@ version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" -[[package]] -name = "pyo3" -version = "0.23.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7778bffd85cf38175ac1f545509665d0b9b92a198ca7941f131f85f7a4f9a872" -dependencies = [ - "cfg-if", - "indoc", - "libc", - "memoffset", - "once_cell", - "portable-atomic", - "pyo3-build-config", - "pyo3-ffi", - "pyo3-macros", - "unindent", -] - -[[package]] -name = "pyo3-async-runtimes" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977dc837525cfd22919ba6a831413854beb7c99a256c03bf8624ad707e45810e" -dependencies = [ - "futures", - "once_cell", - "pin-project-lite", - "pyo3", - "tokio", -] - -[[package]] -name = "pyo3-build-config" -version = "0.23.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f6cbe86ef3bf18998d9df6e0f3fc1050a8c5efa409bf712e661a4366e010fb" -dependencies = [ - "once_cell", - "target-lexicon", -] - -[[package]] -name = "pyo3-ffi" -version = "0.23.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f1b4c431c0bb1c8fb0a338709859eed0d030ff6daa34368d3b152a63dfdd8d" -dependencies = [ - "libc", - "pyo3-build-config", -] - -[[package]] -name = "pyo3-macros" -version = "0.23.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc2201328f63c4710f68abdf653c89d8dbc2858b88c5d88b0ff38a75288a9da" -dependencies = [ - "proc-macro2", - "pyo3-macros-backend", - "quote", - "syn", -] - -[[package]] -name = "pyo3-macros-backend" -version = "0.23.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca6726ad0f3da9c9de093d6f116a93c1a38e417ed73bf138472cf4064f72028" -dependencies = [ - "heck", - "proc-macro2", - "pyo3-build-config", - "quote", - "syn", -] - [[package]] name = "quiche" -version = "0.24.6" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187c95c7080b7e9e0202b428acdd24f97eaa9cc65e023673b307d5f171e17a7a" +checksum = "ba053386c3a3b16441cb8a34574f91a9178fd3d813c0639514fcd8e4f274a44b" dependencies = [ "boring", "cmake", - "debug_panic", "either", "enum_dispatch", "foreign-types-shared", @@ -1279,12 +1008,6 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" - [[package]] name = "serde" version = "1.0.228" @@ -1328,6 +1051,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha2" version = "0.10.9" @@ -1383,8 +1118,8 @@ dependencies = [ ] [[package]] -name = "specter" -version = "1.3.0" +name = "specters" +version = "2.1.3" dependencies = [ "base64", "boring", @@ -1403,6 +1138,7 @@ dependencies = [ "rustls-native-certs", "serde", "serde_json", + "serde_urlencoded", "sha2", "socket2", "thiserror", @@ -1415,32 +1151,6 @@ dependencies = [ "zstd", ] -[[package]] -name = "specter-node" -version = "1.3.0" -dependencies = [ - "bytes", - "http", - "napi", - "napi-build", - "napi-derive", - "serde_json", - "specter", - "tokio", -] - -[[package]] -name = "specter-python" -version = "1.3.0" -dependencies = [ - "bytes", - "http", - "pyo3", - "pyo3-async-runtimes", - "specter", - "tokio", -] - [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -1469,12 +1179,6 @@ dependencies = [ "syn", ] -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - [[package]] name = "thiserror" version = "2.0.17" @@ -1667,18 +1371,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unindent" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" - [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 545f5f0d..2ac046bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "specter" -version = "1.3.0" +name = "specters" +version = "2.1.3" edition = "2021" license = "MIT" description = "HTTP client with full TLS, HTTP/2, and HTTP/3 fingerprint control" @@ -9,6 +9,18 @@ keywords = ["http", "http3", "fingerprint", "tls", "boringssl"] categories = ["network-programming", "web-programming::http-client"] authors = ["Jared Boynton"] readme = "README.md" +exclude = [ + "lib/boringssl/", + "bindings/", + "scripts/", + ".github/", + ".cargo/", + "examples/", + "justfile", +] + +[lib] +name = "specter" [dependencies] # TLS with BoringSSL @@ -45,6 +57,7 @@ chrono = { version = "0.4", features = ["serde"] } sha2 = "0.10" serde = { version = "1", features = ["derive"] } serde_json = "1" +serde_urlencoded = "0.7" getrandom = "0.3" psl = "2" socket2 = { version = "0.6", features = ["all"] } @@ -56,33 +69,3 @@ tokio-test = "0.4" tracing-subscriber = { version = "0.3", features = ["env-filter"] } hex = "0.4" rcgen = "0.14.5" - -[workspace] -members = [".", "bindings/python", "bindings/node"] -resolver = "2" - -# Note: Windows-specific crates (windows-sys, windows-targets, etc.) appear in Cargo.lock -# as transitive dependencies from tokio, quiche, etc., but they are platform-specific -# and will only be compiled when building for Windows targets. On macOS/Linux, they -# are automatically excluded from the build. - -# Build profiles optimized for M4 Max (16 cores, 128GB RAM) -[profile.dev] -# Development: fast compilation, minimal optimization -opt-level = 0 -debug = true -incremental = true -codegen-units = 16 # Parallel codegen for faster builds on 16-core machine - -[profile.release] -# Release: maximum optimization with reasonable compile time -opt-level = 3 -lto = "thin" # Thin LTO balances optimization and compile time -codegen-units = 1 # Single unit for better optimization -debug = false -panic = "abort" # Smaller binary size - -[profile.bench] -# Benchmark profile: same as release but with debug symbols for profiling -inherits = "release" -debug = true diff --git a/README.md b/README.md index 1338ade4..69748643 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ # Specter -HTTP client that accurately replicates Chrome's TLS and HTTP/2 behavior, letting you automate browser workflows programmatically. +HTTP client that accurately replicates Chrome's TLS and HTTP/2 behavior, letting you automate browser workflows programmatically. Supports SOCKS5 and HTTP CONNECT proxies with full fingerprint preservation across HTTP/1.1, HTTP/2, and HTTP/3 (QUIC). ## What This Is -Specter implements HTTP/1.1, HTTP/2, and HTTP/3 with the same protocol fingerprints as Chrome. It's written in Rust with a custom HTTP/2 implementation built from RFC 9113 (we don't use hyper or the h2 crate). TLS uses BoringSSL - Chrome's actual TLS library. When you make requests with Specter, fingerprinting systems see the same signatures they'd see from Chrome 142. Validated against ScrapFly, Browserleaks, and tls.peet.ws. +Specter implements HTTP/1.1, HTTP/2, and HTTP/3 with the same protocol fingerprints as Chrome. It's written in Rust with a custom HTTP/2 implementation built from RFC 9113 (we don't use hyper or the h2 crate). TLS uses BoringSSL - Chrome's actual TLS library. When you make requests with Specter, fingerprinting systems see the same signatures they'd see from a real Chrome browser. Validated against ScrapFly, Browserleaks, and tls.peet.ws. + +Supported Chrome fingerprints: **142, 143, 144, 145, 146** (current stable). Firefox 133 also supported. ```toml [dependencies] @@ -21,14 +23,14 @@ use specter::{Client, FingerprintProfile}; #[tokio::main] async fn main() -> Result<(), specter::Error> { let client = Client::builder() - .fingerprint(FingerprintProfile::Chrome142) + .fingerprint(FingerprintProfile::Chrome146) .build()?; let response = client.get("https://example.com") .send() .await?; - println!("Status: {}", response.status); + println!("Status: {}", response.status()); println!("Body: {}", response.text()?); Ok(()) @@ -56,7 +58,7 @@ use specter::transport::h2::PseudoHeaderOrder; use std::time::Duration; let client = Client::builder() - .fingerprint(FingerprintProfile::Chrome142) + .fingerprint(FingerprintProfile::Chrome146) .prefer_http2(true) // advertise h2 first and reuse pooled connections .timeout(Duration::from_secs(30)) .http2_settings(Http2Settings::default()) @@ -65,24 +67,90 @@ let client = Client::builder() .build()?; ``` -- `fingerprint(FingerprintProfile::Chrome142)` selects the TLS and HTTP/2 fingerprints that match shipping Chrome 142. +- `fingerprint(FingerprintProfile::Chrome146)` selects the TLS and HTTP/2 fingerprints that match shipping Chrome 146. Other versions available: `Chrome142`, `Chrome143`, `Chrome144`, `Chrome145`. - `prefer_http2(true)` keeps HTTP/1.1 available through ALPN but defaults to pooled HTTP/2. - `timeout(...)` adds a global request timeout enforced across all transports. - `http2_settings(...)` / `pseudo_order(...)` let you override SETTINGS frames and pseudo header ordering when you need to mimic a different browser or experiment with fingerprints. - `h3_upgrade(false)` disables Alt-Svc based HTTP/3 upgrades if you want deterministic TCP-only behavior. +- `proxy(ProxyConfig::socks5("127.0.0.1", 1080))` routes all traffic through a SOCKS5 proxy. HTTP/3 uses UDP ASSOCIATE; H1/H2 use TCP CONNECT. +- `proxy(ProxyConfig::http_connect("proxy.example.com", 8080))` routes H1/H2 traffic through an HTTP CONNECT tunnel. ### Redirects, retries, and cookies stay under your control -Specter never follows redirects or stores cookies automatically. That is intentional so you can replay the exact browser flow the target expects. Use `CookieJar` plus the header helpers to implement whatever policy you need: +Specter never follows redirects or stores cookies automatically by default. That is intentional so you can replay the exact browser flow the target expects. You can opt in: + +```rust +use specter::RedirectPolicy; + +let client = Client::builder() + .redirect_policy(RedirectPolicy::Limited(10)) + .cookie_store(true) + .build()?; +``` + +### Proxy support + +Route all traffic through SOCKS5 or HTTP CONNECT proxies. TLS fingerprints are fully preserved because the TLS handshake happens *inside* the proxy tunnel. + +```rust +use specter::{Client, FingerprintProfile, ProxyConfig}; + +// SOCKS5 proxy (supports H1, H2, and H3 via UDP ASSOCIATE) +let client = Client::builder() + .fingerprint(FingerprintProfile::Chrome146) + .proxy(ProxyConfig::socks5("127.0.0.1", 1080)) + .build()?; + +// SOCKS5 with username/password auth +let client = Client::builder() + .fingerprint(FingerprintProfile::Chrome146) + .proxy(ProxyConfig::socks5_with_auth("proxy.example.com", 1080, "user", "pass")) + .build()?; + +// HTTP CONNECT proxy (H1/H2 only — no UDP path for H3) +let client = Client::builder() + .fingerprint(FingerprintProfile::Chrome146) + .proxy(ProxyConfig::http_connect("proxy.example.com", 8080)) + .build()?; + +// HTTP CONNECT with auth +let client = Client::builder() + .fingerprint(FingerprintProfile::Chrome146) + .proxy(ProxyConfig::http_connect_with_auth("proxy.example.com", 8080, "user", "pass")) + .build()?; +``` + +Once configured, every request goes through the proxy — no per-request setup needed: + +```rust +// All of these use the proxy automatically +let resp = client.get("https://example.com").send().await?; +let resp = client.get("https://api.example.com/data") + .version(HttpVersion::Http3) // SOCKS5: tunneled via UDP ASSOCIATE + .send().await?; +``` + +**How it works:** + +| Proxy type | HTTP/1.1 | HTTP/2 | HTTP/3 (QUIC) | +|------------|----------|--------|----------------| +| SOCKS5 | TCP CONNECT | TCP CONNECT | UDP ASSOCIATE | +| HTTP CONNECT | CONNECT tunnel | CONNECT tunnel | Falls back to H2 | + +- DNS is always resolved on the proxy side (SOCKS5 domain address type) to prevent DNS leaks. +- TLS fingerprints are not affected by the proxy because the TLS handshake happens after the tunnel is established. +- Connection pooling is proxy-aware: connections through different proxies are never mixed. + +Use `CookieJar` plus the header helpers to implement whatever policy you need: ```rust use specter::{Client, CookieJar, FingerprintProfile, HttpVersion, Result}; -use specter::headers::{chrome_142_headers, with_cookies}; +use specter::headers::{chrome_146_headers, with_cookies}; use url::Url; async fn fetch_with_redirects() -> Result<()> { let client = Client::builder() - .fingerprint(FingerprintProfile::Chrome142) + .fingerprint(FingerprintProfile::Chrome146) .prefer_http2(true) .build()?; @@ -90,7 +158,7 @@ async fn fetch_with_redirects() -> Result<()> { let mut current = Url::parse("https://example.com/login").expect("valid URL"); for _ in 0..5 { - let headers = with_cookies(chrome_142_headers(), current.as_str(), &jar); + let headers = with_cookies(chrome_146_headers(), current.as_str(), &jar); let response = client.get(current.as_str()) .headers(headers) @@ -98,7 +166,7 @@ async fn fetch_with_redirects() -> Result<()> { .send() .await?; - jar.store_from_headers(&response.headers, current.as_str()); + jar.store_from_headers(response.headers(), current.as_str()); if response.is_redirect() { if let Some(location) = response.redirect_url() { @@ -107,7 +175,7 @@ async fn fetch_with_redirects() -> Result<()> { } } - println!("Reached {} with status {}", current, response.status); + println!("Reached {} with status {}", current, response.status()); println!("Body: {}", response.text()?); break; } @@ -116,7 +184,7 @@ async fn fetch_with_redirects() -> Result<()> { } ``` -Use `response.is_redirect()`/`response.redirect_url()` to drive your redirect engine, and `response.effective_url` if you need to report the final hop back to upstream logic. +Use `response.is_redirect()`/`response.redirect_url()` to drive your redirect engine, and `response.url()` if you need to report the final hop back to upstream logic. ### Persist cookies between runs @@ -131,7 +199,7 @@ jar.save_to_file("cookies.txt").await?; ### Header presets & origin helpers -`specter::headers` ships Chrome 142 navigation, AJAX, and form presets plus helpers such as `with_origin`, `with_referer`, `with_cookies`, and `headers_to_owned`. Start from those presets, then add per-request headers so you never accidentally send forbidden connection-specific headers on HTTP/2/3. +`specter::headers` ships Chrome 142-146 navigation, AJAX, and form presets plus helpers such as `with_origin`, `with_referer`, `with_cookies`, and `headers_to_owned`. Start from those presets, then add per-request headers so you never accidentally send forbidden connection-specific headers on HTTP/2/3. ### Response helpers @@ -149,9 +217,9 @@ jar.save_to_file("cookies.txt").await?; - All headers properly lowercased per RFC 7540/9113 - True multiplexing (concurrent requests on single connection, respecting `MAX_CONCURRENT_STREAMS`) -**HTTP/3** - QUIC transport via quiche with TLS 1.3 fingerprinting. +**HTTP/3** - QUIC transport via quiche with TLS 1.3 fingerprinting. Works through SOCKS5 proxies via RFC 1928 UDP ASSOCIATE. -**TLS** - BoringSSL configured with Chrome 142 cipher suites, curves, and signature algorithms. BoringSSL does its own extension randomization (which matches Chrome's behavior for TLS 1.3). +**TLS** - BoringSSL configured with Chrome cipher suites, curves, and signature algorithms. The TLS configuration is identical across Chrome 142-146. BoringSSL does its own extension randomization (which matches Chrome's behavior for TLS 1.3). **Control** - Nothing happens automatically. You manage redirects, cookies, headers, and retries explicitly (see the examples above for recommended patterns). @@ -169,6 +237,9 @@ Local/CI checks: - `cargo run --example fingerprint_validation` hits ScrapFly, BrowserLeaks, tls.peet.ws, and Cloudflare to confirm TLS/HTTP/2/HTTP/3 fingerprints. - `cargo run --example protocol_test -- --verbose` walks through HTTP/1.1 preference, HTTP/2 pooling, HTTP/3 only, and connection header filtering. Pass `--target example.com` to test a custom origin. - `cargo clippy -p specter -- -D warnings` stays clean to make CI fail-fast on regressions. +- `cargo run --example proxy_test -- --socks5 host:port --user USER --pass PASS` verifies proxy tunneling against IP detection APIs. +- `cargo run --example proxy_browserleaks -- --socks5 host:port --user USER --pass PASS` checks TLS/H2 fingerprints through a SOCKS5 proxy. +- `cargo run --example proxy_h3_test -- --socks5 host:port --user USER --pass PASS` tests HTTP/3 via SOCKS5 UDP ASSOCIATE. ## Development diff --git a/bindings/node/Cargo.lock b/bindings/node/Cargo.lock new file mode 100644 index 00000000..6f2d6421 --- /dev/null +++ b/bindings/node/Cargo.lock @@ -0,0 +1,1637 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "boring" +version = "4.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a732fa30cc654efcca7d4b39cc0e0b0a22df43a188fa8221ea9a24ddca718caf" +dependencies = [ + "bitflags", + "boring-sys", + "foreign-types", + "libc", + "openssl-macros", +] + +[[package]] +name = "boring-sys" +version = "4.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f922afb52d05239f8d4042ca1df15da9d340c2b58bfb5b8daf15acbf8d6e195e" +dependencies = [ + "bindgen", + "cmake", + "fs_extra", + "fslock", +] + +[[package]] +name = "brotli" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cc" +version = "1.2.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "fslock" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "intrusive-collections" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86" +dependencies = [ + "memoffset", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "napi" +version = "2.16.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55740c4ae1d8696773c78fdafd5d0e5fe9bc9f1b071c7ba493ba5c413a9184f3" +dependencies = [ + "bitflags", + "ctor", + "napi-derive", + "napi-sys", + "once_cell", + "tokio", +] + +[[package]] +name = "napi-build" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d376940fd5b723c6893cd1ee3f33abbfd86acb1cd1ec079f3ab04a2a3bc4d3b1" + +[[package]] +name = "napi-derive" +version = "2.16.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cbe2585d8ac223f7d34f13701434b9d5f4eb9c332cccce8dee57ea18ab8ab0c" +dependencies = [ + "cfg-if", + "convert_case", + "napi-derive-backend", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "napi-derive-backend" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1639aaa9eeb76e91c6ae66da8ce3e89e921cd3885e99ec85f4abacae72fc91bf" +dependencies = [ + "convert_case", + "once_cell", + "proc-macro2", + "quote", + "regex", + "semver", + "syn", +] + +[[package]] +name = "napi-sys" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3" +dependencies = [ + "libloading", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "octets" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8311fa8ab7a57759b4ff1f851a3048d9ef0effaa0130726426b742d26d8a88e7" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psl" +version = "2.1.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "868e3200a2474f99d0ea576a7c76aabda7cdcc795cc27f2d93f30ab79867820d" +dependencies = [ + "psl-types", +] + +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "quiche" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba053386c3a3b16441cb8a34574f91a9178fd3d813c0639514fcd8e4f274a44b" +dependencies = [ + "boring", + "cmake", + "either", + "enum_dispatch", + "foreign-types-shared", + "intrusive-collections", + "libc", + "libm", + "log", + "octets", + "slab", + "smallvec", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "specter-node" +version = "2.1.3" +dependencies = [ + "bytes", + "http", + "napi", + "napi-build", + "napi-derive", + "serde_json", + "specters", + "tokio", +] + +[[package]] +name = "specters" +version = "2.1.3" +dependencies = [ + "base64", + "boring", + "boring-sys", + "brotli", + "bytes", + "chrono", + "flate2", + "getrandom", + "hex", + "http", + "httparse", + "psl", + "quiche", + "rustls-native-certs", + "serde", + "serde_json", + "serde_urlencoded", + "sha2", + "socket2", + "thiserror", + "tokio", + "tokio-boring", + "tracing", + "url", + "zstd", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.52.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-boring" +version = "4.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a5b1722d42be029aa3ef0b0f4dd4554b44409eb2af5da60159008f936525be3" +dependencies = [ + "boring", + "boring-sys", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/bindings/node/Cargo.toml b/bindings/node/Cargo.toml index 7dba07cf..4a2235fd 100644 --- a/bindings/node/Cargo.toml +++ b/bindings/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "specter-node" -version = "1.3.0" +version = "2.1.3" edition = "2021" license = "MIT" description = "Node.js bindings for Specter HTTP client" @@ -10,7 +10,7 @@ repository = "https://github.com/jaredboynton/specter" crate-type = ["cdylib"] [dependencies] -specter = { path = "../.." } +specter = { package = "specters", path = "../.." } napi = { version = "2", features = ["async", "tokio_rt", "napi9"] } napi-derive = "2" tokio = { version = "1", features = ["rt-multi-thread"] } diff --git a/bindings/node/README.md b/bindings/node/README.md index 9f356860..aaa0e76f 100644 --- a/bindings/node/README.md +++ b/bindings/node/README.md @@ -40,7 +40,12 @@ main(); ```javascript const { Client, FingerprintProfile } = require('@specter/client'); -// Impersonate Chrome 142 +// Impersonate Chrome 146 (current stable) +const client = Client.builder() + .fingerprint(FingerprintProfile.Chrome146) + .build(); + +// Or pick a specific version (142, 143, 144, 145, 146) const client = Client.builder() .fingerprint(FingerprintProfile.Chrome142) .build(); diff --git a/bindings/node/index.js b/bindings/node/index.js index 971b6796..dbef5eac 100644 --- a/bindings/node/index.js +++ b/bindings/node/index.js @@ -3,120 +3,129 @@ * * A high-performance async HTTP client with full TLS, HTTP/2, and HTTP/3 * fingerprint control for browser impersonation. - * - * @example - * const { clientBuilder, FingerprintProfile } = require('@specter/client'); - * - * async function main() { - * // Create a client with default settings - * const client = clientBuilder().build(); - * - * // Simple GET request - * const response = await client.get('https://httpbin.org/get').send(); - * console.log(`Status: ${response.status}`); - * console.log(response.text()); - * - * // POST with JSON body - * const response2 = await client.post('https://api.example.com/data') - * .header('Authorization', 'Bearer token') - * .json(JSON.stringify({ name: 'test' })) - * .send(); - * console.log(JSON.parse(response2.json())); - * } - * - * main(); */ -const { loadBinding } = require('@napi-rs/wasm-runtime'); -const path = require('path'); - -// Try to load the native binding -let nativeBinding; - -// Platform to binary name mapping based on napi-rs naming convention -// Format: specter.{os}-{arch}[-{libc}].node -const platformBinaries = { - 'darwin-arm64': 'specter.darwin-arm64.node', - 'darwin-x64': 'specter.darwin-x64.node', - 'linux-arm64-gnu': 'specter.linux-arm64-gnu.node', - 'linux-x64-gnu': 'specter.linux-x64-gnu.node', - 'linux-x64-musl': 'specter.linux-x64-musl.node', - 'win32-x64-msvc': 'specter.win32-x64-msvc.node', +const { execSync } = require('node:child_process'); +const { readFileSync } = require('node:fs'); + +const PACKAGE_VERSION = '2.1.3'; + +const targets = { + 'darwin-x64': { + local: './specter.darwin-x64.node', + package: 'specters-darwin-x64', + }, + 'darwin-arm64': { + local: './specter.darwin-arm64.node', + package: 'specters-darwin-arm64', + }, + 'linux-x64-gnu': { + local: './specter.linux-x64-gnu.node', + package: 'specters-linux-x64-gnu', + }, + 'linux-arm64-gnu': { + local: './specter.linux-arm64-gnu.node', + package: 'specters-linux-arm64-gnu', + }, }; -function getPlatformKey() { - const platform = process.platform; - const arch = process.arch; +function isMusl() { + if (process.platform !== 'linux') { + return false; + } - if (platform === 'darwin') { - return `darwin-${arch}`; + const report = typeof process.report?.getReport === 'function' + ? process.report.getReport() + : null; + + if (report?.header?.glibcVersionRuntime) { + return false; } - if (platform === 'win32') { - return `win32-${arch}-msvc`; + + if (Array.isArray(report?.sharedObjects)) { + return report.sharedObjects.some((file) => file.includes('libc.musl-') || file.includes('ld-musl-')); } - if (platform === 'linux') { - // Check if we're on musl by looking at the libc - const isMusl = (() => { - try { - const { execSync } = require('child_process'); - return execSync('ldd --version 2>&1').toString().includes('musl'); - } catch { - return false; - } - })(); - return `linux-${arch}-${isMusl ? 'musl' : 'gnu'}`; + + try { + return readFileSync('/usr/bin/ldd', 'utf8').includes('musl'); + } catch { + try { + return execSync('ldd --version', { encoding: 'utf8' }).includes('musl'); + } catch { + return false; + } + } +} + +function targetKey() { + if (process.platform === 'darwin') { + return `darwin-${process.arch}`; + } + + if (process.platform === 'linux') { + return `linux-${process.arch}-${isMusl() ? 'musl' : 'gnu'}`; + } + + return `${process.platform}-${process.arch}`; +} + +function versionCheck(packageName) { + if (!process.env.NAPI_RS_ENFORCE_VERSION_CHECK || process.env.NAPI_RS_ENFORCE_VERSION_CHECK === '0') { + return; + } + + const packageVersion = require(`${packageName}/package.json`).version; + if (packageVersion !== PACKAGE_VERSION) { + throw new Error( + `Native binding package version mismatch for ${packageName}: expected ${PACKAGE_VERSION}, got ${packageVersion}. ` + + 'Reinstall dependencies to refresh optional native packages.' + ); } - return null; } function loadNativeBinding() { - // Try platform-specific binary first - const platformKey = getPlatformKey(); - if (platformKey && platformBinaries[platformKey]) { + const loadErrors = []; + + if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) { try { - nativeBinding = require(`./${platformBinaries[platformKey]}`); - return nativeBinding; - } catch (e) { - // Continue to fallback + return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH); + } catch (error) { + loadErrors.push(error); } } - // Try all known binaries - for (const binaryName of Object.values(platformBinaries)) { - try { - nativeBinding = require(`./${binaryName}`); - return nativeBinding; - } catch (e) { - // Continue to next platform - } + const key = targetKey(); + const target = targets[key]; + + if (!target) { + throw new Error( + `Unsupported Specter native target: ${key}. ` + + `Supported targets: ${Object.keys(targets).join(', ')}.` + ); } - // Try loading from build directory try { - nativeBinding = require('./specter.node'); - return nativeBinding; - } catch (e) { - // Fall through + return require(target.local); + } catch (error) { + loadErrors.push(error); } - // Try loading from target try { - nativeBinding = require('./build/Release/specter.node'); - return nativeBinding; - } catch (e) { - // Fall through + versionCheck(target.package); + return require(target.package); + } catch (error) { + loadErrors.push(error); } throw new Error( - `Failed to load native binding for Specter. ` + - `Please ensure you've built the native module with "npm run build".` + `Failed to load Specter native binding for ${key}. ` + + `Expected optional package "${target.package}" or local binary "${target.local}".\n` + + loadErrors.map((error) => `- ${error.message}`).join('\n') ); } -// Load the binding const binding = loadNativeBinding(); -// Export the native types module.exports.Client = binding.Client; module.exports.ClientBuilder = binding.ClientBuilder; module.exports.RequestBuilder = binding.RequestBuilder; diff --git a/bindings/node/npm/darwin-arm64/README.md b/bindings/node/npm/darwin-arm64/README.md new file mode 100644 index 00000000..ca1e8b2c --- /dev/null +++ b/bindings/node/npm/darwin-arm64/README.md @@ -0,0 +1,3 @@ +# `specters-darwin-arm64` + +This is the **aarch64-apple-darwin** binary for `specters` diff --git a/bindings/node/npm/darwin-arm64/package.json b/bindings/node/npm/darwin-arm64/package.json new file mode 100644 index 00000000..616dff64 --- /dev/null +++ b/bindings/node/npm/darwin-arm64/package.json @@ -0,0 +1,35 @@ +{ + "name": "specters-darwin-arm64", + "version": "2.1.3", + "cpu": [ + "arm64" + ], + "main": "specter.darwin-arm64.node", + "files": [ + "specter.darwin-arm64.node" + ], + "description": "Node.js bindings for Specter HTTP client with TLS/HTTP2/HTTP3 fingerprint control", + "keywords": [ + "http", + "http3", + "fingerprint", + "tls", + "client", + "async", + "native" + ], + "author": "Jared Boynton", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/jaredboynton/specter.git", + "directory": "bindings/node" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "os": [ + "darwin" + ] +} diff --git a/bindings/node/npm/darwin-x64/README.md b/bindings/node/npm/darwin-x64/README.md new file mode 100644 index 00000000..efaca0c6 --- /dev/null +++ b/bindings/node/npm/darwin-x64/README.md @@ -0,0 +1,3 @@ +# `specters-darwin-x64` + +This is the **x86_64-apple-darwin** binary for `specters` diff --git a/bindings/node/npm/darwin-x64/package.json b/bindings/node/npm/darwin-x64/package.json new file mode 100644 index 00000000..dc55f578 --- /dev/null +++ b/bindings/node/npm/darwin-x64/package.json @@ -0,0 +1,35 @@ +{ + "name": "specters-darwin-x64", + "version": "2.1.3", + "cpu": [ + "x64" + ], + "main": "specter.darwin-x64.node", + "files": [ + "specter.darwin-x64.node" + ], + "description": "Node.js bindings for Specter HTTP client with TLS/HTTP2/HTTP3 fingerprint control", + "keywords": [ + "http", + "http3", + "fingerprint", + "tls", + "client", + "async", + "native" + ], + "author": "Jared Boynton", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/jaredboynton/specter.git", + "directory": "bindings/node" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "os": [ + "darwin" + ] +} diff --git a/bindings/node/npm/linux-arm64-gnu/README.md b/bindings/node/npm/linux-arm64-gnu/README.md new file mode 100644 index 00000000..cc007848 --- /dev/null +++ b/bindings/node/npm/linux-arm64-gnu/README.md @@ -0,0 +1,3 @@ +# `specters-linux-arm64-gnu` + +This is the **aarch64-unknown-linux-gnu** binary for `specters` diff --git a/bindings/node/npm/linux-arm64-gnu/package.json b/bindings/node/npm/linux-arm64-gnu/package.json new file mode 100644 index 00000000..45694293 --- /dev/null +++ b/bindings/node/npm/linux-arm64-gnu/package.json @@ -0,0 +1,38 @@ +{ + "name": "specters-linux-arm64-gnu", + "version": "2.1.3", + "cpu": [ + "arm64" + ], + "main": "specter.linux-arm64-gnu.node", + "files": [ + "specter.linux-arm64-gnu.node" + ], + "description": "Node.js bindings for Specter HTTP client with TLS/HTTP2/HTTP3 fingerprint control", + "keywords": [ + "http", + "http3", + "fingerprint", + "tls", + "client", + "async", + "native" + ], + "author": "Jared Boynton", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/jaredboynton/specter.git", + "directory": "bindings/node" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "os": [ + "linux" + ], + "libc": [ + "glibc" + ] +} diff --git a/bindings/node/npm/linux-x64-gnu/README.md b/bindings/node/npm/linux-x64-gnu/README.md new file mode 100644 index 00000000..a1c3315c --- /dev/null +++ b/bindings/node/npm/linux-x64-gnu/README.md @@ -0,0 +1,3 @@ +# `specters-linux-x64-gnu` + +This is the **x86_64-unknown-linux-gnu** binary for `specters` diff --git a/bindings/node/npm/linux-x64-gnu/package.json b/bindings/node/npm/linux-x64-gnu/package.json new file mode 100644 index 00000000..74afd57a --- /dev/null +++ b/bindings/node/npm/linux-x64-gnu/package.json @@ -0,0 +1,38 @@ +{ + "name": "specters-linux-x64-gnu", + "version": "2.1.3", + "cpu": [ + "x64" + ], + "main": "specter.linux-x64-gnu.node", + "files": [ + "specter.linux-x64-gnu.node" + ], + "description": "Node.js bindings for Specter HTTP client with TLS/HTTP2/HTTP3 fingerprint control", + "keywords": [ + "http", + "http3", + "fingerprint", + "tls", + "client", + "async", + "native" + ], + "author": "Jared Boynton", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/jaredboynton/specter.git", + "directory": "bindings/node" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "os": [ + "linux" + ], + "libc": [ + "glibc" + ] +} diff --git a/bindings/node/package.json b/bindings/node/package.json index 98d97e1d..84710aaa 100644 --- a/bindings/node/package.json +++ b/bindings/node/package.json @@ -1,6 +1,6 @@ { - "name": "@specter/client", - "version": "1.3.0", + "name": "specters", + "version": "2.1.3", "description": "Node.js bindings for Specter HTTP client with TLS/HTTP2/HTTP3 fingerprint control", "main": "index.js", "types": "index.d.ts", @@ -10,24 +10,33 @@ "x86_64-apple-darwin", "aarch64-apple-darwin", "x86_64-unknown-linux-gnu", - "x86_64-unknown-linux-musl", "aarch64-unknown-linux-gnu" ] }, "files": [ "index.js", - "index.d.ts", - "*.node" + "index.d.ts" ], + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, "scripts": { "build": "napi build --platform --release --dts index.gen.d.ts", "build:debug": "napi build --platform", - "prepublishOnly": "napi prepublish -t npm", - "artifacts": "napi artifacts", + "create:npm-dirs": "napi create-npm-dirs", + "prepublishOnly": "napi prepublish -t npm --no-gh-release", + "artifacts": "napi artifacts --output-dir ./artifacts", "test": "jest" }, + "optionalDependencies": { + "specters-darwin-x64": "2.1.3", + "specters-darwin-arm64": "2.1.3", + "specters-linux-x64-gnu": "2.1.3", + "specters-linux-arm64-gnu": "2.1.3" + }, "devDependencies": { - "@napi-rs/cli": "^3.0.0-alpha", + "@napi-rs/cli": "^3.6.2", "jest": "^29.7.0" }, "keywords": [ diff --git a/bindings/node/src/lib.rs b/bindings/node/src/lib.rs index 7103b1e0..8cc02a17 100644 --- a/bindings/node/src/lib.rs +++ b/bindings/node/src/lib.rs @@ -54,6 +54,14 @@ pub struct CookieJar { pub enum FingerprintProfile { /// Chrome 142 on macOS Chrome142, + /// Chrome 143 on macOS + Chrome143, + /// Chrome 144 on macOS + Chrome144, + /// Chrome 145 on macOS + Chrome145, + /// Chrome 146 on macOS (current stable) + Chrome146, /// Firefox 133 on macOS Firefox133, /// No fingerprinting - use default TLS settings @@ -300,13 +308,13 @@ impl RequestBuilder { // Build the request using the appropriate method let mut req_builder = match method.as_str() { - "GET" => client.get(&url), - "POST" => client.post(&url), - "PUT" => client.put(&url), - "DELETE" => client.delete(&url), - "PATCH" => client.request(::http::Method::PATCH, &url), - "HEAD" => client.request(::http::Method::HEAD, &url), - "OPTIONS" => client.request(::http::Method::OPTIONS, &url), + "GET" => client.get(url.as_str()), + "POST" => client.post(url.as_str()), + "PUT" => client.put(url.as_str()), + "DELETE" => client.delete(url.as_str()), + "PATCH" => client.request(::http::Method::PATCH, url.as_str()), + "HEAD" => client.request(::http::Method::HEAD, url.as_str()), + "OPTIONS" => client.request(::http::Method::OPTIONS, url.as_str()), _ => { return Err(Error::new( Status::InvalidArg, @@ -339,6 +347,10 @@ impl ClientBuilder { if let Some(inner) = self.inner.take() { let rust_profile = match profile { FingerprintProfile::Chrome142 => RustFingerprintProfile::Chrome142, + FingerprintProfile::Chrome143 => RustFingerprintProfile::Chrome143, + FingerprintProfile::Chrome144 => RustFingerprintProfile::Chrome144, + FingerprintProfile::Chrome145 => RustFingerprintProfile::Chrome145, + FingerprintProfile::Chrome146 => RustFingerprintProfile::Chrome146, FingerprintProfile::Firefox133 => RustFingerprintProfile::Firefox133, FingerprintProfile::None => RustFingerprintProfile::None, }; @@ -474,24 +486,22 @@ impl Response { /// Get the HTTP status code. #[napi(getter)] pub fn status(&self) -> u16 { - self.inner.status + self.inner.status().as_u16() } /// Get the response headers as an object. #[napi(getter)] pub fn headers(&self) -> HashMap { let mut map = HashMap::new(); - for header in &self.inner.headers { - if let Some((key, value)) = header.split_once(':') { - let key = key.trim().to_string(); - let value = value.trim().to_string(); - // Handle multiple values for the same header by joining with comma - map.entry(key) - .and_modify(|v: &mut String| { - *v = format!("{}, {}", v, value); - }) - .or_insert(value); - } + for (key, value) in self.inner.headers().iter() { + let key = key.to_string(); + let value = value.to_string(); + // Handle multiple values for the same header by joining with comma + map.entry(key) + .and_modify(|v: &mut String| { + *v = format!("{}, {}", v, value); + }) + .or_insert(value); } map } @@ -500,13 +510,9 @@ impl Response { #[napi] pub fn headers_list(&self) -> Vec> { self.inner - .headers + .headers() .iter() - .filter_map(|header| { - header - .split_once(':') - .map(|(key, value)| vec![key.trim().to_string(), value.trim().to_string()]) - }) + .map(|(key, value)| vec![key.to_string(), value.to_string()]) .collect() } @@ -545,7 +551,7 @@ impl Response { /// Get the effective URL (after redirects). #[napi(getter)] pub fn effective_url(&self) -> Option { - self.inner.effective_url.clone() + self.inner.url().map(|url| url.to_string()) } /// Check if the response status is successful (2xx). diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 4c431431..16663eb2 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "specter-python" -version = "1.3.0" +version = "2.0.0" edition = "2021" license = "MIT" description = "Python bindings for Specter HTTP client" diff --git a/bindings/python/README.md b/bindings/python/README.md index 48b29fd3..a743ec22 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -40,7 +40,12 @@ asyncio.run(main()) ```python import specter -# Impersonate Chrome 142 +# Impersonate Chrome 146 (current stable) +client = (specter.Client.builder() + .fingerprint(specter.FingerprintProfile.Chrome146) + .build()) + +# Or pick a specific version (142, 143, 144, 145, 146) client = (specter.Client.builder() .fingerprint(specter.FingerprintProfile.Chrome142) .build()) diff --git a/bindings/python/README_PYPI.md b/bindings/python/README_PYPI.md new file mode 100644 index 00000000..bcfe7043 --- /dev/null +++ b/bindings/python/README_PYPI.md @@ -0,0 +1,71 @@ +# Specter + +Python bindings for the Specter HTTP client - an HTTP client that accurately replicates Chrome's TLS and HTTP/2 behavior. + +## Installation + +```bash +pip install specters +``` + +## Features + +- HTTP/1.1, HTTP/2, and HTTP/3 support +- Chrome 142-146 TLS fingerprint (BoringSSL) +- Chrome HTTP/2 fingerprint (SETTINGS, pseudo-header order, GREASE) +- Async/await interface +- Cookie jar with Netscape format support + +## Usage + +```python +import asyncio +from specter import Client, FingerprintProfile + +async def main(): + client = Client(fingerprint=FingerprintProfile.Chrome146) + + response = await client.get("https://example.com") + print(f"Status: {response.status}") + print(f"Body: {response.text()}") + +asyncio.run(main()) +``` + +### Force HTTP version + +```python +from specter import HttpVersion + +# HTTP/2 only +response = await client.get(url, version=HttpVersion.Http2) + +# HTTP/3 with fallback +response = await client.get(url, version=HttpVersion.Http3) +``` + +### Custom headers and cookies + +```python +from specter import CookieJar + +jar = CookieJar() +await jar.load_from_file("cookies.txt") + +response = await client.get(url, cookies=jar) +jar.store_from_headers(response.headers, url) + +await jar.save_to_file("cookies.txt") +``` + +## Validation + +Specter fingerprints are validated against: +- ScrapFly (tools.scrapfly.io) +- Browserleaks (tls.browserleaks.com) +- tls.peet.ws +- Cloudflare + +## License + +MIT diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index 0f8a66b4..c4941d97 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -3,10 +3,10 @@ requires = ["maturin>=1.8,<2.0"] build-backend = "maturin" [project] -name = "specter" -version = "1.3.0" +name = "specters" +version = "2.0.0" description = "Python bindings for Specter HTTP client with TLS/HTTP2/HTTP3 fingerprint control" -readme = "README.md" +readme = "README_PYPI.md" license = { text = "MIT" } requires-python = ">=3.10" classifiers = [ diff --git a/bindings/python/specter.pyi b/bindings/python/specter.pyi index d3da8e95..6029f429 100644 --- a/bindings/python/specter.pyi +++ b/bindings/python/specter.pyi @@ -34,7 +34,7 @@ class FingerprintProfile(Enum): """Browser fingerprint profiles for impersonation.""" Chrome142 = ... Firefox133 = ... - None = ... + NoFingerprint = ... class HttpVersion(Enum): """HTTP version preference.""" diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 73d5f0c9..822ccaaa 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -57,10 +57,19 @@ pub struct CookieJar { pub enum FingerprintProfile { /// Chrome 142 on macOS Chrome142, + /// Chrome 143 on macOS + Chrome143, + /// Chrome 144 on macOS + Chrome144, + /// Chrome 145 on macOS + Chrome145, + /// Chrome 146 on macOS (current stable) + Chrome146, /// Firefox 133 on macOS Firefox133, /// No fingerprinting - use default TLS settings - None, + /// Note: Named NoFingerprint instead of None because None is a reserved keyword in Python + NoFingerprint, } /// HTTP version preference. @@ -272,13 +281,13 @@ impl RequestBuilder { future_into_py(py, async move { // Build the request using the appropriate method let mut req_builder = match method.as_str() { - "GET" => client.get(&url), - "POST" => client.post(&url), - "PUT" => client.put(&url), - "DELETE" => client.delete(&url), - "PATCH" => client.request(::http::Method::PATCH, &url), - "HEAD" => client.request(::http::Method::HEAD, &url), - "OPTIONS" => client.request(::http::Method::OPTIONS, &url), + "GET" => client.get(url.as_str()), + "POST" => client.post(url.as_str()), + "PUT" => client.put(url.as_str()), + "DELETE" => client.delete(url.as_str()), + "PATCH" => client.request(::http::Method::PATCH, url.as_str()), + "HEAD" => client.request(::http::Method::HEAD, url.as_str()), + "OPTIONS" => client.request(::http::Method::OPTIONS, url.as_str()), _ => client.request( ::http::Method::from_bytes(method.as_bytes()).map_err(|e| { PyErr::new::(format!( @@ -286,7 +295,7 @@ impl RequestBuilder { e )) })?, - &url, + url.as_str(), ), }; @@ -318,8 +327,12 @@ impl ClientBuilder { fn fingerprint(&mut self, profile: FingerprintProfile) -> PyResult<()> { let rust_profile = match profile { FingerprintProfile::Chrome142 => RustFingerprintProfile::Chrome142, + FingerprintProfile::Chrome143 => RustFingerprintProfile::Chrome143, + FingerprintProfile::Chrome144 => RustFingerprintProfile::Chrome144, + FingerprintProfile::Chrome145 => RustFingerprintProfile::Chrome145, + FingerprintProfile::Chrome146 => RustFingerprintProfile::Chrome146, FingerprintProfile::Firefox133 => RustFingerprintProfile::Firefox133, - FingerprintProfile::None => RustFingerprintProfile::None, + FingerprintProfile::NoFingerprint => RustFingerprintProfile::None, }; // Since RustClientBuilder is not Clone, we need to take ownership // We use std::mem::replace to work around this @@ -432,24 +445,20 @@ impl Response { /// Get the HTTP status code. #[getter] fn status(&self) -> u16 { - self.inner.status + self.inner.status().as_u16() } /// Get the response headers as a dictionary. #[getter] fn headers<'py>(&self, py: Python<'py>) -> PyResult> { let dict = PyDict::new(py); - for header in &self.inner.headers { - if let Some((key, value)) = header.split_once(':') { - let key = key.trim(); - let value = value.trim(); - // Handle multiple values for the same header - if let Some(existing) = dict.get_item(key)? { - let existing_str: String = existing.extract()?; - dict.set_item(key, format!("{}, {}", existing_str, value))?; - } else { - dict.set_item(key, value)?; - } + for (key, value) in self.inner.headers().iter() { + // Handle multiple values for the same header + if let Some(existing) = dict.get_item(key)? { + let existing_str: String = existing.extract()?; + dict.set_item(key, format!("{}, {}", existing_str, value))?; + } else { + dict.set_item(key, value)?; } } Ok(dict) @@ -458,11 +467,9 @@ impl Response { /// Get all headers as a list of tuples. fn headers_list<'py>(&self, py: Python<'py>) -> PyResult> { let list = PyList::empty(py); - for header in &self.inner.headers { - if let Some((key, value)) = header.split_once(':') { - let tuple = (key.trim(), value.trim()); - list.append(tuple)?; - } + for (key, value) in self.inner.headers().iter() { + let tuple = (key, value); + list.append(tuple)?; } Ok(list) } @@ -480,15 +487,25 @@ impl Response { /// Get the response body as bytes. fn bytes<'py>(&self, py: Python<'py>) -> PyResult> { let bytes = self.inner.body().clone(); - Ok(PyBytesWrapper(bytes).into_pyobject(py)?.into_any()) + future_into_py(py, async move { + Python::with_gil(|py| { + let obj = PyBytesWrapper(bytes).into_pyobject(py)?; + Ok(obj.into_any().unbind()) + }) + }) } /// Parse the response body as JSON. fn json<'py>(&self, py: Python<'py>) -> PyResult> { let text = self.inner.text().map_err(to_py_err)?; - // Use Python's json module to parse - let json_module = py.import("json")?; - json_module.getattr("loads")?.call1((text,)) + future_into_py(py, async move { + Python::with_gil(|py| { + // Use Python's json module to parse + let json_module = py.import("json")?; + let obj = json_module.getattr("loads")?.call1((text,))?; + Ok(obj.unbind()) + }) + }) } /// Get the HTTP version string. @@ -500,7 +517,7 @@ impl Response { /// Get the effective URL (after redirects). #[getter] fn effective_url(&self) -> Option { - self.inner.effective_url.clone() + self.inner.url().map(|url| url.to_string()) } /// Check if the response status is successful (2xx). @@ -529,7 +546,7 @@ impl Response { /// Get the string representation. fn __repr__(&self) -> String { - format!("", self.inner.status) + format!("", self.inner.status().as_u16()) } } diff --git a/bindings/python/tests/test_client.py b/bindings/python/tests/test_client.py index 424b2a8e..025bb9d9 100644 --- a/bindings/python/tests/test_client.py +++ b/bindings/python/tests/test_client.py @@ -36,7 +36,7 @@ def test_fingerprint_firefox(self): def test_fingerprint_none(self): """Test setting no fingerprint.""" builder = specter.Client.builder() - builder.fingerprint(specter.FingerprintProfile.None) + builder.fingerprint(specter.FingerprintProfile.NoFingerprint) client = builder.build() assert client is not None @@ -221,9 +221,9 @@ def test_firefox133_exists(self): """Test Firefox133 profile exists.""" assert specter.FingerprintProfile.Firefox133 is not None - def test_none_exists(self): - """Test None profile exists.""" - assert specter.FingerprintProfile.None is not None + def test_nofingerprint_exists(self): + """Test NoFingerprint profile exists.""" + assert specter.FingerprintProfile.NoFingerprint is not None class TestHttpVersion: @@ -358,7 +358,7 @@ async def test_arbitrary_method_request(self): builder = specter.Client.builder() client = builder.build() response = await client.request("PURGE", "https://httpbin.org/anything").send() - assert response.status == 200 + assert response.status in (200, 405) async def test_response_properties(self): """Test response properties.""" diff --git a/examples/fingerprint_validation.rs b/examples/fingerprint_validation.rs index 1381b732..d3d80f87 100644 --- a/examples/fingerprint_validation.rs +++ b/examples/fingerprint_validation.rs @@ -267,7 +267,10 @@ async fn test_h2_fingerprint() -> Result<()> { match h2_conn.send_request(Method::GET, &uri, headers, None).await { Ok(response) => { - info!(" [PASS] HTTP/2 request succeeded: {}", response.status); + info!( + " [PASS] HTTP/2 request succeeded: {}", + response.status() + ); // Parse response to check fingerprint let body = String::from_utf8_lossy(response.body()); @@ -344,17 +347,21 @@ async fn test_h3_fingerprint() -> Result<()> { "GET", vec![ ( - "user-agent", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user-agent".to_string(), + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" + .to_string(), ), - ("accept", "*/*"), + ("accept".to_string(), "*/*".to_string()), ], None, ) .await { Ok(response) => { - info!(" [PASS] HTTP/3 request succeeded: {}", response.status); + info!( + " [PASS] HTTP/3 request succeeded: {}", + response.status() + ); info!(" [PASS] Protocol: {}", response.http_version()); let body = String::from_utf8_lossy(response.body()); @@ -389,17 +396,18 @@ async fn test_h3_fingerprint() -> Result<()> { "GET", vec![ ( - "user-agent", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user-agent".to_string(), + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" + .to_string(), ), - ("accept", "text/html"), + ("accept".to_string(), "text/html".to_string()), ], None, ) .await { Ok(response) => { - info!(" [PASS] quic.tech response: {}", response.status); + info!(" [PASS] quic.tech response: {}", response.status()); if response.http_version() == "HTTP/3" { info!(" [PASS] HTTP/3 confirmed"); } @@ -555,7 +563,10 @@ async fn test_firefox_h2_fingerprint() -> Result<()> { match h2_conn.send_request(Method::GET, &uri, headers, None).await { Ok(response) => { - info!(" [PASS] HTTP/2 request succeeded: {}", response.status); + info!( + " [PASS] HTTP/2 request succeeded: {}", + response.status() + ); // Parse response to check fingerprint let body = String::from_utf8_lossy(response.body()); @@ -701,7 +712,7 @@ async fn test_browserleaks() -> Result<()> { match h2_conn.send_request(Method::GET, &uri, headers, None).await { Ok(response) => { - info!(" [PASS] Response: {}", response.status); + info!(" [PASS] Response: {}", response.status()); let body = String::from_utf8_lossy(response.body()); @@ -803,7 +814,7 @@ async fn test_scrapfly() -> Result<()> { match h2_conn.send_request(Method::GET, &uri, headers, None).await { Ok(response) => { - info!(" [PASS] Response: {}", response.status); + info!(" [PASS] Response: {}", response.status()); let body = String::from_utf8_lossy(response.body()); diff --git a/examples/protocol_test.rs b/examples/protocol_test.rs index 84c67df3..bcb99338 100644 --- a/examples/protocol_test.rs +++ b/examples/protocol_test.rs @@ -301,7 +301,7 @@ async fn test_http1_explicit(url: &str, _verbose: bool) -> TestResult { Ok(response) => { let duration = start.elapsed().as_millis() as u64; let protocol = response.http_version(); - let status = response.status; + let status = response.status().as_u16(); let body_len = response.body().len(); // Server may upgrade to HTTP/2 via ALPN - that's valid behavior @@ -339,7 +339,7 @@ async fn test_http2_explicit(url: &str, _verbose: bool) -> TestResult { Ok(response) => { let duration = start.elapsed().as_millis() as u64; let protocol = response.http_version(); - let status = response.status; + let status = response.status().as_u16(); let body_len = response.body().len(); if protocol != "HTTP/2" { @@ -377,7 +377,7 @@ async fn test_http2_auto_upgrade(url: &str, _verbose: bool) -> TestResult { Ok(response) => { let duration = start.elapsed().as_millis() as u64; let protocol = response.http_version(); - let status = response.status; + let status = response.status().as_u16(); let body_len = response.body().len(); // Most servers will select H2 - this test validates the auto-upgrade works @@ -467,7 +467,7 @@ async fn test_http3_explicit(url: &str, _verbose: bool) -> TestResult { Ok(response) => { let duration = start.elapsed().as_millis() as u64; let protocol = response.http_version(); - let status = response.status; + let status = response.status().as_u16(); let body_len = response.body().len(); if protocol != "HTTP/3" { @@ -515,7 +515,7 @@ async fn test_connection_header_filtering(url: &str, _verbose: bool) -> TestResu Ok(response) => { let duration = start.elapsed().as_millis() as u64; let protocol = response.http_version(); - let status = response.status; + let status = response.status().as_u16(); let body_len = response.body().len(); TestResult::success(name, protocol, status, duration, body_len) @@ -561,7 +561,7 @@ async fn test_post_request(base_url: &str, _verbose: bool) -> TestResult { let start = Instant::now(); match client - .post(&url) + .post(url.as_str()) .headers(headers) .body(body.as_bytes().to_vec()) .version(HttpVersion::Http2) @@ -571,7 +571,7 @@ async fn test_post_request(base_url: &str, _verbose: bool) -> TestResult { Ok(response) => { let duration = start.elapsed().as_millis() as u64; let protocol = response.http_version(); - let status = response.status; + let status = response.status().as_u16(); let body_len = response.body().len(); // Accept various success codes (200, 201, 301, 302, 405, etc.) diff --git a/examples/proxy_browserleaks.rs b/examples/proxy_browserleaks.rs new file mode 100644 index 00000000..d8a49e7a --- /dev/null +++ b/examples/proxy_browserleaks.rs @@ -0,0 +1,164 @@ +//! BrowserLeaks TLS fingerprint check through SOCKS5 proxy. +//! +//! Usage: +//! cargo run --example proxy_browserleaks -- --socks5 host:port --user USER --pass PASS + +use specter::headers::chrome_146_headers; +use specter::{Client, FingerprintProfile, HttpVersion, ProxyConfig}; + +#[tokio::main] +async fn main() -> Result<(), specter::Error> { + tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::from_default_env() + .add_directive("specter=debug".parse().unwrap()), + ) + .init(); + + let args: Vec = std::env::args().collect(); + let proxy = parse_proxy(&args); + + let mut builder = Client::builder() + .fingerprint(FingerprintProfile::Chrome146) + .prefer_http2(true) + .with_platform_roots(true); + + if let Some(ref p) = proxy { + println!("[*] Proxy: {}", p.proxy_key()); + builder = builder.proxy(p.clone()); + } else { + println!("[*] Direct (no proxy)"); + } + + let client = builder.build()?; + + // 1. BrowserLeaks TLS fingerprint + println!("\n=== tls.browserleaks.com/json ==="); + let headers = chrome_146_headers(); + match client + .get("https://tls.browserleaks.com/json") + .headers(headers.clone()) + .version(HttpVersion::Http2) + .send() + .await + { + Ok(resp) => { + let status = resp.status(); + let body = resp.text().unwrap_or_default(); + println!("Status: {}", status); + // Pretty-print the JSON + if let Ok(val) = serde_json::from_str::(&body) { + if let Some(ja3_hash) = val.get("ja3_hash") { + println!("JA3 hash: {}", ja3_hash); + } + if let Some(ja3n_hash) = val.get("ja3n_hash") { + println!("JA3N hash: {}", ja3n_hash); + } + if let Some(ja4) = val.get("ja4") { + println!("JA4: {}", ja4); + } + if let Some(akamai) = val.get("akamai_hash") { + println!("Akamai H2 hash: {}", akamai); + } + if let Some(akamai_text) = val.get("akamai_text") { + println!("Akamai H2 text: {}", akamai_text); + } + if let Some(tls_version) = val.get("tls_version") { + println!("TLS version: {}", tls_version); + } + if let Some(protocol) = val.get("protocol") { + println!("HTTP protocol: {}", protocol); + } + if let Some(ip) = val.get("ip") { + println!("IP: {}", ip); + } + } else { + println!("{}", body); + } + } + Err(e) => println!("FAILED: {}", e), + } + + // 2. tls.peet.ws for detailed fingerprint + println!("\n=== tls.peet.ws/api/all ==="); + match client + .get("https://tls.peet.ws/api/all") + .headers(headers) + .version(HttpVersion::Http2) + .send() + .await + { + Ok(resp) => { + let status = resp.status(); + let body = resp.text().unwrap_or_default(); + println!("Status: {}", status); + if let Ok(val) = serde_json::from_str::(&body) { + if let Some(ip) = val.get("ip") { + println!("IP: {}", ip); + } + if let Some(ja3) = val.get("ja3_hash") { + println!("JA3 hash: {}", ja3); + } + if let Some(ja4) = val.get("ja4") { + println!("JA4: {}", ja4); + } + if let Some(h2) = val.get("http_version") { + println!("HTTP version: {}", h2); + } + if let Some(akamai) = val.get("akamai") { + println!("Akamai fp: {}", akamai); + } + if let Some(h2fp) = val.get("h2") { + if let Some(akamai_fp) = h2fp.get("akamai_fingerprint") { + println!("H2 Akamai fp: {}", akamai_fp); + } + } + } else { + println!("{}", body); + } + } + Err(e) => println!("FAILED: {}", e), + } + + Ok(()) +} + +fn parse_proxy(args: &[String]) -> Option { + let mut socks5 = None; + let mut user = None; + let mut pass = None; + + let mut i = 1; + while i < args.len() { + match args[i].as_str() { + "--socks5" if i + 1 < args.len() => { + socks5 = Some(args[i + 1].clone()); + i += 2; + } + "--user" if i + 1 < args.len() => { + user = Some(args[i + 1].clone()); + i += 2; + } + "--pass" if i + 1 < args.len() => { + pass = Some(args[i + 1].clone()); + i += 2; + } + _ => i += 1, + } + } + + socks5.map(|addr| { + let (host, port) = if let Some(pos) = addr.rfind(':') { + ( + addr[..pos].to_string(), + addr[pos + 1..].parse().unwrap_or(1080), + ) + } else { + (addr, 1080) + }; + match (user, pass) { + (Some(u), Some(p)) => ProxyConfig::socks5_with_auth(host, port, u, p), + _ => ProxyConfig::socks5(host, port), + } + }) +} diff --git a/examples/proxy_h3_test.rs b/examples/proxy_h3_test.rs new file mode 100644 index 00000000..9dff3126 --- /dev/null +++ b/examples/proxy_h3_test.rs @@ -0,0 +1,154 @@ +//! HTTP/3 (QUIC) test through SOCKS5 proxy via UDP ASSOCIATE. +//! +//! Usage: +//! # Direct H3: +//! cargo run --example proxy_h3_test +//! +//! # H3 through SOCKS5: +//! cargo run --example proxy_h3_test -- --socks5 host:port --user USER --pass PASS + +use specter::headers::chrome_146_headers; +use specter::{Client, FingerprintProfile, HttpVersion, ProxyConfig}; + +#[tokio::main] +async fn main() -> Result<(), specter::Error> { + tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::from_default_env() + .add_directive("specter=debug".parse().unwrap()), + ) + .init(); + + let args: Vec = std::env::args().collect(); + let proxy = parse_proxy(&args); + + let mut builder = Client::builder() + .fingerprint(FingerprintProfile::Chrome146) + .with_platform_roots(true) + .h3_upgrade(true); + + if let Some(ref p) = proxy { + println!("[*] Proxy: {}", p.proxy_key()); + builder = builder.proxy(p.clone()); + } else { + println!("[*] Direct (no proxy)"); + } + + let client = builder.build()?; + let headers = chrome_146_headers(); + + // Test 1: HTTP/3 Only (strict — no fallback) + println!("\n=== Test 1: HTTP/3 Only (strict) ==="); + println!("[>] cloudflare.com via H3 only..."); + match client + .get("https://cloudflare.com") + .headers(headers.clone()) + .version(HttpVersion::Http3Only) + .send() + .await + { + Ok(resp) => { + println!(" Status: {}", resp.status()); + println!(" HTTP version: {}", resp.http_version()); + let body = resp.text().unwrap_or_default(); + println!(" Body length: {} bytes", body.len()); + } + Err(e) => println!(" FAILED: {}", e), + } + + // Test 2: HTTP/3 preferred (with H1/H2 fallback) + println!("\n=== Test 2: HTTP/3 preferred (fallback to H1/H2) ==="); + println!("[>] cloudflare.com via H3 preferred..."); + match client + .get("https://cloudflare.com") + .headers(headers.clone()) + .version(HttpVersion::Http3) + .send() + .await + { + Ok(resp) => { + println!(" Status: {}", resp.status()); + println!(" HTTP version: {}", resp.http_version()); + let body = resp.text().unwrap_or_default(); + println!(" Body length: {} bytes", body.len()); + } + Err(e) => println!(" FAILED: {}", e), + } + + // Test 3: IP check via H3 + println!("\n=== Test 3: IP check via H3 ==="); + println!("[>] one.one.one.one/cdn-cgi/trace (Cloudflare H3)..."); + match client + .get("https://one.one.one.one/cdn-cgi/trace") + .headers(headers.clone()) + .version(HttpVersion::Http3) + .send() + .await + { + Ok(resp) => { + println!(" Status: {}", resp.status()); + println!(" HTTP version: {}", resp.http_version()); + let body = resp.text().unwrap_or_default(); + // Parse key fields from trace + for line in body.lines() { + if line.starts_with("ip=") + || line.starts_with("h=") + || line.starts_with("http=") + || line.starts_with("tls=") + || line.starts_with("loc=") + || line.starts_with("colo=") + { + println!(" {}", line); + } + } + } + Err(e) => println!(" FAILED: {}", e), + } + + // Test 4: Auto version (check Alt-Svc H3 upgrade) + println!("\n=== Test 4: Auto version ==="); + println!("[>] httpbin.org/ip via Auto..."); + match client + .get("https://httpbin.org/ip") + .headers(headers) + .version(HttpVersion::Auto) + .send() + .await + { + Ok(resp) => { + println!(" Status: {}", resp.status()); + println!(" HTTP version: {}", resp.http_version()); + let body = resp.text().unwrap_or_default(); + println!(" {}", body.trim()); + } + Err(e) => println!(" FAILED: {}", e), + } + + Ok(()) +} + +fn parse_proxy(args: &[String]) -> Option { + let mut socks5 = None; + let mut user = None; + let mut pass = None; + let mut i = 1; + while i < args.len() { + match args[i].as_str() { + "--socks5" if i + 1 < args.len() => { socks5 = Some(args[i + 1].clone()); i += 2; } + "--user" if i + 1 < args.len() => { user = Some(args[i + 1].clone()); i += 2; } + "--pass" if i + 1 < args.len() => { pass = Some(args[i + 1].clone()); i += 2; } + _ => i += 1, + } + } + socks5.map(|addr| { + let (host, port) = if let Some(pos) = addr.rfind(':') { + (addr[..pos].to_string(), addr[pos + 1..].parse().unwrap_or(1080)) + } else { + (addr, 1080) + }; + match (user, pass) { + (Some(u), Some(p)) => ProxyConfig::socks5_with_auth(host, port, u, p), + _ => ProxyConfig::socks5(host, port), + } + }) +} diff --git a/examples/proxy_test.rs b/examples/proxy_test.rs new file mode 100644 index 00000000..a8bd9b4c --- /dev/null +++ b/examples/proxy_test.rs @@ -0,0 +1,124 @@ +//! Proxy integration test — hits IP detection APIs. +//! +//! Usage: +//! # Without proxy (direct): +//! cargo run --example proxy_test +//! +//! # With SOCKS5 proxy: +//! cargo run --example proxy_test -- --socks5 127.0.0.1:1080 +//! +//! # With SOCKS5 proxy + auth: +//! cargo run --example proxy_test -- --socks5 127.0.0.1:1080 --user admin --pass secret +//! +//! # With HTTP CONNECT proxy: +//! cargo run --example proxy_test -- --http-proxy 127.0.0.1:8080 + +use specter::{Client, FingerprintProfile, ProxyConfig}; + +#[tokio::main] +async fn main() -> Result<(), specter::Error> { + tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::from_default_env() + .add_directive("specter=debug".parse().unwrap()), + ) + .init(); + + let args: Vec = std::env::args().collect(); + let proxy = parse_proxy_args(&args); + + // Build client + let mut builder = Client::builder() + .fingerprint(FingerprintProfile::Chrome146) + .with_platform_roots(true); + + if let Some(ref p) = proxy { + println!("[*] Using proxy: {:?}", p); + builder = builder.proxy(p.clone()); + } else { + println!("[*] Direct connection (no proxy)"); + } + + let client = builder.build()?; + + // Hit IP detection APIs + let apis = [ + ("httpbin.org/ip", "https://httpbin.org/ip"), + ("api.ipify.org", "https://api.ipify.org?format=json"), + ("ifconfig.me", "https://ifconfig.me/ip"), + ]; + + for (name, url) in &apis { + print!("[>] {} ... ", name); + match client.get(*url).send().await { + Ok(resp) => { + let status = resp.status(); + let body = resp.text().unwrap_or_else(|_| "(decode error)".into()); + println!("HTTP {} — {}", status, body.trim()); + } + Err(e) => { + println!("FAILED — {}", e); + } + } + } + + Ok(()) +} + +fn parse_proxy_args(args: &[String]) -> Option { + let mut socks5_addr = None; + let mut http_proxy_addr = None; + let mut user = None; + let mut pass = None; + + let mut i = 1; + while i < args.len() { + match args[i].as_str() { + "--socks5" if i + 1 < args.len() => { + socks5_addr = Some(args[i + 1].clone()); + i += 2; + } + "--http-proxy" if i + 1 < args.len() => { + http_proxy_addr = Some(args[i + 1].clone()); + i += 2; + } + "--user" if i + 1 < args.len() => { + user = Some(args[i + 1].clone()); + i += 2; + } + "--pass" if i + 1 < args.len() => { + pass = Some(args[i + 1].clone()); + i += 2; + } + _ => { + i += 1; + } + } + } + + if let Some(addr) = socks5_addr { + let (host, port) = parse_host_port(&addr, 1080); + match (user, pass) { + (Some(u), Some(p)) => Some(ProxyConfig::socks5_with_auth(host, port, u, p)), + _ => Some(ProxyConfig::socks5(host, port)), + } + } else if let Some(addr) = http_proxy_addr { + let (host, port) = parse_host_port(&addr, 8080); + match (user, pass) { + (Some(u), Some(p)) => Some(ProxyConfig::http_connect_with_auth(host, port, u, p)), + _ => Some(ProxyConfig::http_connect(host, port)), + } + } else { + None + } +} + +fn parse_host_port(addr: &str, default_port: u16) -> (String, u16) { + if let Some(pos) = addr.rfind(':') { + let host = addr[..pos].to_string(); + let port = addr[pos + 1..].parse().unwrap_or(default_port); + (host, port) + } else { + (addr.to_string(), default_port) + } +} diff --git a/justfile b/justfile new file mode 100644 index 00000000..f02118db --- /dev/null +++ b/justfile @@ -0,0 +1,259 @@ +#!/usr/bin/env just --justfile +# Specter Build Commands +# Run `just` to see all available commands + +default: + @just --list + +# ============================================================================= +# BUILD +# ============================================================================= + +# Cross-compile for Linux ARM64 using zig (with prebuilt BoringSSL) +# Usage: just zigbuild [target] +# Targets: aarch64-unknown-linux-gnu (default), x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl +[group('build')] +zigbuild target="aarch64-unknown-linux-gnu": + #!/usr/bin/env bash + set -euo pipefail + + if ! command -v cargo-zigbuild &> /dev/null; then + echo "cargo-zigbuild not found. Install with: cargo install cargo-zigbuild" + exit 1 + fi + + if ! command -v zig &> /dev/null; then + echo "zig not found. Install with: brew install zig" + exit 1 + fi + + TARGET="{{ target }}" + + # Select wrapper scripts and prebuilt libs based on target + case "$TARGET" in + aarch64-unknown-linux-gnu) + WRAPPER_CC="$(pwd)/scripts/zig-cc-aarch64-linux-gnu" + WRAPPER_CXX="$(pwd)/scripts/zig-cxx-aarch64-linux-gnu" + ;; + x86_64-unknown-linux-gnu) + WRAPPER_CC="$(pwd)/scripts/zig-cc-x86_64-linux-gnu" + WRAPPER_CXX="$(pwd)/scripts/zig-cxx-x86_64-linux-gnu" + ;; + x86_64-unknown-linux-musl) + WRAPPER_CC="$(pwd)/scripts/zig-cc-x86_64-linux-musl" + WRAPPER_CXX="$(pwd)/scripts/zig-cxx-x86_64-linux-musl" + ;; + aarch64-unknown-linux-musl) + WRAPPER_CC="$(pwd)/scripts/zig-cc-aarch64-linux-musl" + WRAPPER_CXX="$(pwd)/scripts/zig-cxx-aarch64-linux-musl" + ;; + *) + echo "Unsupported target: $TARGET" + echo "Supported targets: aarch64-unknown-linux-gnu, x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, aarch64-unknown-linux-musl" + exit 1 + ;; + esac + + # Check if wrapper scripts exist + if [[ ! -f "$WRAPPER_CC" ]]; then + echo "Wrapper script not found: $WRAPPER_CC" + echo "Run: just setup-zigbuild" + exit 1 + fi + + # Check if prebuilt BoringSSL exists for this target + BSSL_PATH="$(pwd)/lib/boringssl/$TARGET" + if [[ -d "$BSSL_PATH/build" ]]; then + echo "Using prebuilt BoringSSL from $BSSL_PATH" + export BORING_BSSL_PATH="$BSSL_PATH/build" + export BORING_BSSL_INCLUDE_PATH="$(pwd)/lib/boringssl/include" + else + echo "Warning: No prebuilt BoringSSL found at $BSSL_PATH" + echo "BoringSSL will be built from source (slower)" + fi + + # Set up compiler wrappers + export CC="$WRAPPER_CC" + export CXX="$WRAPPER_CXX" + export CC_${TARGET//-/_}="$WRAPPER_CC" + export CXX_${TARGET//-/_}="$WRAPPER_CXX" + export AR_${TARGET//-/_}="ar" + + # CMAKE-specific (for boring-sys) + export CMAKE_C_COMPILER_${TARGET//-/_}="$WRAPPER_CC" + export CMAKE_CXX_COMPILER_${TARGET//-/_}="$WRAPPER_CXX" + + echo "Cross-compiling for $TARGET with cargo-zigbuild..." + echo " CC=$CC" + echo " BORING_BSSL_PATH=${BORING_BSSL_PATH:-}" + + cargo zigbuild --release --target "$TARGET" --lib + + echo "" + echo "Build complete for $TARGET" + +# Build for native macOS (with prebuilt BoringSSL) +[group('build')] +build: + #!/usr/bin/env bash + set -euo pipefail + + # Detect architecture + if [[ "$(uname -m)" == "arm64" ]]; then + TARGET="aarch64-apple-darwin" + else + TARGET="x86_64-apple-darwin" + fi + + BSSL_PATH="$(pwd)/lib/boringssl/$TARGET" + if [[ -d "$BSSL_PATH/build" ]]; then + echo "Using prebuilt BoringSSL from $BSSL_PATH" + export BORING_BSSL_PATH="$BSSL_PATH/build" + export BORING_BSSL_INCLUDE_PATH="$(pwd)/lib/boringssl/include" + fi + + cargo build --release + +# ============================================================================= +# SETUP +# ============================================================================= + +# Install zig and cargo-zigbuild for cross-compilation +[group('setup')] +setup-zigbuild: + #!/usr/bin/env bash + set -euo pipefail + + echo "Setting up zig cross-compilation toolchain..." + + if ! command -v zig &> /dev/null; then + echo "Installing zig via Homebrew..." + brew install zig + else + echo "zig already installed: $(zig version)" + fi + + if ! command -v cargo-zigbuild &> /dev/null; then + echo "Installing cargo-zigbuild..." + cargo install cargo-zigbuild + else + echo "cargo-zigbuild already installed" + fi + + # Add Rust targets + echo "Adding Rust cross-compilation targets..." + rustup target add aarch64-unknown-linux-gnu + rustup target add x86_64-unknown-linux-gnu + rustup target add x86_64-unknown-linux-musl + + # Ensure wrapper scripts are executable + chmod +x scripts/zig-*.sh scripts/zig-cc-* scripts/zig-cxx-* 2>/dev/null || true + + echo "" + echo "Setup complete! You can now run:" + echo " just zigbuild # Linux ARM64" + echo " just zigbuild x86_64-unknown-linux-gnu # Linux x86_64" + +# Build prebuilt BoringSSL libraries for all targets +[group('setup')] +build-boringssl *TARGETS: + #!/usr/bin/env bash + set -euo pipefail + + if [[ -z "{{ TARGETS }}" ]]; then + ./scripts/build-boringssl.sh + else + ./scripts/build-boringssl.sh {{ TARGETS }} + fi + +# ============================================================================= +# TEST +# ============================================================================= + +# Run tests with prebuilt BoringSSL +[group('test')] +test: + #!/usr/bin/env bash + set -euo pipefail + + # Detect architecture + if [[ "$(uname -m)" == "arm64" ]]; then + TARGET="aarch64-apple-darwin" + else + TARGET="x86_64-apple-darwin" + fi + + BSSL_PATH="$(pwd)/lib/boringssl/$TARGET" + if [[ -d "$BSSL_PATH/build" ]]; then + export BORING_BSSL_PATH="$BSSL_PATH/build" + export BORING_BSSL_INCLUDE_PATH="$(pwd)/lib/boringssl/include" + fi + + cargo nextest run --all-features + +# Run tests with cargo test (if nextest not available) +[group('test')] +test-cargo: + #!/usr/bin/env bash + set -euo pipefail + + if [[ "$(uname -m)" == "arm64" ]]; then + TARGET="aarch64-apple-darwin" + else + TARGET="x86_64-apple-darwin" + fi + + BSSL_PATH="$(pwd)/lib/boringssl/$TARGET" + if [[ -d "$BSSL_PATH/build" ]]; then + export BORING_BSSL_PATH="$BSSL_PATH/build" + export BORING_BSSL_INCLUDE_PATH="$(pwd)/lib/boringssl/include" + fi + + cargo test --all-features + +# ============================================================================= +# QUALITY +# ============================================================================= + +# Run clippy linter +[group('quality')] +clippy: + cargo clippy --all-features -- -D warnings + +# Check formatting +[group('quality')] +fmt-check: + cargo fmt -- --check + +# Format code +[group('quality')] +fmt: + cargo fmt + +# Run all quality checks +[group('quality')] +check: + just fmt-check + just clippy + just test + +# ============================================================================= +# CLEAN +# ============================================================================= + +# Clean build artifacts +[group('cleanup')] +clean: + cargo clean + +# Clean BoringSSL build cache (not prebuilt libs) +[group('cleanup')] +clean-boringssl-cache: + rm -rf .boringssl-build + +# Clean everything including prebuilt libs +[group('cleanup')] +clean-all: + cargo clean + rm -rf .boringssl-build + rm -rf lib/boringssl diff --git a/lib/boringssl/aarch64-apple-darwin/build/libcrypto.a b/lib/boringssl/aarch64-apple-darwin/build/libcrypto.a new file mode 100644 index 00000000..dc3e7c18 Binary files /dev/null and b/lib/boringssl/aarch64-apple-darwin/build/libcrypto.a differ diff --git a/lib/boringssl/aarch64-apple-darwin/build/libssl.a b/lib/boringssl/aarch64-apple-darwin/build/libssl.a new file mode 100644 index 00000000..1ac35625 Binary files /dev/null and b/lib/boringssl/aarch64-apple-darwin/build/libssl.a differ diff --git a/lib/boringssl/aarch64-apple-darwin/include b/lib/boringssl/aarch64-apple-darwin/include new file mode 120000 index 00000000..f5030fe8 --- /dev/null +++ b/lib/boringssl/aarch64-apple-darwin/include @@ -0,0 +1 @@ +../include \ No newline at end of file diff --git a/lib/boringssl/aarch64-pc-windows-msvc/build/crypto.lib b/lib/boringssl/aarch64-pc-windows-msvc/build/crypto.lib new file mode 100644 index 00000000..59af83f1 Binary files /dev/null and b/lib/boringssl/aarch64-pc-windows-msvc/build/crypto.lib differ diff --git a/lib/boringssl/aarch64-pc-windows-msvc/build/ssl.lib b/lib/boringssl/aarch64-pc-windows-msvc/build/ssl.lib new file mode 100644 index 00000000..92bf4493 Binary files /dev/null and b/lib/boringssl/aarch64-pc-windows-msvc/build/ssl.lib differ diff --git a/lib/boringssl/aarch64-pc-windows-msvc/include b/lib/boringssl/aarch64-pc-windows-msvc/include new file mode 120000 index 00000000..f5030fe8 --- /dev/null +++ b/lib/boringssl/aarch64-pc-windows-msvc/include @@ -0,0 +1 @@ +../include \ No newline at end of file diff --git a/lib/boringssl/aarch64-unknown-linux-gnu/build/libcrypto.a b/lib/boringssl/aarch64-unknown-linux-gnu/build/libcrypto.a new file mode 100644 index 00000000..0ff2de6e Binary files /dev/null and b/lib/boringssl/aarch64-unknown-linux-gnu/build/libcrypto.a differ diff --git a/lib/boringssl/aarch64-unknown-linux-gnu/build/libssl.a b/lib/boringssl/aarch64-unknown-linux-gnu/build/libssl.a new file mode 100644 index 00000000..162de3b6 Binary files /dev/null and b/lib/boringssl/aarch64-unknown-linux-gnu/build/libssl.a differ diff --git a/lib/boringssl/aarch64-unknown-linux-gnu/include b/lib/boringssl/aarch64-unknown-linux-gnu/include new file mode 120000 index 00000000..f5030fe8 --- /dev/null +++ b/lib/boringssl/aarch64-unknown-linux-gnu/include @@ -0,0 +1 @@ +../include \ No newline at end of file diff --git a/lib/boringssl/aarch64-unknown-linux-musl/build/libcrypto.a b/lib/boringssl/aarch64-unknown-linux-musl/build/libcrypto.a new file mode 100644 index 00000000..c1a04099 Binary files /dev/null and b/lib/boringssl/aarch64-unknown-linux-musl/build/libcrypto.a differ diff --git a/lib/boringssl/aarch64-unknown-linux-musl/build/libssl.a b/lib/boringssl/aarch64-unknown-linux-musl/build/libssl.a new file mode 100644 index 00000000..ccc050b3 Binary files /dev/null and b/lib/boringssl/aarch64-unknown-linux-musl/build/libssl.a differ diff --git a/lib/boringssl/aarch64-unknown-linux-musl/include b/lib/boringssl/aarch64-unknown-linux-musl/include new file mode 120000 index 00000000..f5030fe8 --- /dev/null +++ b/lib/boringssl/aarch64-unknown-linux-musl/include @@ -0,0 +1 @@ +../include \ No newline at end of file diff --git a/lib/boringssl/include/openssl/aead.h b/lib/boringssl/include/openssl/aead.h new file mode 100644 index 00000000..376bff17 --- /dev/null +++ b/lib/boringssl/include/openssl/aead.h @@ -0,0 +1,482 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_AEAD_H +#define OPENSSL_HEADER_AEAD_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Authenticated Encryption with Additional Data. +// +// AEAD couples confidentiality and integrity in a single primitive. AEAD +// algorithms take a key and then can seal and open individual messages. Each +// message has a unique, per-message nonce and, optionally, additional data +// which is authenticated but not included in the ciphertext. +// +// The |EVP_AEAD_CTX_init| function initialises an |EVP_AEAD_CTX| structure and +// performs any precomputation needed to use |aead| with |key|. The length of +// the key, |key_len|, is given in bytes. +// +// The |tag_len| argument contains the length of the tags, in bytes, and allows +// for the processing of truncated authenticators. A zero value indicates that +// the default tag length should be used and this is defined as +// |EVP_AEAD_DEFAULT_TAG_LENGTH| in order to make the code clear. Using +// truncated tags increases an attacker's chance of creating a valid forgery. +// Be aware that the attacker's chance may increase more than exponentially as +// would naively be expected. +// +// When no longer needed, the initialised |EVP_AEAD_CTX| structure must be +// passed to |EVP_AEAD_CTX_cleanup|, which will deallocate any memory used. +// +// With an |EVP_AEAD_CTX| in hand, one can seal and open messages. These +// operations are intended to meet the standard notions of privacy and +// authenticity for authenticated encryption. For formal definitions see +// Bellare and Namprempre, "Authenticated encryption: relations among notions +// and analysis of the generic composition paradigm," Lecture Notes in Computer +// Science B<1976> (2000), 531–545, +// http://www-cse.ucsd.edu/~mihir/papers/oem.html. +// +// When sealing messages, a nonce must be given. The length of the nonce is +// fixed by the AEAD in use and is returned by |EVP_AEAD_nonce_length|. *The +// nonce must be unique for all messages with the same key*. This is critically +// important - nonce reuse may completely undermine the security of the AEAD. +// Nonces may be predictable and public, so long as they are unique. Uniqueness +// may be achieved with a simple counter or, if large enough, may be generated +// randomly. The nonce must be passed into the "open" operation by the receiver +// so must either be implicit (e.g. a counter), or must be transmitted along +// with the sealed message. +// +// The "seal" and "open" operations are atomic - an entire message must be +// encrypted or decrypted in a single call. Large messages may have to be split +// up in order to accommodate this. When doing so, be mindful of the need not to +// repeat nonces and the possibility that an attacker could duplicate, reorder +// or drop message chunks. For example, using a single key for a given (large) +// message and sealing chunks with nonces counting from zero would be secure as +// long as the number of chunks was securely transmitted. (Otherwise an +// attacker could truncate the message by dropping chunks from the end.) +// +// The number of chunks could be transmitted by prefixing it to the plaintext, +// for example. This also assumes that no other message would ever use the same +// key otherwise the rule that nonces must be unique for a given key would be +// violated. +// +// The "seal" and "open" operations also permit additional data to be +// authenticated via the |ad| parameter. This data is not included in the +// ciphertext and must be identical for both the "seal" and "open" call. This +// permits implicit context to be authenticated but may be empty if not needed. +// +// The "seal" and "open" operations may work in-place if the |out| and |in| +// arguments are equal. Otherwise, if |out| and |in| alias, input data may be +// overwritten before it is read. This situation will cause an error. +// +// The "seal" and "open" operations return one on success and zero on error. + + +// AEAD algorithms. + +// EVP_aead_aes_128_gcm is AES-128 in Galois Counter Mode. +// +// Note: AES-GCM should only be used with 12-byte (96-bit) nonces. Although it +// is specified to take a variable-length nonce, nonces with other lengths are +// effectively randomized, which means one must consider collisions. Unless +// implementing an existing protocol which has already specified incorrect +// parameters, only use 12-byte nonces. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm(void); + +// EVP_aead_aes_192_gcm is AES-192 in Galois Counter Mode. +// +// WARNING: AES-192 is superfluous and shouldn't exist. NIST should never have +// defined it. Use only when interop with another system requires it, never +// de novo. +// +// Note: AES-GCM should only be used with 12-byte (96-bit) nonces. Although it +// is specified to take a variable-length nonce, nonces with other lengths are +// effectively randomized, which means one must consider collisions. Unless +// implementing an existing protocol which has already specified incorrect +// parameters, only use 12-byte nonces. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_192_gcm(void); + +// EVP_aead_aes_256_gcm is AES-256 in Galois Counter Mode. +// +// Note: AES-GCM should only be used with 12-byte (96-bit) nonces. Although it +// is specified to take a variable-length nonce, nonces with other lengths are +// effectively randomized, which means one must consider collisions. Unless +// implementing an existing protocol which has already specified incorrect +// parameters, only use 12-byte nonces. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm(void); + +// EVP_aead_chacha20_poly1305 is the AEAD built from ChaCha20 and +// Poly1305 as described in RFC 8439. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305(void); + +// EVP_aead_xchacha20_poly1305 is ChaCha20-Poly1305 with an extended nonce that +// makes random generation of nonces safe. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_xchacha20_poly1305(void); + +// EVP_aead_aes_128_ctr_hmac_sha256 is AES-128 in CTR mode with HMAC-SHA256 for +// authentication. The nonce is 12 bytes; the bottom 32-bits are used as the +// block counter, thus the maximum plaintext size is 64GB. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ctr_hmac_sha256(void); + +// EVP_aead_aes_256_ctr_hmac_sha256 is AES-256 in CTR mode with HMAC-SHA256 for +// authentication. See |EVP_aead_aes_128_ctr_hmac_sha256| for details. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void); + +// EVP_aead_aes_128_gcm_siv is AES-128 in GCM-SIV mode. See RFC 8452. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void); + +// EVP_aead_aes_256_gcm_siv is AES-256 in GCM-SIV mode. See RFC 8452. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void); + +// EVP_aead_aes_128_gcm_randnonce is AES-128 in Galois Counter Mode with +// internal nonce generation. The 12-byte nonce is appended to the tag +// and is generated internally. The "tag", for the purpurses of the API, is thus +// 12 bytes larger. The nonce parameter when using this AEAD must be +// zero-length. Since the nonce is random, a single key should not be used for +// more than 2^32 seal operations. +// +// Warning: this is for use for FIPS compliance only. It is probably not +// suitable for other uses. Using standard AES-GCM AEADs allows one to achieve +// the same effect, but gives more control over nonce storage. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_randnonce(void); + +// EVP_aead_aes_256_gcm_randnonce is AES-256 in Galois Counter Mode with +// internal nonce generation. The 12-byte nonce is appended to the tag +// and is generated internally. The "tag", for the purpurses of the API, is thus +// 12 bytes larger. The nonce parameter when using this AEAD must be +// zero-length. Since the nonce is random, a single key should not be used for +// more than 2^32 seal operations. +// +// Warning: this is for use for FIPS compliance only. It is probably not +// suitable for other uses. Using standard AES-GCM AEADs allows one to achieve +// the same effect, but gives more control over nonce storage. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_randnonce(void); + +// EVP_aead_aes_128_ccm_bluetooth is AES-128-CCM with M=4 and L=2 (4-byte tags +// and 13-byte nonces), as decribed in the Bluetooth Core Specification v5.0, +// Volume 6, Part E, Section 1. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth(void); + +// EVP_aead_aes_128_ccm_bluetooth_8 is AES-128-CCM with M=8 and L=2 (8-byte tags +// and 13-byte nonces), as used in the Bluetooth Mesh Networking Specification +// v1.0. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth_8(void); + +// EVP_aead_aes_128_ccm_matter is AES-128-CCM with M=16 and L=2 (16-byte tags +// and 13-byte nonces), as used in the Matter specification. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ccm_matter(void); + +// EVP_has_aes_hardware returns one if we enable hardware support for fast and +// constant-time AES-GCM. +OPENSSL_EXPORT int EVP_has_aes_hardware(void); + + +// Utility functions. + +// EVP_AEAD_key_length returns the length, in bytes, of the keys used by +// |aead|. +OPENSSL_EXPORT size_t EVP_AEAD_key_length(const EVP_AEAD *aead); + +// EVP_AEAD_nonce_length returns the length, in bytes, of the per-message nonce +// for |aead|. +OPENSSL_EXPORT size_t EVP_AEAD_nonce_length(const EVP_AEAD *aead); + +// EVP_AEAD_max_overhead returns the maximum number of additional bytes added +// by the act of sealing data with |aead|. +OPENSSL_EXPORT size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead); + +// EVP_AEAD_max_tag_len returns the maximum tag length when using |aead|. This +// is the largest value that can be passed as |tag_len| to +// |EVP_AEAD_CTX_init|. +OPENSSL_EXPORT size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead); + + +// AEAD operations. + +union evp_aead_ctx_st_state { + uint8_t opaque[564]; + uint64_t alignment; +}; + +// An evp_aead_ctx_st (typedefed as |EVP_AEAD_CTX| in base.h) represents an AEAD +// algorithm configured with a specific key and message-independent IV. +struct evp_aead_ctx_st { + const EVP_AEAD *aead; + union evp_aead_ctx_st_state state; + // tag_len may contain the actual length of the authentication tag if it is + // known at initialization time. + uint8_t tag_len; +}; + +// EVP_AEAD_MAX_KEY_LENGTH contains the maximum key length used by +// any AEAD defined in this header. +#define EVP_AEAD_MAX_KEY_LENGTH 80 + +// EVP_AEAD_MAX_NONCE_LENGTH contains the maximum nonce length used by +// any AEAD defined in this header. +#define EVP_AEAD_MAX_NONCE_LENGTH 24 + +// EVP_AEAD_MAX_OVERHEAD contains the maximum overhead used by any AEAD +// defined in this header. +#define EVP_AEAD_MAX_OVERHEAD 64 + +// EVP_AEAD_DEFAULT_TAG_LENGTH is a magic value that can be passed to +// EVP_AEAD_CTX_init to indicate that the default tag length for an AEAD should +// be used. +#define EVP_AEAD_DEFAULT_TAG_LENGTH 0 + +// EVP_AEAD_CTX_zero sets an uninitialized |ctx| to the zero state. It must be +// initialized with |EVP_AEAD_CTX_init| before use. It is safe, but not +// necessary, to call |EVP_AEAD_CTX_cleanup| in this state. This may be used for +// more uniform cleanup of |EVP_AEAD_CTX|. +OPENSSL_EXPORT void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx); + +// EVP_AEAD_CTX_new allocates an |EVP_AEAD_CTX|, calls |EVP_AEAD_CTX_init| and +// returns the |EVP_AEAD_CTX|, or NULL on error. +OPENSSL_EXPORT EVP_AEAD_CTX *EVP_AEAD_CTX_new(const EVP_AEAD *aead, + const uint8_t *key, + size_t key_len, size_t tag_len); + +// EVP_AEAD_CTX_free calls |EVP_AEAD_CTX_cleanup| and |OPENSSL_free| on +// |ctx|. +OPENSSL_EXPORT void EVP_AEAD_CTX_free(EVP_AEAD_CTX *ctx); + +// EVP_AEAD_CTX_init initializes |ctx| for the given AEAD algorithm. The |impl| +// argument is ignored and should be NULL. Authentication tags may be truncated +// by passing a size as |tag_len|. A |tag_len| of zero indicates the default +// tag length and this is defined as EVP_AEAD_DEFAULT_TAG_LENGTH for +// readability. +// +// Returns 1 on success. Otherwise returns 0 and pushes to the error stack. In +// the error case, you do not need to call |EVP_AEAD_CTX_cleanup|, but it's +// harmless to do so. +OPENSSL_EXPORT int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, + const uint8_t *key, size_t key_len, + size_t tag_len, ENGINE *impl); + +// EVP_AEAD_CTX_cleanup frees any data allocated by |ctx|. It is a no-op to +// call |EVP_AEAD_CTX_cleanup| on a |EVP_AEAD_CTX| that has been |memset| to +// all zeros. +OPENSSL_EXPORT void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx); + +// EVP_AEAD_CTX_seal encrypts and authenticates |in_len| bytes from |in| and +// authenticates |ad_len| bytes from |ad| and writes the result to |out|. It +// returns one on success and zero otherwise. +// +// This function may be called concurrently with itself or any other seal/open +// function on the same |EVP_AEAD_CTX|. +// +// At most |max_out_len| bytes are written to |out| and, in order to ensure +// success, |max_out_len| should be |in_len| plus the result of +// |EVP_AEAD_max_overhead|. On successful return, |*out_len| is set to the +// actual number of bytes written. +// +// The length of |nonce|, |nonce_len|, must be equal to the result of +// |EVP_AEAD_nonce_length| for this AEAD. +// +// |EVP_AEAD_CTX_seal| never results in a partial output. If |max_out_len| is +// insufficient, zero will be returned. If any error occurs, |out| will be +// filled with zero bytes and |*out_len| set to zero. +// +// If |in| and |out| alias then |out| must be == |in|. +OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len); + +// EVP_AEAD_CTX_open authenticates |in_len| bytes from |in| and |ad_len| bytes +// from |ad| and decrypts at most |in_len| bytes into |out|. It returns one on +// success and zero otherwise. +// +// This function may be called concurrently with itself or any other seal/open +// function on the same |EVP_AEAD_CTX|. +// +// At most |in_len| bytes are written to |out|. In order to ensure success, +// |max_out_len| should be at least |in_len|. On successful return, |*out_len| +// is set to the the actual number of bytes written. +// +// The length of |nonce|, |nonce_len|, must be equal to the result of +// |EVP_AEAD_nonce_length| for this AEAD. +// +// |EVP_AEAD_CTX_open| never results in a partial output. If |max_out_len| is +// insufficient, zero will be returned. If any error occurs, |out| will be +// filled with zero bytes and |*out_len| set to zero. +// +// If |in| and |out| alias then |out| must be == |in|. +OPENSSL_EXPORT int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len); + +// EVP_AEAD_CTX_seal_scatter encrypts and authenticates |in_len| bytes from |in| +// and authenticates |ad_len| bytes from |ad|. It writes |in_len| bytes of +// ciphertext to |out| and the authentication tag to |out_tag|. It returns one +// on success and zero otherwise. +// +// This function may be called concurrently with itself or any other seal/open +// function on the same |EVP_AEAD_CTX|. +// +// Exactly |in_len| bytes are written to |out|, and up to +// |EVP_AEAD_max_overhead+extra_in_len| bytes to |out_tag|. On successful +// return, |*out_tag_len| is set to the actual number of bytes written to +// |out_tag|. +// +// |extra_in| may point to an additional plaintext input buffer if the cipher +// supports it. If present, |extra_in_len| additional bytes of plaintext are +// encrypted and authenticated, and the ciphertext is written (before the tag) +// to |out_tag|. |max_out_tag_len| must be sized to allow for the additional +// |extra_in_len| bytes. +// +// The length of |nonce|, |nonce_len|, must be equal to the result of +// |EVP_AEAD_nonce_length| for this AEAD. +// +// |EVP_AEAD_CTX_seal_scatter| never results in a partial output. If +// |max_out_tag_len| is insufficient, zero will be returned. If any error +// occurs, |out| and |out_tag| will be filled with zero bytes and |*out_tag_len| +// set to zero. +// +// If |in| and |out| alias then |out| must be == |in|. |out_tag| may not alias +// any other argument. +OPENSSL_EXPORT int EVP_AEAD_CTX_seal_scatter( + const EVP_AEAD_CTX *ctx, uint8_t *out, + uint8_t *out_tag, size_t *out_tag_len, size_t max_out_tag_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *extra_in, size_t extra_in_len, + const uint8_t *ad, size_t ad_len); + +// EVP_AEAD_CTX_open_gather decrypts and authenticates |in_len| bytes from |in| +// and authenticates |ad_len| bytes from |ad| using |in_tag_len| bytes of +// authentication tag from |in_tag|. If successful, it writes |in_len| bytes of +// plaintext to |out|. It returns one on success and zero otherwise. +// +// This function may be called concurrently with itself or any other seal/open +// function on the same |EVP_AEAD_CTX|. +// +// The length of |nonce|, |nonce_len|, must be equal to the result of +// |EVP_AEAD_nonce_length| for this AEAD. +// +// |EVP_AEAD_CTX_open_gather| never results in a partial output. If any error +// occurs, |out| will be filled with zero bytes. +// +// If |in| and |out| alias then |out| must be == |in|. +OPENSSL_EXPORT int EVP_AEAD_CTX_open_gather( + const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce, + size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag, + size_t in_tag_len, const uint8_t *ad, size_t ad_len); + +// EVP_AEAD_CTX_aead returns the underlying AEAD for |ctx|, or NULL if one has +// not been set. +OPENSSL_EXPORT const EVP_AEAD *EVP_AEAD_CTX_aead(const EVP_AEAD_CTX *ctx); + + +// TLS-specific AEAD algorithms. +// +// These AEAD primitives do not meet the definition of generic AEADs. They are +// all specific to TLS and should not be used outside of that context. They must +// be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful, and may +// not be used concurrently. Any nonces are used as IVs, so they must be +// unpredictable. They only accept an |ad| parameter of length 11 (the standard +// TLS one with length omitted). + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void); + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void); + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void); + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void); + +// EVP_aead_aes_128_gcm_tls12 is AES-128 in Galois Counter Mode using the TLS +// 1.2 nonce construction. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_tls12(void); + +// EVP_aead_aes_256_gcm_tls12 is AES-256 in Galois Counter Mode using the TLS +// 1.2 nonce construction. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_tls12(void); + +// EVP_aead_aes_128_gcm_tls13 is AES-128 in Galois Counter Mode using the TLS +// 1.3 nonce construction. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_tls13(void); + +// EVP_aead_aes_256_gcm_tls13 is AES-256 in Galois Counter Mode using the TLS +// 1.3 nonce construction. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_tls13(void); + + +// Obscure functions. + +// evp_aead_direction_t denotes the direction of an AEAD operation. +enum evp_aead_direction_t { + evp_aead_open, + evp_aead_seal, +}; + +// EVP_AEAD_CTX_init_with_direction calls |EVP_AEAD_CTX_init| for normal +// AEADs. For TLS-specific and SSL3-specific AEADs, it initializes |ctx| for a +// given direction. +OPENSSL_EXPORT int EVP_AEAD_CTX_init_with_direction( + EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, const uint8_t *key, size_t key_len, + size_t tag_len, enum evp_aead_direction_t dir); + +// EVP_AEAD_CTX_get_iv sets |*out_len| to the length of the IV for |ctx| and +// sets |*out_iv| to point to that many bytes of the current IV. This is only +// meaningful for AEADs with implicit IVs (i.e. CBC mode in TLS 1.0). +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_AEAD_CTX_get_iv(const EVP_AEAD_CTX *ctx, + const uint8_t **out_iv, size_t *out_len); + +// EVP_AEAD_CTX_tag_len computes the exact byte length of the tag written by +// |EVP_AEAD_CTX_seal_scatter| and writes it to |*out_tag_len|. It returns one +// on success or zero on error. |in_len| and |extra_in_len| must equal the +// arguments of the same names passed to |EVP_AEAD_CTX_seal_scatter|. +OPENSSL_EXPORT int EVP_AEAD_CTX_tag_len(const EVP_AEAD_CTX *ctx, + size_t *out_tag_len, + const size_t in_len, + const size_t extra_in_len); + + +#if defined(__cplusplus) +} // extern C + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +using ScopedEVP_AEAD_CTX = + internal::StackAllocated; + +BORINGSSL_MAKE_DELETER(EVP_AEAD_CTX, EVP_AEAD_CTX_free) + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#endif + +#endif // OPENSSL_HEADER_AEAD_H diff --git a/lib/boringssl/include/openssl/aes.h b/lib/boringssl/include/openssl/aes.h new file mode 100644 index 00000000..496ec90d --- /dev/null +++ b/lib/boringssl/include/openssl/aes.h @@ -0,0 +1,207 @@ +/* ==================================================================== + * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#ifndef OPENSSL_HEADER_AES_H +#define OPENSSL_HEADER_AES_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Raw AES functions. + + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +// AES_MAXNR is the maximum number of AES rounds. +#define AES_MAXNR 14 + +#define AES_BLOCK_SIZE 16 + +// aes_key_st should be an opaque type, but EVP requires that the size be +// known. +struct aes_key_st { + uint32_t rd_key[4 * (AES_MAXNR + 1)]; + unsigned rounds; +}; +typedef struct aes_key_st AES_KEY; + +// AES_set_encrypt_key configures |aeskey| to encrypt with the |bits|-bit key, +// |key|. |key| must point to |bits|/8 bytes. It returns zero on success and a +// negative number if |bits| is an invalid AES key size. +// +// WARNING: this function breaks the usual return value convention. +OPENSSL_EXPORT int AES_set_encrypt_key(const uint8_t *key, unsigned bits, + AES_KEY *aeskey); + +// AES_set_decrypt_key configures |aeskey| to decrypt with the |bits|-bit key, +// |key|. |key| must point to |bits|/8 bytes. It returns zero on success and a +// negative number if |bits| is an invalid AES key size. +// +// WARNING: this function breaks the usual return value convention. +OPENSSL_EXPORT int AES_set_decrypt_key(const uint8_t *key, unsigned bits, + AES_KEY *aeskey); + +// AES_encrypt encrypts a single block from |in| to |out| with |key|. The |in| +// and |out| pointers may overlap. +OPENSSL_EXPORT void AES_encrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key); + +// AES_decrypt decrypts a single block from |in| to |out| with |key|. The |in| +// and |out| pointers may overlap. +OPENSSL_EXPORT void AES_decrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key); + + +// Block cipher modes. + +// AES_ctr128_encrypt encrypts (or decrypts, it's the same in CTR mode) |len| +// bytes from |in| to |out|. The |num| parameter must be set to zero on the +// first call and |ivec| will be incremented. This function may be called +// in-place with |in| equal to |out|, but otherwise the buffers may not +// partially overlap. A partial overlap may overwrite input data before it is +// read. +OPENSSL_EXPORT void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, + size_t len, const AES_KEY *key, + uint8_t ivec[AES_BLOCK_SIZE], + uint8_t ecount_buf[AES_BLOCK_SIZE], + unsigned int *num); + +// AES_ecb_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) a single, +// 16 byte block from |in| to |out|. This function may be called in-place with +// |in| equal to |out|, but otherwise the buffers may not partially overlap. A +// partial overlap may overwrite input data before it is read. +OPENSSL_EXPORT void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key, const int enc); + +// AES_cbc_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) |len| +// bytes from |in| to |out|. The length must be a multiple of the block size. +// This function may be called in-place with |in| equal to |out|, but otherwise +// the buffers may not partially overlap. A partial overlap may overwrite input +// data before it is read. +OPENSSL_EXPORT void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const AES_KEY *key, uint8_t *ivec, + const int enc); + +// AES_ofb128_encrypt encrypts (or decrypts, it's the same in OFB mode) |len| +// bytes from |in| to |out|. The |num| parameter must be set to zero on the +// first call. This function may be called in-place with |in| equal to |out|, +// but otherwise the buffers may not partially overlap. A partial overlap may +// overwrite input data before it is read. +OPENSSL_EXPORT void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, + size_t len, const AES_KEY *key, + uint8_t *ivec, int *num); + +// AES_cfb128_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) |len| +// bytes from |in| to |out|. The |num| parameter must be set to zero on the +// first call. This function may be called in-place with |in| equal to |out|, +// but otherwise the buffers may not partially overlap. A partial overlap may +// overwrite input data before it is read. +OPENSSL_EXPORT void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, + size_t len, const AES_KEY *key, + uint8_t *ivec, int *num, int enc); + + +// AES key wrap. +// +// These functions implement AES Key Wrap mode, as defined in RFC 3394. They +// should never be used except to interoperate with existing systems that use +// this mode. + +// AES_wrap_key performs AES key wrap on |in| which must be a multiple of 8 +// bytes. |iv| must point to an 8 byte value or be NULL to use the default IV. +// |key| must have been configured for encryption. On success, it writes +// |in_len| + 8 bytes to |out| and returns |in_len| + 8. Otherwise, it returns +// -1. +OPENSSL_EXPORT int AES_wrap_key(const AES_KEY *key, const uint8_t *iv, + uint8_t *out, const uint8_t *in, size_t in_len); + +// AES_unwrap_key performs AES key unwrap on |in| which must be a multiple of 8 +// bytes. |iv| must point to an 8 byte value or be NULL to use the default IV. +// |key| must have been configured for decryption. On success, it writes +// |in_len| - 8 bytes to |out| and returns |in_len| - 8. Otherwise, it returns +// -1. +OPENSSL_EXPORT int AES_unwrap_key(const AES_KEY *key, const uint8_t *iv, + uint8_t *out, const uint8_t *in, + size_t in_len); + + +// AES key wrap with padding. +// +// These functions implement AES Key Wrap with Padding mode, as defined in RFC +// 5649. They should never be used except to interoperate with existing systems +// that use this mode. + +// AES_wrap_key_padded performs a padded AES key wrap on |in| which must be +// between 1 and 2^32-1 bytes. |key| must have been configured for encryption. +// On success it writes at most |max_out| bytes of ciphertext to |out|, sets +// |*out_len| to the number of bytes written, and returns one. On failure it +// returns zero. To ensure success, set |max_out| to at least |in_len| + 15. +OPENSSL_EXPORT int AES_wrap_key_padded(const AES_KEY *key, uint8_t *out, + size_t *out_len, size_t max_out, + const uint8_t *in, size_t in_len); + +// AES_unwrap_key_padded performs a padded AES key unwrap on |in| which must be +// a multiple of 8 bytes. |key| must have been configured for decryption. On +// success it writes at most |max_out| bytes to |out|, sets |*out_len| to the +// number of bytes written, and returns one. On failure it returns zero. Setting +// |max_out| to |in_len| is a sensible estimate. +OPENSSL_EXPORT int AES_unwrap_key_padded(const AES_KEY *key, uint8_t *out, + size_t *out_len, size_t max_out, + const uint8_t *in, size_t in_len); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_AES_H diff --git a/lib/boringssl/include/openssl/arm_arch.h b/lib/boringssl/include/openssl/arm_arch.h new file mode 100644 index 00000000..7215f62e --- /dev/null +++ b/lib/boringssl/include/openssl/arm_arch.h @@ -0,0 +1,220 @@ +/* ==================================================================== + * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_ARM_ARCH_H +#define OPENSSL_HEADER_ARM_ARCH_H + +// arm_arch.h contains symbols used by ARM assembly, and the C code that calls +// it. It is included as a public header to simplify the build, but is not +// intended for external use. + +#if defined(__ARMEL__) || defined(_M_ARM) || defined(__AARCH64EL__) || \ + defined(_M_ARM64) + +// ARMV7_NEON is true when a NEON unit is present in the current CPU. +#define ARMV7_NEON (1 << 0) + +// ARMV8_AES indicates support for hardware AES instructions. +#define ARMV8_AES (1 << 2) + +// ARMV8_SHA1 indicates support for hardware SHA-1 instructions. +#define ARMV8_SHA1 (1 << 3) + +// ARMV8_SHA256 indicates support for hardware SHA-256 instructions. +#define ARMV8_SHA256 (1 << 4) + +// ARMV8_PMULL indicates support for carryless multiplication. +#define ARMV8_PMULL (1 << 5) + +// ARMV8_SHA512 indicates support for hardware SHA-512 instructions. +#define ARMV8_SHA512 (1 << 6) + +#if defined(__ASSEMBLER__) + +// We require the ARM assembler provide |__ARM_ARCH| from Arm C Language +// Extensions (ACLE). This is supported in GCC 4.8+ and Clang 3.2+. MSVC does +// not implement ACLE, but we require Clang's assembler on Windows. +#if !defined(__ARM_ARCH) +#error "ARM assembler must define __ARM_ARCH" +#endif + +// __ARM_ARCH__ is used by OpenSSL assembly to determine the minimum target ARM +// version. +// +// TODO(davidben): Switch the assembly to use |__ARM_ARCH| directly. +#define __ARM_ARCH__ __ARM_ARCH + +// Even when building for 32-bit ARM, support for aarch64 crypto instructions +// will be included. +#define __ARM_MAX_ARCH__ 8 + +// Support macros for +// - Armv8.3-A Pointer Authentication and +// - Armv8.5-A Branch Target Identification +// features which require emitting a .note.gnu.property section with the +// appropriate architecture-dependent feature bits set. +// +// |AARCH64_SIGN_LINK_REGISTER| and |AARCH64_VALIDATE_LINK_REGISTER| expand to +// PACIxSP and AUTIxSP, respectively. |AARCH64_SIGN_LINK_REGISTER| should be +// used immediately before saving the LR register (x30) to the stack. +// |AARCH64_VALIDATE_LINK_REGISTER| should be used immediately after restoring +// it. Note |AARCH64_SIGN_LINK_REGISTER|'s modifications to LR must be undone +// with |AARCH64_VALIDATE_LINK_REGISTER| before RET. The SP register must also +// have the same value at the two points. For example: +// +// .global f +// f: +// AARCH64_SIGN_LINK_REGISTER +// stp x29, x30, [sp, #-96]! +// mov x29, sp +// ... +// ldp x29, x30, [sp], #96 +// AARCH64_VALIDATE_LINK_REGISTER +// ret +// +// |AARCH64_VALID_CALL_TARGET| expands to BTI 'c'. Either it, or +// |AARCH64_SIGN_LINK_REGISTER|, must be used at every point that may be an +// indirect call target. In particular, all symbols exported from a file must +// begin with one of these macros. For example, a leaf function that does not +// save LR can instead use |AARCH64_VALID_CALL_TARGET|: +// +// .globl return_zero +// return_zero: +// AARCH64_VALID_CALL_TARGET +// mov x0, #0 +// ret +// +// A non-leaf function which does not immediately save LR may need both macros +// because |AARCH64_SIGN_LINK_REGISTER| appears late. For example, the function +// may jump to an alternate implementation before setting up the stack: +// +// .globl with_early_jump +// with_early_jump: +// AARCH64_VALID_CALL_TARGET +// cmp x0, #128 +// b.lt .Lwith_early_jump_128 +// AARCH64_SIGN_LINK_REGISTER +// stp x29, x30, [sp, #-96]! +// mov x29, sp +// ... +// ldp x29, x30, [sp], #96 +// AARCH64_VALIDATE_LINK_REGISTER +// ret +// +// .Lwith_early_jump_128: +// ... +// ret +// +// These annotations are only required with indirect calls. Private symbols that +// are only the target of direct calls do not require annotations. Also note +// that |AARCH64_VALID_CALL_TARGET| is only valid for indirect calls (BLR), not +// indirect jumps (BR). Indirect jumps in assembly are currently not supported +// and would require a macro for BTI 'j'. +// +// Although not necessary, it is safe to use these macros in 32-bit ARM +// assembly. This may be used to simplify dual 32-bit and 64-bit files. +// +// References: +// - "ELF for the Arm® 64-bit Architecture" +// https://github.com/ARM-software/abi-aa/blob/master/aaelf64/aaelf64.rst +// - "Providing protection for complex software" +// https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software + +#if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1 +#define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has Branch Target Identification +#define AARCH64_VALID_CALL_TARGET hint #34 // BTI 'c' +#else +#define GNU_PROPERTY_AARCH64_BTI 0 // No Branch Target Identification +#define AARCH64_VALID_CALL_TARGET +#endif + +#if defined(__ARM_FEATURE_PAC_DEFAULT) && \ + (__ARM_FEATURE_PAC_DEFAULT & 1) == 1 // Signed with A-key +#define GNU_PROPERTY_AARCH64_POINTER_AUTH \ + (1 << 1) // Has Pointer Authentication +#define AARCH64_SIGN_LINK_REGISTER hint #25 // PACIASP +#define AARCH64_VALIDATE_LINK_REGISTER hint #29 // AUTIASP +#elif defined(__ARM_FEATURE_PAC_DEFAULT) && \ + (__ARM_FEATURE_PAC_DEFAULT & 2) == 2 // Signed with B-key +#define GNU_PROPERTY_AARCH64_POINTER_AUTH \ + (1 << 1) // Has Pointer Authentication +#define AARCH64_SIGN_LINK_REGISTER hint #27 // PACIBSP +#define AARCH64_VALIDATE_LINK_REGISTER hint #31 // AUTIBSP +#else +#define GNU_PROPERTY_AARCH64_POINTER_AUTH 0 // No Pointer Authentication +#if GNU_PROPERTY_AARCH64_BTI != 0 +#define AARCH64_SIGN_LINK_REGISTER AARCH64_VALID_CALL_TARGET +#else +#define AARCH64_SIGN_LINK_REGISTER +#endif +#define AARCH64_VALIDATE_LINK_REGISTER +#endif + +#if GNU_PROPERTY_AARCH64_POINTER_AUTH != 0 || GNU_PROPERTY_AARCH64_BTI != 0 +.pushsection .note.gnu.property, "a"; +.balign 8; +.long 4; +.long 0x10; +.long 0x5; +.asciz "GNU"; +.long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ +.long 4; +.long (GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_BTI); +.long 0; +.popsection; +#endif + +#endif // __ASSEMBLER__ + +#endif // __ARMEL__ || _M_ARM || __AARCH64EL__ || _M_ARM64 + +#endif // OPENSSL_HEADER_ARM_ARCH_H diff --git a/lib/boringssl/include/openssl/asn1.h b/lib/boringssl/include/openssl/asn1.h new file mode 100644 index 00000000..d128c8df --- /dev/null +++ b/lib/boringssl/include/openssl/asn1.h @@ -0,0 +1,2065 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef OPENSSL_HEADER_ASN1_H +#define OPENSSL_HEADER_ASN1_H + +#include + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Legacy ASN.1 library. +// +// This header is part of OpenSSL's ASN.1 implementation. It is retained for +// compatibility but should not be used by new code. The functions are difficult +// to use correctly, and have buggy or non-standard behaviors. They are thus +// particularly prone to behavior changes and API removals, as BoringSSL +// iterates on these issues. +// +// Use the new |CBS| and |CBB| library in instead. + + +// Tag constants. +// +// These constants are used in various APIs to specify ASN.1 types and tag +// components. See the specific API's documentation for details on which values +// are used and how. + +// The following constants are tag classes. +#define V_ASN1_UNIVERSAL 0x00 +#define V_ASN1_APPLICATION 0x40 +#define V_ASN1_CONTEXT_SPECIFIC 0x80 +#define V_ASN1_PRIVATE 0xc0 + +// V_ASN1_CONSTRUCTED indicates an element is constructed, rather than +// primitive. +#define V_ASN1_CONSTRUCTED 0x20 + +// V_ASN1_PRIMITIVE_TAG is the highest tag number which can be encoded in a +// single byte. Note this is unrelated to whether an element is constructed or +// primitive. +// +// TODO(davidben): Make this private. +#define V_ASN1_PRIMITIVE_TAG 0x1f + +// V_ASN1_MAX_UNIVERSAL is the highest supported universal tag number. It is +// necessary to avoid ambiguity with |V_ASN1_NEG| and |MBSTRING_FLAG|. +// +// TODO(davidben): Make this private. +#define V_ASN1_MAX_UNIVERSAL 0xff + +// V_ASN1_UNDEF is used in some APIs to indicate an ASN.1 element is omitted. +#define V_ASN1_UNDEF (-1) + +// V_ASN1_OTHER is used in |ASN1_TYPE| to indicate a non-universal ASN.1 type. +#define V_ASN1_OTHER (-3) + +// V_ASN1_ANY is used by the ASN.1 templates to indicate an ANY type. +#define V_ASN1_ANY (-4) + +// The following constants are tag numbers for universal types. +#define V_ASN1_EOC 0 +#define V_ASN1_BOOLEAN 1 +#define V_ASN1_INTEGER 2 +#define V_ASN1_BIT_STRING 3 +#define V_ASN1_OCTET_STRING 4 +#define V_ASN1_NULL 5 +#define V_ASN1_OBJECT 6 +#define V_ASN1_OBJECT_DESCRIPTOR 7 +#define V_ASN1_EXTERNAL 8 +#define V_ASN1_REAL 9 +#define V_ASN1_ENUMERATED 10 +#define V_ASN1_UTF8STRING 12 +#define V_ASN1_SEQUENCE 16 +#define V_ASN1_SET 17 +#define V_ASN1_NUMERICSTRING 18 +#define V_ASN1_PRINTABLESTRING 19 +#define V_ASN1_T61STRING 20 +#define V_ASN1_TELETEXSTRING 20 +#define V_ASN1_VIDEOTEXSTRING 21 +#define V_ASN1_IA5STRING 22 +#define V_ASN1_UTCTIME 23 +#define V_ASN1_GENERALIZEDTIME 24 +#define V_ASN1_GRAPHICSTRING 25 +#define V_ASN1_ISO64STRING 26 +#define V_ASN1_VISIBLESTRING 26 +#define V_ASN1_GENERALSTRING 27 +#define V_ASN1_UNIVERSALSTRING 28 +#define V_ASN1_BMPSTRING 30 + +// The following constants are used for |ASN1_STRING| values that represent +// negative INTEGER and ENUMERATED values. See |ASN1_STRING| for more details. +#define V_ASN1_NEG 0x100 +#define V_ASN1_NEG_INTEGER (V_ASN1_INTEGER | V_ASN1_NEG) +#define V_ASN1_NEG_ENUMERATED (V_ASN1_ENUMERATED | V_ASN1_NEG) + +// The following constants are bitmask representations of ASN.1 types. +#define B_ASN1_NUMERICSTRING 0x0001 +#define B_ASN1_PRINTABLESTRING 0x0002 +#define B_ASN1_T61STRING 0x0004 +#define B_ASN1_TELETEXSTRING 0x0004 +#define B_ASN1_VIDEOTEXSTRING 0x0008 +#define B_ASN1_IA5STRING 0x0010 +#define B_ASN1_GRAPHICSTRING 0x0020 +#define B_ASN1_ISO64STRING 0x0040 +#define B_ASN1_VISIBLESTRING 0x0040 +#define B_ASN1_GENERALSTRING 0x0080 +#define B_ASN1_UNIVERSALSTRING 0x0100 +#define B_ASN1_OCTET_STRING 0x0200 +#define B_ASN1_BIT_STRING 0x0400 +#define B_ASN1_BMPSTRING 0x0800 +#define B_ASN1_UNKNOWN 0x1000 +#define B_ASN1_UTF8STRING 0x2000 +#define B_ASN1_UTCTIME 0x4000 +#define B_ASN1_GENERALIZEDTIME 0x8000 +#define B_ASN1_SEQUENCE 0x10000 + +// ASN1_tag2bit converts |tag| from the tag number of a universal type to a +// corresponding |B_ASN1_*| constant, |B_ASN1_UNKNOWN|, or zero. If the +// |B_ASN1_*| constant above is defined, it will map the corresponding +// |V_ASN1_*| constant to it. Otherwise, whether it returns |B_ASN1_UNKNOWN| or +// zero is ill-defined and callers should not rely on it. +// +// TODO(https://crbug.com/boringssl/412): Figure out what |B_ASN1_UNNOWN| vs +// zero is meant to be. The main impact is what values go in |B_ASN1_PRINTABLE|. +// To that end, we must return zero on types that can't go in |ASN1_STRING|. +OPENSSL_EXPORT unsigned long ASN1_tag2bit(int tag); + +// ASN1_tag2str returns a string representation of |tag|, interpret as a tag +// number for a universal type, or |V_ASN1_NEG_*|. +OPENSSL_EXPORT const char *ASN1_tag2str(int tag); + + +// API conventions. +// +// The following sample functions document the calling conventions used by +// legacy ASN.1 APIs. + +#if 0 // Sample functions + +// d2i_SAMPLE parses a structure from up to |len| bytes at |*inp|. On success, +// it advances |*inp| by the number of bytes read and returns a newly-allocated +// |SAMPLE| object containing the parsed structure. If |out| is non-NULL, it +// additionally frees the previous value at |*out| and updates |*out| to the +// result. If parsing or allocating the result fails, it returns NULL. +// +// This function does not reject trailing data in the input. This allows the +// caller to parse a sequence of concatenated structures. Callers parsing only +// one structure should check for trailing data by comparing the updated |*inp| +// with the end of the input. +// +// Note: If |out| and |*out| are both non-NULL, the object at |*out| is not +// updated in-place. Instead, it is freed, and the pointer is updated to the +// new object. This differs from OpenSSL. Callers are recommended to set |out| +// to NULL and instead use the return value. +SAMPLE *d2i_SAMPLE(SAMPLE **out, const uint8_t **inp, long len); + +// i2d_SAMPLE marshals |in|. On error, it returns a negative value. On success, +// it returns the length of the result and outputs it via |outp| as follows: +// +// If |outp| is NULL, the function writes nothing. This mode can be used to size +// buffers. +// +// If |outp| is non-NULL but |*outp| is NULL, the function sets |*outp| to a +// newly-allocated buffer containing the result. The caller is responsible for +// releasing |*outp| with |OPENSSL_free|. This mode is recommended for most +// callers. +// +// If |outp| and |*outp| are non-NULL, the function writes the result to +// |*outp|, which must have enough space available, and advances |*outp| just +// past the output. +// +// WARNING: In the third mode, the function does not internally check output +// bounds. Failing to correctly size the buffer will result in a potentially +// exploitable memory error. +int i2d_SAMPLE(const SAMPLE *in, uint8_t **outp); + +#endif // Sample functions + +// The following typedefs are sometimes used for pointers to functions like +// |d2i_SAMPLE| and |i2d_SAMPLE|. Note, however, that these act on |void*|. +// Calling a function with a different pointer type is undefined in C, so this +// is only valid with a wrapper. +typedef void *d2i_of_void(void **, const unsigned char **, long); +typedef int i2d_of_void(const void *, unsigned char **); + + +// ASN.1 types. +// +// An |ASN1_ITEM| represents an ASN.1 type and allows working with ASN.1 types +// generically. +// +// |ASN1_ITEM|s use a different namespace from C types and are accessed via +// |ASN1_ITEM_*| macros. So, for example, |ASN1_OCTET_STRING| is both a C type +// and the name of an |ASN1_ITEM|, referenced as +// |ASN1_ITEM_rptr(ASN1_OCTET_STRING)|. +// +// Each |ASN1_ITEM| has a corresponding C type, typically with the same name, +// which represents values in the ASN.1 type. This type is either a pointer type +// or |ASN1_BOOLEAN|. When it is a pointer, NULL pointers represent omitted +// values. For example, an OCTET STRING value is declared with the C type +// |ASN1_OCTET_STRING*| and uses the |ASN1_ITEM| named |ASN1_OCTET_STRING|. An +// OPTIONAL OCTET STRING uses the same C type and represents an omitted value +// with a NULL pointer. |ASN1_BOOLEAN| is described in a later section. + +// DECLARE_ASN1_ITEM declares an |ASN1_ITEM| with name |name|. The |ASN1_ITEM| +// may be referenced with |ASN1_ITEM_rptr|. Uses of this macro should document +// the corresponding ASN.1 and C types. +#define DECLARE_ASN1_ITEM(name) extern OPENSSL_EXPORT const ASN1_ITEM name##_it; + +// ASN1_ITEM_rptr returns the |const ASN1_ITEM *| named |name|. +#define ASN1_ITEM_rptr(name) (&(name##_it)) + +// ASN1_ITEM_EXP is an abstraction for referencing an |ASN1_ITEM| in a +// constant-initialized structure, such as a method table. It exists because, on +// some OpenSSL platforms, |ASN1_ITEM| references are indirected through +// functions. Structures reference the |ASN1_ITEM| by declaring a field like +// |ASN1_ITEM_EXP *item| and initializing it with |ASN1_ITEM_ref|. +typedef const ASN1_ITEM ASN1_ITEM_EXP; + +// ASN1_ITEM_ref returns an |ASN1_ITEM_EXP*| for the |ASN1_ITEM| named |name|. +#define ASN1_ITEM_ref(name) (&(name##_it)) + +// ASN1_ITEM_ptr converts |iptr|, which must be an |ASN1_ITEM_EXP*| to a +// |const ASN1_ITEM*|. +#define ASN1_ITEM_ptr(iptr) (iptr) + +// ASN1_VALUE_st (aka |ASN1_VALUE|) is an opaque type used as a placeholder for +// the C type corresponding to an |ASN1_ITEM|. +typedef struct ASN1_VALUE_st ASN1_VALUE; + +// ASN1_item_new allocates a new value of the C type corresponding to |it|, or +// NULL on error. On success, the caller must release the value with +// |ASN1_item_free|, or the corresponding C type's free function, when done. The +// new value will initialize fields of the value to some default state, such as +// an empty string. Note, however, that this default state sometimes omits +// required values, such as with CHOICE types. +// +// This function may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +// +// WARNING: Casting the result of this function to the wrong type is a +// potentially exploitable memory error. Callers must ensure the value is used +// consistently with |it|. Prefer using type-specific functions such as +// |ASN1_OCTET_STRING_new|. +OPENSSL_EXPORT ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); + +// ASN1_item_free releases memory associated with |val|, which must be an object +// of the C type corresponding to |it|. +// +// This function may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +// +// WARNING: Passing a pointer of the wrong type into this function is a +// potentially exploitable memory error. Callers must ensure |val| is consistent +// with |it|. Prefer using type-specific functions such as +// |ASN1_OCTET_STRING_free|. +OPENSSL_EXPORT void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); + +// ASN1_item_d2i parses the ASN.1 type |it| from up to |len| bytes at |*inp|. +// It behaves like |d2i_SAMPLE|, except that |out| and the return value are cast +// to |ASN1_VALUE| pointers. +// +// TODO(https://crbug.com/boringssl/444): C strict aliasing forbids type-punning +// |T*| and |ASN1_VALUE*| the way this function signature does. When that bug is +// resolved, we will need to pick which type |*out| is (probably |T*|). Do not +// use a non-NULL |out| to avoid ending up on the wrong side of this question. +// +// This function may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +// +// WARNING: Casting the result of this function to the wrong type, or passing a +// pointer of the wrong type into this function, are potentially exploitable +// memory errors. Callers must ensure |out| is consistent with |it|. Prefer +// using type-specific functions such as |d2i_ASN1_OCTET_STRING|. +OPENSSL_EXPORT ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **out, + const unsigned char **inp, long len, + const ASN1_ITEM *it); + +// ASN1_item_i2d marshals |val| as the ASN.1 type associated with |it|, as +// described in |i2d_SAMPLE|. +// +// This function may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +// +// WARNING: Passing a pointer of the wrong type into this function is a +// potentially exploitable memory error. Callers must ensure |val| is consistent +// with |it|. Prefer using type-specific functions such as +// |i2d_ASN1_OCTET_STRING|. +OPENSSL_EXPORT int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **outp, + const ASN1_ITEM *it); + +// ASN1_item_dup returns a newly-allocated copy of |x|, or NULL on error. |x| +// must be an object of |it|'s C type. +// +// This function may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +// +// WARNING: Casting the result of this function to the wrong type, or passing a +// pointer of the wrong type into this function, are potentially exploitable +// memory errors. Prefer using type-specific functions such as +// |ASN1_STRING_dup|. +OPENSSL_EXPORT void *ASN1_item_dup(const ASN1_ITEM *it, void *x); + +// The following functions behave like |ASN1_item_d2i| but read from |in| +// instead. |out| is the same parameter as in |ASN1_item_d2i|, but written with +// |void*| instead. The return values similarly match. +// +// These functions may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +// +// WARNING: These functions do not bound how much data is read from |in|. +// Parsing an untrusted input could consume unbounded memory. +OPENSSL_EXPORT void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *out); +OPENSSL_EXPORT void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *out); + +// The following functions behave like |ASN1_item_i2d| but write to |out| +// instead. |in| is the same parameter as in |ASN1_item_i2d|, but written with +// |void*| instead. +// +// These functions may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +OPENSSL_EXPORT int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *in); +OPENSSL_EXPORT int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *in); + +// ASN1_item_unpack parses |oct|'s contents as |it|'s ASN.1 type. It returns a +// newly-allocated instance of |it|'s C type on success, or NULL on error. +// +// This function may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +// +// WARNING: Casting the result of this function to the wrong type is a +// potentially exploitable memory error. Callers must ensure the value is used +// consistently with |it|. +OPENSSL_EXPORT void *ASN1_item_unpack(const ASN1_STRING *oct, + const ASN1_ITEM *it); + +// ASN1_item_pack marshals |obj| as |it|'s ASN.1 type. If |out| is NULL, it +// returns a newly-allocated |ASN1_STRING| with the result, or NULL on error. +// If |out| is non-NULL, but |*out| is NULL, it does the same but additionally +// sets |*out| to the result. If both |out| and |*out| are non-NULL, it writes +// the result to |*out| and returns |*out| on success or NULL on error. +// +// This function may not be used with |ASN1_ITEM|s whose C type is +// |ASN1_BOOLEAN|. +// +// WARNING: Passing a pointer of the wrong type into this function is a +// potentially exploitable memory error. Callers must ensure |val| is consistent +// with |it|. +OPENSSL_EXPORT ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, + ASN1_STRING **out); + + +// Booleans. +// +// This library represents ASN.1 BOOLEAN values with |ASN1_BOOLEAN|, which is an +// integer type. FALSE is zero, TRUE is 0xff, and an omitted OPTIONAL BOOLEAN is +// -1. + +// ASN1_BOOLEAN_FALSE is FALSE as an |ASN1_BOOLEAN|. +#define ASN1_BOOLEAN_FALSE 0 + +// ASN1_BOOLEAN_TRUE is TRUE as an |ASN1_BOOLEAN|. Some code incorrectly uses +// 1, so prefer |b != ASN1_BOOLEAN_FALSE| over |b == ASN1_BOOLEAN_TRUE|. +#define ASN1_BOOLEAN_TRUE 0xff + +// ASN1_BOOLEAN_NONE, in contexts where the |ASN1_BOOLEAN| represents an +// OPTIONAL BOOLEAN, is an omitted value. Using this value in other contexts is +// undefined and may be misinterpreted as TRUE. +#define ASN1_BOOLEAN_NONE (-1) + +// d2i_ASN1_BOOLEAN parses a DER-encoded ASN.1 BOOLEAN from up to |len| bytes at +// |*inp|. On success, it advances |*inp| by the number of bytes read and +// returns the result. If |out| is non-NULL, it additionally writes the result +// to |*out|. On error, it returns |ASN1_BOOLEAN_NONE|. +// +// This function does not reject trailing data in the input. This allows the +// caller to parse a sequence of concatenated structures. Callers parsing only +// one structure should check for trailing data by comparing the updated |*inp| +// with the end of the input. +// +// WARNING: This function's is slightly different from other |d2i_*| functions +// because |ASN1_BOOLEAN| is not a pointer type. +OPENSSL_EXPORT ASN1_BOOLEAN d2i_ASN1_BOOLEAN(ASN1_BOOLEAN *out, + const unsigned char **inp, + long len); + +// i2d_ASN1_BOOLEAN marshals |a| as a DER-encoded ASN.1 BOOLEAN, as described in +// |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_BOOLEAN(ASN1_BOOLEAN a, unsigned char **outp); + +// The following |ASN1_ITEM|s have ASN.1 type BOOLEAN and C type |ASN1_BOOLEAN|. +// |ASN1_TBOOLEAN| and |ASN1_FBOOLEAN| must be marked OPTIONAL. When omitted, +// they are parsed as TRUE and FALSE, respectively, rather than +// |ASN1_BOOLEAN_NONE|. +DECLARE_ASN1_ITEM(ASN1_BOOLEAN) +DECLARE_ASN1_ITEM(ASN1_TBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_FBOOLEAN) + + +// Strings. +// +// ASN.1 contains a myriad of string types, as well as types that contain data +// that may be encoded into a string. This library uses a single type, +// |ASN1_STRING|, to represent most values. + +// An asn1_string_st (aka |ASN1_STRING|) represents a value of a string-like +// ASN.1 type. It contains a |type| field, and a byte string |data| field with a +// type-specific representation. +// +// If |type| is one of |V_ASN1_OCTET_STRING|, |V_ASN1_UTF8STRING|, +// |V_ASN1_NUMERICSTRING|, |V_ASN1_PRINTABLESTRING|, |V_ASN1_T61STRING|, +// |V_ASN1_VIDEOTEXSTRING|, |V_ASN1_IA5STRING|, |V_ASN1_GRAPHICSTRING|, +// |V_ASN1_ISO64STRING|, |V_ASN1_VISIBLESTRING|, |V_ASN1_GENERALSTRING|, +// |V_ASN1_UNIVERSALSTRING|, or |V_ASN1_BMPSTRING|, the object represents an +// ASN.1 string type. The data contains the byte representation of the +// string. +// +// If |type| is |V_ASN1_BIT_STRING|, the object represents a BIT STRING value. +// See bit string documentation below for the data and flags. +// +// If |type| is one of |V_ASN1_INTEGER|, |V_ASN1_NEG_INTEGER|, +// |V_ASN1_ENUMERATED|, or |V_ASN1_NEG_ENUMERATED|, the object represents an +// INTEGER or ENUMERATED value. See integer documentation below for details. +// +// If |type| is |V_ASN1_GENERALIZEDTIME| or |V_ASN1_UTCTIME|, the object +// represents a GeneralizedTime or UTCTime value, respectively. The data +// contains the DER encoding of the value. For example, the UNIX epoch would be +// "19700101000000Z" for a GeneralizedTime and "700101000000Z" for a UTCTime. +// +// If |type| is |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or |V_ASN1_OTHER|, the object +// represents a SEQUENCE, SET, or arbitrary ASN.1 value, respectively. Unlike +// the above cases, the data contains the DER encoding of the entire structure, +// including the header. If the value is explicitly or implicitly tagged, this +// too will be reflected in the data field. As this case handles unknown types, +// the contents are not checked when parsing or serializing. +// +// Other values of |type| do not represent a valid ASN.1 value, though +// default-constructed objects may set |type| to -1. Such objects cannot be +// serialized. +// +// |ASN1_STRING| additionally has the following typedefs: |ASN1_BIT_STRING|, +// |ASN1_BMPSTRING|, |ASN1_ENUMERATED|, |ASN1_GENERALIZEDTIME|, +// |ASN1_GENERALSTRING|, |ASN1_IA5STRING|, |ASN1_INTEGER|, |ASN1_OCTET_STRING|, +// |ASN1_PRINTABLESTRING|, |ASN1_T61STRING|, |ASN1_TIME|, +// |ASN1_UNIVERSALSTRING|, |ASN1_UTCTIME|, |ASN1_UTF8STRING|, and +// |ASN1_VISIBLESTRING|. Other than |ASN1_TIME|, these correspond to universal +// ASN.1 types. |ASN1_TIME| represents a CHOICE of UTCTime and GeneralizedTime, +// with a cutoff of 2049, as used in Section 4.1.2.5 of RFC 5280. +// +// For clarity, callers are encouraged to use the appropriate typedef when +// available. They are the same type as |ASN1_STRING|, so a caller may freely +// pass them into functions expecting |ASN1_STRING|, such as +// |ASN1_STRING_length|. +// +// If a function returns an |ASN1_STRING| where the typedef or ASN.1 structure +// implies constraints on |type|, callers may assume that |type| is correct. +// However, if a function takes an |ASN1_STRING| as input, callers must ensure +// |type| matches. These invariants are not captured by the C type system and +// may not be checked at runtime. For example, callers may assume the output of +// |X509_get0_serialNumber| has type |V_ASN1_INTEGER| or |V_ASN1_NEG_INTEGER|. +// Callers must not pass a string of type |V_ASN1_OCTET_STRING| to +// |X509_set_serialNumber|. Doing so may break invariants on the |X509| object +// and break the |X509_get0_serialNumber| invariant. +// +// TODO(https://crbug.com/boringssl/445): This is very unfriendly. Getting the +// type field wrong should not cause memory errors, but it may do strange +// things. We should add runtime checks to anything that consumes |ASN1_STRING|s +// from the caller. +struct asn1_string_st { + int length; + int type; + unsigned char *data; + long flags; +}; + +// ASN1_STRING_FLAG_BITS_LEFT indicates, in a BIT STRING |ASN1_STRING|, that +// flags & 0x7 contains the number of padding bits added to the BIT STRING +// value. When not set, all trailing zero bits in the last byte are implicitly +// treated as padding. This behavior is deprecated and should not be used. +#define ASN1_STRING_FLAG_BITS_LEFT 0x08 + +// ASN1_STRING_type_new returns a newly-allocated empty |ASN1_STRING| object of +// type |type|, or NULL on error. +OPENSSL_EXPORT ASN1_STRING *ASN1_STRING_type_new(int type); + +// ASN1_STRING_new returns a newly-allocated empty |ASN1_STRING| object with an +// arbitrary type. Prefer one of the type-specific constructors, such as +// |ASN1_OCTET_STRING_new|, or |ASN1_STRING_type_new|. +OPENSSL_EXPORT ASN1_STRING *ASN1_STRING_new(void); + +// ASN1_STRING_free releases memory associated with |str|. +OPENSSL_EXPORT void ASN1_STRING_free(ASN1_STRING *str); + +// ASN1_STRING_copy sets |dst| to a copy of |str|. It returns one on success and +// zero on error. +OPENSSL_EXPORT int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str); + +// ASN1_STRING_dup returns a newly-allocated copy of |str|, or NULL on error. +OPENSSL_EXPORT ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str); + +// ASN1_STRING_type returns the type of |str|. This value will be one of the +// |V_ASN1_*| constants. +OPENSSL_EXPORT int ASN1_STRING_type(const ASN1_STRING *str); + +// ASN1_STRING_get0_data returns a pointer to |str|'s contents. Callers should +// use |ASN1_STRING_length| to determine the length of the string. The string +// may have embedded NUL bytes and may not be NUL-terminated. +OPENSSL_EXPORT const unsigned char *ASN1_STRING_get0_data( + const ASN1_STRING *str); + +// ASN1_STRING_data returns a mutable pointer to |str|'s contents. Callers +// should use |ASN1_STRING_length| to determine the length of the string. The +// string may have embedded NUL bytes and may not be NUL-terminated. +// +// Prefer |ASN1_STRING_get0_data|. +OPENSSL_EXPORT unsigned char *ASN1_STRING_data(ASN1_STRING *str); + +// ASN1_STRING_length returns the length of |str|, in bytes. +OPENSSL_EXPORT int ASN1_STRING_length(const ASN1_STRING *str); + +// ASN1_STRING_cmp compares |a| and |b|'s type and contents. It returns an +// integer equal to, less than, or greater than zero if |a| is equal to, less +// than, or greater than |b|, respectively. This function compares by length, +// then data, then type. Note the data compared is the |ASN1_STRING| internal +// representation and the type order is arbitrary. While this comparison is +// suitable for sorting, callers should not rely on the exact order when |a| +// and |b| are different types. +// +// Note that, if |a| and |b| are INTEGERs, this comparison does not order the +// values numerically. For a numerical comparison, use |ASN1_INTEGER_cmp|. +OPENSSL_EXPORT int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b); + +// ASN1_STRING_set sets the contents of |str| to a copy of |len| bytes from +// |data|. It returns one on success and zero on error. If |data| is NULL, it +// updates the length and allocates the buffer as needed, but does not +// initialize the contents. +OPENSSL_EXPORT int ASN1_STRING_set(ASN1_STRING *str, const void *data, + ossl_ssize_t len); + +// ASN1_STRING_set0 sets the contents of |str| to |len| bytes from |data|. It +// takes ownership of |data|, which must have been allocated with +// |OPENSSL_malloc|. +OPENSSL_EXPORT void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); + +// The following functions call |ASN1_STRING_type_new| with the corresponding +// |V_ASN1_*| constant. +OPENSSL_EXPORT ASN1_BMPSTRING *ASN1_BMPSTRING_new(void); +OPENSSL_EXPORT ASN1_GENERALSTRING *ASN1_GENERALSTRING_new(void); +OPENSSL_EXPORT ASN1_IA5STRING *ASN1_IA5STRING_new(void); +OPENSSL_EXPORT ASN1_OCTET_STRING *ASN1_OCTET_STRING_new(void); +OPENSSL_EXPORT ASN1_PRINTABLESTRING *ASN1_PRINTABLESTRING_new(void); +OPENSSL_EXPORT ASN1_T61STRING *ASN1_T61STRING_new(void); +OPENSSL_EXPORT ASN1_UNIVERSALSTRING *ASN1_UNIVERSALSTRING_new(void); +OPENSSL_EXPORT ASN1_UTF8STRING *ASN1_UTF8STRING_new(void); +OPENSSL_EXPORT ASN1_VISIBLESTRING *ASN1_VISIBLESTRING_new(void); + +// The following functions call |ASN1_STRING_free|. +OPENSSL_EXPORT void ASN1_BMPSTRING_free(ASN1_BMPSTRING *str); +OPENSSL_EXPORT void ASN1_GENERALSTRING_free(ASN1_GENERALSTRING *str); +OPENSSL_EXPORT void ASN1_IA5STRING_free(ASN1_IA5STRING *str); +OPENSSL_EXPORT void ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *str); +OPENSSL_EXPORT void ASN1_PRINTABLESTRING_free(ASN1_PRINTABLESTRING *str); +OPENSSL_EXPORT void ASN1_T61STRING_free(ASN1_T61STRING *str); +OPENSSL_EXPORT void ASN1_UNIVERSALSTRING_free(ASN1_UNIVERSALSTRING *str); +OPENSSL_EXPORT void ASN1_UTF8STRING_free(ASN1_UTF8STRING *str); +OPENSSL_EXPORT void ASN1_VISIBLESTRING_free(ASN1_VISIBLESTRING *str); + +// The following functions parse up to |len| bytes from |*inp| as a +// DER-encoded ASN.1 value of the corresponding type, as described in +// |d2i_SAMPLE|. +OPENSSL_EXPORT ASN1_BMPSTRING *d2i_ASN1_BMPSTRING(ASN1_BMPSTRING **out, + const uint8_t **inp, + long len); +OPENSSL_EXPORT ASN1_GENERALSTRING *d2i_ASN1_GENERALSTRING( + ASN1_GENERALSTRING **out, const uint8_t **inp, long len); +OPENSSL_EXPORT ASN1_IA5STRING *d2i_ASN1_IA5STRING(ASN1_IA5STRING **out, + const uint8_t **inp, + long len); +OPENSSL_EXPORT ASN1_OCTET_STRING *d2i_ASN1_OCTET_STRING(ASN1_OCTET_STRING **out, + const uint8_t **inp, + long len); +OPENSSL_EXPORT ASN1_PRINTABLESTRING *d2i_ASN1_PRINTABLESTRING( + ASN1_PRINTABLESTRING **out, const uint8_t **inp, long len); +OPENSSL_EXPORT ASN1_T61STRING *d2i_ASN1_T61STRING(ASN1_T61STRING **out, + const uint8_t **inp, + long len); +OPENSSL_EXPORT ASN1_UNIVERSALSTRING *d2i_ASN1_UNIVERSALSTRING( + ASN1_UNIVERSALSTRING **out, const uint8_t **inp, long len); +OPENSSL_EXPORT ASN1_UTF8STRING *d2i_ASN1_UTF8STRING(ASN1_UTF8STRING **out, + const uint8_t **inp, + long len); +OPENSSL_EXPORT ASN1_VISIBLESTRING *d2i_ASN1_VISIBLESTRING( + ASN1_VISIBLESTRING **out, const uint8_t **inp, long len); + +// The following functions marshal |in| as a DER-encoded ASN.1 value of the +// corresponding type, as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_BMPSTRING(const ASN1_BMPSTRING *in, uint8_t **outp); +OPENSSL_EXPORT int i2d_ASN1_GENERALSTRING(const ASN1_GENERALSTRING *in, + uint8_t **outp); +OPENSSL_EXPORT int i2d_ASN1_IA5STRING(const ASN1_IA5STRING *in, uint8_t **outp); +OPENSSL_EXPORT int i2d_ASN1_OCTET_STRING(const ASN1_OCTET_STRING *in, + uint8_t **outp); +OPENSSL_EXPORT int i2d_ASN1_PRINTABLESTRING(const ASN1_PRINTABLESTRING *in, + uint8_t **outp); +OPENSSL_EXPORT int i2d_ASN1_T61STRING(const ASN1_T61STRING *in, uint8_t **outp); +OPENSSL_EXPORT int i2d_ASN1_UNIVERSALSTRING(const ASN1_UNIVERSALSTRING *in, + uint8_t **outp); +OPENSSL_EXPORT int i2d_ASN1_UTF8STRING(const ASN1_UTF8STRING *in, + uint8_t **outp); +OPENSSL_EXPORT int i2d_ASN1_VISIBLESTRING(const ASN1_VISIBLESTRING *in, + uint8_t **outp); + +// The following |ASN1_ITEM|s have the ASN.1 type referred to in their name and +// C type |ASN1_STRING*|. The C type may also be written as the corresponding +// typedef. +DECLARE_ASN1_ITEM(ASN1_BMPSTRING) +DECLARE_ASN1_ITEM(ASN1_GENERALSTRING) +DECLARE_ASN1_ITEM(ASN1_IA5STRING) +DECLARE_ASN1_ITEM(ASN1_OCTET_STRING) +DECLARE_ASN1_ITEM(ASN1_PRINTABLESTRING) +DECLARE_ASN1_ITEM(ASN1_T61STRING) +DECLARE_ASN1_ITEM(ASN1_UNIVERSALSTRING) +DECLARE_ASN1_ITEM(ASN1_UTF8STRING) +DECLARE_ASN1_ITEM(ASN1_VISIBLESTRING) + +// ASN1_OCTET_STRING_dup calls |ASN1_STRING_dup|. +OPENSSL_EXPORT ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup( + const ASN1_OCTET_STRING *a); + +// ASN1_OCTET_STRING_cmp calls |ASN1_STRING_cmp|. +OPENSSL_EXPORT int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, + const ASN1_OCTET_STRING *b); + +// ASN1_OCTET_STRING_set calls |ASN1_STRING_set|. +OPENSSL_EXPORT int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, + const unsigned char *data, int len); + +// ASN1_STRING_to_UTF8 converts |in| to UTF-8. On success, sets |*out| to a +// newly-allocated buffer containing the resulting string and returns the length +// of the string. The caller must call |OPENSSL_free| to release |*out| when +// done. On error, it returns a negative number. +OPENSSL_EXPORT int ASN1_STRING_to_UTF8(unsigned char **out, + const ASN1_STRING *in); + +// The following formats define encodings for use with functions like +// |ASN1_mbstring_copy|. Note |MBSTRING_ASC| refers to Latin-1, not ASCII. +#define MBSTRING_FLAG 0x1000 +#define MBSTRING_UTF8 (MBSTRING_FLAG) +#define MBSTRING_ASC (MBSTRING_FLAG | 1) +#define MBSTRING_BMP (MBSTRING_FLAG | 2) +#define MBSTRING_UNIV (MBSTRING_FLAG | 4) + +// DIRSTRING_TYPE contains the valid string types in an X.509 DirectoryString. +#define DIRSTRING_TYPE \ + (B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_BMPSTRING | \ + B_ASN1_UTF8STRING) + +// PKCS9STRING_TYPE contains the valid string types in a PKCS9String. +#define PKCS9STRING_TYPE (DIRSTRING_TYPE | B_ASN1_IA5STRING) + +// ASN1_mbstring_copy converts |len| bytes from |in| to an ASN.1 string. If +// |len| is -1, |in| must be NUL-terminated and the length is determined by +// |strlen|. |in| is decoded according to |inform|, which must be one of +// |MBSTRING_*|. |mask| determines the set of valid output types and is a +// bitmask containing a subset of |B_ASN1_PRINTABLESTRING|, |B_ASN1_IA5STRING|, +// |B_ASN1_T61STRING|, |B_ASN1_BMPSTRING|, |B_ASN1_UNIVERSALSTRING|, and +// |B_ASN1_UTF8STRING|, in that preference order. This function chooses the +// first output type in |mask| which can represent |in|. It interprets T61String +// as Latin-1, rather than T.61. +// +// If |mask| is zero, |DIRSTRING_TYPE| is used by default. +// +// On success, this function returns the |V_ASN1_*| constant corresponding to +// the selected output type and, if |out| and |*out| are both non-NULL, updates +// the object at |*out| with the result. If |out| is non-NULL and |*out| is +// NULL, it instead sets |*out| to a newly-allocated |ASN1_STRING| containing +// the result. If |out| is NULL, it returns the selected output type without +// constructing an |ASN1_STRING|. On error, this function returns -1. +OPENSSL_EXPORT int ASN1_mbstring_copy(ASN1_STRING **out, const uint8_t *in, + ossl_ssize_t len, int inform, + unsigned long mask); + +// ASN1_mbstring_ncopy behaves like |ASN1_mbstring_copy| but returns an error if +// the input is less than |minsize| or greater than |maxsize| codepoints long. A +// |maxsize| value of zero is ignored. Note the sizes are measured in +// codepoints, not output bytes. +OPENSSL_EXPORT int ASN1_mbstring_ncopy(ASN1_STRING **out, const uint8_t *in, + ossl_ssize_t len, int inform, + unsigned long mask, ossl_ssize_t minsize, + ossl_ssize_t maxsize); + +// ASN1_STRING_set_by_NID behaves like |ASN1_mbstring_ncopy|, but determines +// |mask|, |minsize|, and |maxsize| based on |nid|. When |nid| is a recognized +// X.509 attribute type, it will pick a suitable ASN.1 string type and bounds. +// For most attribute types, it preferentially chooses UTF8String. If |nid| is +// unrecognized, it uses UTF8String by default. +// +// Slightly unlike |ASN1_mbstring_ncopy|, this function interprets |out| and +// returns its result as follows: If |out| is NULL, it returns a newly-allocated +// |ASN1_STRING| containing the result. If |out| is non-NULL and +// |*out| is NULL, it additionally sets |*out| to the result. If both |out| and +// |*out| are non-NULL, it instead updates the object at |*out| and returns +// |*out|. In all cases, it returns NULL on error. +// +// This function supports the following NIDs: |NID_countryName|, +// |NID_dnQualifier|, |NID_domainComponent|, |NID_friendlyName|, +// |NID_givenName|, |NID_initials|, |NID_localityName|, |NID_ms_csp_name|, +// |NID_name|, |NID_organizationalUnitName|, |NID_organizationName|, +// |NID_pkcs9_challengePassword|, |NID_pkcs9_emailAddress|, +// |NID_pkcs9_unstructuredAddress|, |NID_pkcs9_unstructuredName|, +// |NID_serialNumber|, |NID_stateOrProvinceName|, and |NID_surname|. Additional +// NIDs may be registered with |ASN1_STRING_set_by_NID|, but it is recommended +// to call |ASN1_mbstring_ncopy| directly instead. +OPENSSL_EXPORT ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, + const unsigned char *in, + ossl_ssize_t len, int inform, + int nid); + +// STABLE_NO_MASK causes |ASN1_STRING_TABLE_add| to allow types other than +// UTF8String. +#define STABLE_NO_MASK 0x02 + +// ASN1_STRING_TABLE_add registers the corresponding parameters with |nid|, for +// use with |ASN1_STRING_set_by_NID|. It returns one on success and zero on +// error. It is an error to call this function if |nid| is a built-in NID, or +// was already registered by a previous call. +// +// WARNING: This function affects global state in the library. If two libraries +// in the same address space register information for the same OID, one call +// will fail. Prefer directly passing the desired parametrs to +// |ASN1_mbstring_copy| or |ASN1_mbstring_ncopy| instead. +OPENSSL_EXPORT int ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, + unsigned long mask, + unsigned long flags); + + +// Multi-strings. +// +// A multi-string, or "MSTRING", is an |ASN1_STRING| that represents a CHOICE of +// several string or string-like types, such as X.509's DirectoryString. The +// |ASN1_STRING|'s type field determines which type is used. +// +// Multi-string types are associated with a bitmask, using the |B_ASN1_*| +// constants, which defines which types are valid. + +// B_ASN1_DIRECTORYSTRING is a bitmask of types allowed in an X.509 +// DirectoryString (RFC 5280). +#define B_ASN1_DIRECTORYSTRING \ + (B_ASN1_PRINTABLESTRING | B_ASN1_TELETEXSTRING | B_ASN1_BMPSTRING | \ + B_ASN1_UNIVERSALSTRING | B_ASN1_UTF8STRING) + +// DIRECTORYSTRING_new returns a newly-allocated |ASN1_STRING| with type -1, or +// NULL on error. The resulting |ASN1_STRING| is not a valid X.509 +// DirectoryString until initialized with a value. +OPENSSL_EXPORT ASN1_STRING *DIRECTORYSTRING_new(void); + +// DIRECTORYSTRING_free calls |ASN1_STRING_free|. +OPENSSL_EXPORT void DIRECTORYSTRING_free(ASN1_STRING *str); + +// d2i_DIRECTORYSTRING parses up to |len| bytes from |*inp| as a DER-encoded +// X.509 DirectoryString (RFC 5280), as described in |d2i_SAMPLE|. +// +// TODO(https://crbug.com/boringssl/354): This function currently also accepts +// BER, but this will be removed in the future. +// +// TODO(https://crbug.com/boringssl/449): DirectoryString's non-empty string +// requirement is not currently enforced. +OPENSSL_EXPORT ASN1_STRING *d2i_DIRECTORYSTRING(ASN1_STRING **out, + const uint8_t **inp, long len); + +// i2d_DIRECTORYSTRING marshals |in| as a DER-encoded X.509 DirectoryString (RFC +// 5280), as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_DIRECTORYSTRING(const ASN1_STRING *in, uint8_t **outp); + +// DIRECTORYSTRING is an |ASN1_ITEM| whose ASN.1 type is X.509 DirectoryString +// (RFC 5280) and C type is |ASN1_STRING*|. +DECLARE_ASN1_ITEM(DIRECTORYSTRING) + +// B_ASN1_DISPLAYTEXT is a bitmask of types allowed in an X.509 DisplayText (RFC +// 5280). +#define B_ASN1_DISPLAYTEXT \ + (B_ASN1_IA5STRING | B_ASN1_VISIBLESTRING | B_ASN1_BMPSTRING | \ + B_ASN1_UTF8STRING) + +// DISPLAYTEXT_new returns a newly-allocated |ASN1_STRING| with type -1, or NULL +// on error. The resulting |ASN1_STRING| is not a valid X.509 DisplayText until +// initialized with a value. +OPENSSL_EXPORT ASN1_STRING *DISPLAYTEXT_new(void); + +// DISPLAYTEXT_free calls |ASN1_STRING_free|. +OPENSSL_EXPORT void DISPLAYTEXT_free(ASN1_STRING *str); + +// d2i_DISPLAYTEXT parses up to |len| bytes from |*inp| as a DER-encoded X.509 +// DisplayText (RFC 5280), as described in |d2i_SAMPLE|. +// +// TODO(https://crbug.com/boringssl/354): This function currently also accepts +// BER, but this will be removed in the future. +// +// TODO(https://crbug.com/boringssl/449): DisplayText's size limits are not +// currently enforced. +OPENSSL_EXPORT ASN1_STRING *d2i_DISPLAYTEXT(ASN1_STRING **out, + const uint8_t **inp, long len); + +// i2d_DISPLAYTEXT marshals |in| as a DER-encoded X.509 DisplayText (RFC 5280), +// as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_DISPLAYTEXT(const ASN1_STRING *in, uint8_t **outp); + +// DISPLAYTEXT is an |ASN1_ITEM| whose ASN.1 type is X.509 DisplayText (RFC +// 5280) and C type is |ASN1_STRING*|. +DECLARE_ASN1_ITEM(DISPLAYTEXT) + + +// Bit strings. +// +// An ASN.1 BIT STRING type represents a string of bits. The string may not +// necessarily be a whole number of bytes. BIT STRINGs occur in ASN.1 structures +// in several forms: +// +// Some BIT STRINGs represent a bitmask of named bits, such as the X.509 key +// usage extension in RFC 5280, section 4.2.1.3. For such bit strings, DER +// imposes an additional restriction that trailing zero bits are removed. Some +// functions like |ASN1_BIT_STRING_set_bit| help in maintaining this. +// +// Other BIT STRINGs are arbitrary strings of bits used as identifiers and do +// not have this constraint, such as the X.509 issuerUniqueID field. +// +// Finally, some structures use BIT STRINGs as a container for byte strings. For +// example, the signatureValue field in X.509 and the subjectPublicKey field in +// SubjectPublicKeyInfo are defined as BIT STRINGs with a value specific to the +// AlgorithmIdentifier. While some unknown algorithm could choose to store +// arbitrary bit strings, all supported algorithms use a byte string, with bit +// order matching the DER encoding. Callers interpreting a BIT STRING as a byte +// string should use |ASN1_BIT_STRING_num_bytes| instead of |ASN1_STRING_length| +// and reject bit strings that are not a whole number of bytes. +// +// This library represents BIT STRINGs as |ASN1_STRING|s with type +// |V_ASN1_BIT_STRING|. The data contains the encoded form of the BIT STRING, +// including any padding bits added to round to a whole number of bytes, but +// excluding the leading byte containing the number of padding bits. If +// |ASN1_STRING_FLAG_BITS_LEFT| is set, the bottom three bits contains the +// number of padding bits. For example, DER encodes the BIT STRING {1, 0} as +// {0x06, 0x80 = 0b10_000000}. The |ASN1_STRING| representation has data of +// {0x80} and flags of ASN1_STRING_FLAG_BITS_LEFT | 6. If +// |ASN1_STRING_FLAG_BITS_LEFT| is unset, trailing zero bits are implicitly +// removed. Callers should not rely this representation when constructing bit +// strings. The padding bits in the |ASN1_STRING| data must be zero. + +// ASN1_BIT_STRING_new calls |ASN1_STRING_type_new| with |V_ASN1_BIT_STRING|. +OPENSSL_EXPORT ASN1_BIT_STRING *ASN1_BIT_STRING_new(void); + +// ASN1_BIT_STRING_free calls |ASN1_STRING_free|. +OPENSSL_EXPORT void ASN1_BIT_STRING_free(ASN1_BIT_STRING *str); + +// d2i_ASN1_BIT_STRING parses up to |len| bytes from |*inp| as a DER-encoded +// ASN.1 BIT STRING, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT ASN1_BIT_STRING *d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **out, + const uint8_t **inp, + long len); + +// i2d_ASN1_BIT_STRING marshals |in| as a DER-encoded ASN.1 BIT STRING, as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_BIT_STRING(const ASN1_BIT_STRING *in, + uint8_t **outp); + +// c2i_ASN1_BIT_STRING decodes |len| bytes from |*inp| as the contents of a +// DER-encoded BIT STRING, excluding the tag and length. It behaves like +// |d2i_SAMPLE| except, on success, it always consumes all |len| bytes. +OPENSSL_EXPORT ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **out, + const uint8_t **inp, + long len); + +// i2c_ASN1_BIT_STRING encodes |in| as the contents of a DER-encoded BIT STRING, +// excluding the tag and length. If |outp| is non-NULL, it writes the result to +// |*outp|, advances |*outp| just past the output, and returns the number of +// bytes written. |*outp| must have space available for the result. If |outp| is +// NULL, it returns the number of bytes without writing anything. On error, it +// returns a value <= 0. +// +// Note this function differs slightly from |i2d_SAMPLE|. If |outp| is non-NULL +// and |*outp| is NULL, it does not allocate a new buffer. +// +// TODO(davidben): This function currently returns zero on error instead of -1, +// but it is also mostly infallible. I've currently documented <= 0 to suggest +// callers work with both. +OPENSSL_EXPORT int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *in, + uint8_t **outp); + +// ASN1_BIT_STRING is an |ASN1_ITEM| with ASN.1 type BIT STRING and C type +// |ASN1_BIT_STRING*|. +DECLARE_ASN1_ITEM(ASN1_BIT_STRING) + +// ASN1_BIT_STRING_num_bytes computes the length of |str| in bytes. If |str|'s +// bit length is a multiple of 8, it sets |*out| to the byte length and returns +// one. Otherwise, it returns zero. +// +// This function may be used with |ASN1_STRING_get0_data| to interpret |str| as +// a byte string. +OPENSSL_EXPORT int ASN1_BIT_STRING_num_bytes(const ASN1_BIT_STRING *str, + size_t *out); + +// ASN1_BIT_STRING_set calls |ASN1_STRING_set|. It leaves flags unchanged, so +// the caller must set the number of unused bits. +// +// TODO(davidben): Maybe it should? Wrapping a byte string in a bit string is a +// common use case. +OPENSSL_EXPORT int ASN1_BIT_STRING_set(ASN1_BIT_STRING *str, + const unsigned char *d, + ossl_ssize_t length); + +// ASN1_BIT_STRING_set_bit sets bit |n| of |str| to one if |value| is non-zero +// and zero if |value| is zero, resizing |str| as needed. It then truncates +// trailing zeros in |str| to align with the DER represention for a bit string +// with named bits. It returns one on success and zero on error. |n| is indexed +// beginning from zero. +OPENSSL_EXPORT int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *str, int n, + int value); + +// ASN1_BIT_STRING_get_bit returns one if bit |n| of |a| is in bounds and set, +// and zero otherwise. |n| is indexed beginning from zero. +OPENSSL_EXPORT int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *str, int n); + +// ASN1_BIT_STRING_check returns one if |str| only contains bits that are set in +// the |flags_len| bytes pointed by |flags|. Otherwise it returns zero. Bits in +// |flags| are arranged according to the DER representation, so bit 0 +// corresponds to the MSB of |flags[0]|. +OPENSSL_EXPORT int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *str, + const unsigned char *flags, + int flags_len); + + +// Integers and enumerated values. +// +// INTEGER and ENUMERATED values are represented as |ASN1_STRING|s where the +// data contains the big-endian encoding of the absolute value of the integer. +// The sign bit is encoded in the type: non-negative values have a type of +// |V_ASN1_INTEGER| or |V_ASN1_ENUMERATED|, while negative values have a type of +// |V_ASN1_NEG_INTEGER| or |V_ASN1_NEG_ENUMERATED|. Note this differs from DER's +// two's complement representation. +// +// The data in the |ASN1_STRING| may not have leading zeros. Note this means +// zero is represented as the empty string. Parsing functions will never return +// invalid representations. If an invalid input is constructed, the marshaling +// functions will skip leading zeros, however other functions, such as +// |ASN1_INTEGER_cmp| or |ASN1_INTEGER_get|, may not return the correct result. + +DEFINE_STACK_OF(ASN1_INTEGER) + +// ASN1_INTEGER_new calls |ASN1_STRING_type_new| with |V_ASN1_INTEGER|. The +// resulting object has value zero. +OPENSSL_EXPORT ASN1_INTEGER *ASN1_INTEGER_new(void); + +// ASN1_INTEGER_free calls |ASN1_STRING_free|. +OPENSSL_EXPORT void ASN1_INTEGER_free(ASN1_INTEGER *str); + +// ASN1_INTEGER_dup calls |ASN1_STRING_dup|. +OPENSSL_EXPORT ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x); + +// d2i_ASN1_INTEGER parses up to |len| bytes from |*inp| as a DER-encoded +// ASN.1 INTEGER, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT ASN1_INTEGER *d2i_ASN1_INTEGER(ASN1_INTEGER **out, + const uint8_t **inp, long len); + +// i2d_ASN1_INTEGER marshals |in| as a DER-encoded ASN.1 INTEGER, as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_INTEGER(const ASN1_INTEGER *in, uint8_t **outp); + +// c2i_ASN1_INTEGER decodes |len| bytes from |*inp| as the contents of a +// DER-encoded INTEGER, excluding the tag and length. It behaves like +// |d2i_SAMPLE| except, on success, it always consumes all |len| bytes. +OPENSSL_EXPORT ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **in, + const uint8_t **outp, long len); + +// i2c_ASN1_INTEGER encodes |in| as the contents of a DER-encoded INTEGER, +// excluding the tag and length. If |outp| is non-NULL, it writes the result to +// |*outp|, advances |*outp| just past the output, and returns the number of +// bytes written. |*outp| must have space available for the result. If |outp| is +// NULL, it returns the number of bytes without writing anything. On error, it +// returns a value <= 0. +// +// Note this function differs slightly from |i2d_SAMPLE|. If |outp| is non-NULL +// and |*outp| is NULL, it does not allocate a new buffer. +// +// TODO(davidben): This function currently returns zero on error instead of -1, +// but it is also mostly infallible. I've currently documented <= 0 to suggest +// callers work with both. +OPENSSL_EXPORT int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, uint8_t **outp); + +// ASN1_INTEGER is an |ASN1_ITEM| with ASN.1 type INTEGER and C type +// |ASN1_INTEGER*|. +DECLARE_ASN1_ITEM(ASN1_INTEGER) + +// ASN1_INTEGER_set_uint64 sets |a| to an INTEGER with value |v|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v); + +// ASN1_INTEGER_set_int64 sets |a| to an INTEGER with value |v|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int ASN1_INTEGER_set_int64(ASN1_INTEGER *out, int64_t v); + +// ASN1_INTEGER_get_uint64 converts |a| to a |uint64_t|. On success, it returns +// one and sets |*out| to the result. If |a| did not fit or has the wrong type, +// it returns zero. +OPENSSL_EXPORT int ASN1_INTEGER_get_uint64(uint64_t *out, + const ASN1_INTEGER *a); + +// ASN1_INTEGER_get_int64 converts |a| to a |int64_t|. On success, it returns +// one and sets |*out| to the result. If |a| did not fit or has the wrong type, +// it returns zero. +OPENSSL_EXPORT int ASN1_INTEGER_get_int64(int64_t *out, const ASN1_INTEGER *a); + +// BN_to_ASN1_INTEGER sets |ai| to an INTEGER with value |bn| and returns |ai| +// on success or NULL or error. If |ai| is NULL, it returns a newly-allocated +// |ASN1_INTEGER| on success instead, which the caller must release with +// |ASN1_INTEGER_free|. +OPENSSL_EXPORT ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, + ASN1_INTEGER *ai); + +// ASN1_INTEGER_to_BN sets |bn| to the value of |ai| and returns |bn| on success +// or NULL or error. If |bn| is NULL, it returns a newly-allocated |BIGNUM| on +// success instead, which the caller must release with |BN_free|. +OPENSSL_EXPORT BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn); + +// ASN1_INTEGER_cmp compares the values of |x| and |y|. It returns an integer +// equal to, less than, or greater than zero if |x| is equal to, less than, or +// greater than |y|, respectively. +OPENSSL_EXPORT int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, + const ASN1_INTEGER *y); + +// ASN1_ENUMERATED_new calls |ASN1_STRING_type_new| with |V_ASN1_ENUMERATED|. +// The resulting object has value zero. +OPENSSL_EXPORT ASN1_ENUMERATED *ASN1_ENUMERATED_new(void); + +// ASN1_ENUMERATED_free calls |ASN1_STRING_free|. +OPENSSL_EXPORT void ASN1_ENUMERATED_free(ASN1_ENUMERATED *str); + +// d2i_ASN1_ENUMERATED parses up to |len| bytes from |*inp| as a DER-encoded +// ASN.1 ENUMERATED, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT ASN1_ENUMERATED *d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **out, + const uint8_t **inp, + long len); + +// i2d_ASN1_ENUMERATED marshals |in| as a DER-encoded ASN.1 ENUMERATED, as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_ENUMERATED(const ASN1_ENUMERATED *in, + uint8_t **outp); + +// ASN1_ENUMERATED is an |ASN1_ITEM| with ASN.1 type ENUMERATED and C type +// |ASN1_ENUMERATED*|. +DECLARE_ASN1_ITEM(ASN1_ENUMERATED) + +// ASN1_ENUMERATED_set_uint64 sets |a| to an ENUMERATED with value |v|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int ASN1_ENUMERATED_set_uint64(ASN1_ENUMERATED *out, uint64_t v); + +// ASN1_ENUMERATED_set_int64 sets |a| to an ENUMERATED with value |v|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *out, int64_t v); + +// ASN1_ENUMERATED_get_uint64 converts |a| to a |uint64_t|. On success, it +// returns one and sets |*out| to the result. If |a| did not fit or has the +// wrong type, it returns zero. +OPENSSL_EXPORT int ASN1_ENUMERATED_get_uint64(uint64_t *out, + const ASN1_ENUMERATED *a); + +// ASN1_ENUMERATED_get_int64 converts |a| to a |int64_t|. On success, it +// returns one and sets |*out| to the result. If |a| did not fit or has the +// wrong type, it returns zero. +OPENSSL_EXPORT int ASN1_ENUMERATED_get_int64(int64_t *out, + const ASN1_ENUMERATED *a); + +// BN_to_ASN1_ENUMERATED sets |ai| to an ENUMERATED with value |bn| and returns +// |ai| on success or NULL or error. If |ai| is NULL, it returns a +// newly-allocated |ASN1_ENUMERATED| on success instead, which the caller must +// release with |ASN1_ENUMERATED_free|. +OPENSSL_EXPORT ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, + ASN1_ENUMERATED *ai); + +// ASN1_ENUMERATED_to_BN sets |bn| to the value of |ai| and returns |bn| on +// success or NULL or error. If |bn| is NULL, it returns a newly-allocated +// |BIGNUM| on success instead, which the caller must release with |BN_free|. +OPENSSL_EXPORT BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, + BIGNUM *bn); + + +// Time. +// +// GeneralizedTime and UTCTime values are represented as |ASN1_STRING|s. The +// type field is |V_ASN1_GENERALIZEDTIME| or |V_ASN1_UTCTIME|, respectively. The +// data field contains the DER encoding of the value. For example, the UNIX +// epoch would be "19700101000000Z" for a GeneralizedTime and "700101000000Z" +// for a UTCTime. +// +// ASN.1 does not define how to interpret UTCTime's two-digit year. RFC 5280 +// defines it as a range from 1950 to 2049 for X.509. The library uses the +// RFC 5280 interpretation. It does not currently enforce the restrictions from +// BER, and the additional restrictions from RFC 5280, but future versions may. +// Callers should not rely on fractional seconds and non-UTC time zones. +// +// The |ASN1_TIME| typedef is a multi-string representing the X.509 Time type, +// which is a CHOICE of GeneralizedTime and UTCTime, using UTCTime when the +// value is in range. + +// ASN1_UTCTIME_new calls |ASN1_STRING_type_new| with |V_ASN1_UTCTIME|. The +// resulting object contains empty contents and must be initialized to be a +// valid UTCTime. +OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_new(void); + +// ASN1_UTCTIME_free calls |ASN1_STRING_free|. +OPENSSL_EXPORT void ASN1_UTCTIME_free(ASN1_UTCTIME *str); + +// d2i_ASN1_UTCTIME parses up to |len| bytes from |*inp| as a DER-encoded +// ASN.1 UTCTime, as described in |d2i_SAMPLE|. +// +// TODO(https://crbug.com/boringssl/354): This function currently also accepts +// BER, but this will be removed in the future. +OPENSSL_EXPORT ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **out, + const uint8_t **inp, long len); + +// i2d_ASN1_UTCTIME marshals |in| as a DER-encoded ASN.1 UTCTime, as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_UTCTIME(const ASN1_UTCTIME *in, uint8_t **outp); + +// ASN1_UTCTIME is an |ASN1_ITEM| with ASN.1 type UTCTime and C type +// |ASN1_UTCTIME*|. +DECLARE_ASN1_ITEM(ASN1_UTCTIME) + +// ASN1_UTCTIME_check returns one if |a| is a valid UTCTime and zero otherwise. +OPENSSL_EXPORT int ASN1_UTCTIME_check(const ASN1_UTCTIME *a); + +// ASN1_UTCTIME_set represents |posix_time| as a UTCTime and writes the result +// to |s|. It returns |s| on success and NULL on error. If |s| is NULL, it +// returns a newly-allocated |ASN1_UTCTIME| instead. +// +// Note this function may fail if the time is out of range for UTCTime. +OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, + int64_t posix_time); + +// ASN1_UTCTIME_adj adds |offset_day| days and |offset_sec| seconds to +// |posix_time| and writes the result to |s| as a UTCTime. It returns |s| on +// success and NULL on error. If |s| is NULL, it returns a newly-allocated +// |ASN1_UTCTIME| instead. +// +// Note this function may fail if the time overflows or is out of range for +// UTCTime. +OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, + int64_t posix_time, + int offset_day, long offset_sec); + +// ASN1_UTCTIME_set_string sets |s| to a UTCTime whose contents are a copy of +// |str|. It returns one on success and zero on error or if |str| is not a valid +// UTCTime. +// +// If |s| is NULL, this function validates |str| without copying it. +OPENSSL_EXPORT int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str); + +// ASN1_UTCTIME_cmp_time_t compares |s| to |t|. It returns -1 if |s| < |t|, 0 if +// they are equal, 1 if |s| > |t|, and -2 on error. +OPENSSL_EXPORT int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t); + +// ASN1_GENERALIZEDTIME_new calls |ASN1_STRING_type_new| with +// |V_ASN1_GENERALIZEDTIME|. The resulting object contains empty contents and +// must be initialized to be a valid GeneralizedTime. +OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_new(void); + +// ASN1_GENERALIZEDTIME_free calls |ASN1_STRING_free|. +OPENSSL_EXPORT void ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *str); + +// d2i_ASN1_GENERALIZEDTIME parses up to |len| bytes from |*inp| as a +// DER-encoded ASN.1 GeneralizedTime, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT ASN1_GENERALIZEDTIME *d2i_ASN1_GENERALIZEDTIME( + ASN1_GENERALIZEDTIME **out, const uint8_t **inp, long len); + +// i2d_ASN1_GENERALIZEDTIME marshals |in| as a DER-encoded ASN.1 +// GeneralizedTime, as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_GENERALIZEDTIME(const ASN1_GENERALIZEDTIME *in, + uint8_t **outp); + +// ASN1_GENERALIZEDTIME is an |ASN1_ITEM| with ASN.1 type GeneralizedTime and C +// type |ASN1_GENERALIZEDTIME*|. +DECLARE_ASN1_ITEM(ASN1_GENERALIZEDTIME) + +// ASN1_GENERALIZEDTIME_check returns one if |a| is a valid GeneralizedTime and +// zero otherwise. +OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a); + +// ASN1_GENERALIZEDTIME_set represents |posix_time| as a GeneralizedTime and +// writes the result to |s|. It returns |s| on success and NULL on error. If |s| +// is NULL, it returns a newly-allocated |ASN1_GENERALIZEDTIME| instead. +// +// Note this function may fail if the time is out of range for GeneralizedTime. +OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set( + ASN1_GENERALIZEDTIME *s, int64_t posix_time); + +// ASN1_GENERALIZEDTIME_adj adds |offset_day| days and |offset_sec| seconds to +// |posix_time| and writes the result to |s| as a GeneralizedTime. It returns +// |s| on success and NULL on error. If |s| is NULL, it returns a +// newly-allocated |ASN1_GENERALIZEDTIME| instead. +// +// Note this function may fail if the time overflows or is out of range for +// GeneralizedTime. +OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj( + ASN1_GENERALIZEDTIME *s, int64_t posix_time, int offset_day, + long offset_sec); + +// ASN1_GENERALIZEDTIME_set_string sets |s| to a GeneralizedTime whose contents +// are a copy of |str|. It returns one on success and zero on error or if |str| +// is not a valid GeneralizedTime. +// +// If |s| is NULL, this function validates |str| without copying it. +OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, + const char *str); + +// B_ASN1_TIME is a bitmask of types allowed in an X.509 Time. +#define B_ASN1_TIME (B_ASN1_UTCTIME | B_ASN1_GENERALIZEDTIME) + +// ASN1_TIME_new returns a newly-allocated |ASN1_TIME| with type -1, or NULL on +// error. The resulting |ASN1_TIME| is not a valid X.509 Time until initialized +// with a value. +OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_new(void); + +// ASN1_TIME_free releases memory associated with |str|. +OPENSSL_EXPORT void ASN1_TIME_free(ASN1_TIME *str); + +// d2i_ASN1_TIME parses up to |len| bytes from |*inp| as a DER-encoded X.509 +// Time (RFC 5280), as described in |d2i_SAMPLE|. +// +// TODO(https://crbug.com/boringssl/354): This function currently also accepts +// BER, but this will be removed in the future. +OPENSSL_EXPORT ASN1_TIME *d2i_ASN1_TIME(ASN1_TIME **out, const uint8_t **inp, + long len); + +// i2d_ASN1_TIME marshals |in| as a DER-encoded X.509 Time (RFC 5280), as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_TIME(const ASN1_TIME *in, uint8_t **outp); + +// ASN1_TIME is an |ASN1_ITEM| whose ASN.1 type is X.509 Time (RFC 5280) and C +// type is |ASN1_TIME*|. +DECLARE_ASN1_ITEM(ASN1_TIME) + +// ASN1_TIME_diff computes |to| - |from|. On success, it sets |*out_days| to the +// difference in days, rounded towards zero, sets |*out_seconds| to the +// remainder, and returns one. On error, it returns zero. +// +// If |from| is before |to|, both outputs will be <= 0, with at least one +// negative. If |from| is after |to|, both will be >= 0, with at least one +// positive. If they are equal, ignoring fractional seconds, both will be zero. +// +// Note this function may fail on overflow, or if |from| or |to| cannot be +// decoded. +OPENSSL_EXPORT int ASN1_TIME_diff(int *out_days, int *out_seconds, + const ASN1_TIME *from, const ASN1_TIME *to); + +// ASN1_TIME_set_posix represents |posix_time| as a GeneralizedTime or UTCTime +// and writes the result to |s|. As in RFC 5280, section 4.1.2.5, it uses +// UTCTime when the time fits and GeneralizedTime otherwise. It returns |s| on +// success and NULL on error. If |s| is NULL, it returns a newly-allocated +// |ASN1_TIME| instead. +// +// Note this function may fail if the time is out of range for GeneralizedTime. +OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_set_posix(ASN1_TIME *s, int64_t posix_time); + +// ASN1_TIME_set is exactly the same as |ASN1_TIME_set_posix| but with a +// time_t as input for compatibility. +OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t time); + +// ASN1_TIME_adj adds |offset_day| days and |offset_sec| seconds to +// |posix_time| and writes the result to |s|. As in RFC 5280, section 4.1.2.5, +// it uses UTCTime when the time fits and GeneralizedTime otherwise. It returns +// |s| on success and NULL on error. If |s| is NULL, it returns a +// newly-allocated |ASN1_GENERALIZEDTIME| instead. +// +// Note this function may fail if the time overflows or is out of range for +// GeneralizedTime. +OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, int64_t posix_time, + int offset_day, long offset_sec); + +// ASN1_TIME_check returns one if |t| is a valid UTCTime or GeneralizedTime, and +// zero otherwise. |t|'s type determines which check is performed. This +// function does not enforce that UTCTime was used when possible. +OPENSSL_EXPORT int ASN1_TIME_check(const ASN1_TIME *t); + +// ASN1_TIME_to_generalizedtime converts |t| to a GeneralizedTime. If |out| is +// NULL, it returns a newly-allocated |ASN1_GENERALIZEDTIME| on success, or NULL +// on error. If |out| is non-NULL and |*out| is NULL, it additionally sets +// |*out| to the result. If |out| and |*out| are non-NULL, it instead updates +// the object pointed by |*out| and returns |*out| on success or NULL on error. +OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime( + const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out); + +// ASN1_TIME_set_string behaves like |ASN1_UTCTIME_set_string| if |str| is a +// valid UTCTime, and |ASN1_GENERALIZEDTIME_set_string| if |str| is a valid +// GeneralizedTime. If |str| is neither, it returns zero. +OPENSSL_EXPORT int ASN1_TIME_set_string(ASN1_TIME *s, const char *str); + +// ASN1_TIME_to_time_t converts |t| to a time_t value in |out|. On +// success, one is returned. On failure zero is returned. This function +// will fail if the time can not be represented in a time_t. +OPENSSL_EXPORT int ASN1_TIME_to_time_t(const ASN1_TIME *t, time_t *out); + +// ASN1_TIME_to_posix converts |t| to a POSIX time value in |out|. On +// success, one is returned. On failure zero is returned. +OPENSSL_EXPORT int ASN1_TIME_to_posix(const ASN1_TIME *t, int64_t *out); + +// TODO(davidben): Expand and document function prototypes generated in macros. + + +// NULL values. +// +// This library represents the ASN.1 NULL value by a non-NULL pointer to the +// opaque type |ASN1_NULL|. An omitted OPTIONAL ASN.1 NULL value is a NULL +// pointer. Unlike other pointer types, it is not necessary to free |ASN1_NULL| +// pointers, but it is safe to do so. + +// ASN1_NULL_new returns an opaque, non-NULL pointer. It is safe to call +// |ASN1_NULL_free| on the result, but not necessary. +OPENSSL_EXPORT ASN1_NULL *ASN1_NULL_new(void); + +// ASN1_NULL_free does nothing. +OPENSSL_EXPORT void ASN1_NULL_free(ASN1_NULL *null); + +// d2i_ASN1_NULL parses a DER-encoded ASN.1 NULL value from up to |len| bytes +// at |*inp|, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT ASN1_NULL *d2i_ASN1_NULL(ASN1_NULL **out, const uint8_t **inp, + long len); + +// i2d_ASN1_NULL marshals |in| as a DER-encoded ASN.1 NULL value, as described +// in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_NULL(const ASN1_NULL *in, uint8_t **outp); + +// ASN1_NULL is an |ASN1_ITEM| with ASN.1 type NULL and C type |ASN1_NULL*|. +DECLARE_ASN1_ITEM(ASN1_NULL) + + +// Object identifiers. +// +// An |ASN1_OBJECT| represents a ASN.1 OBJECT IDENTIFIER. See also obj.h for +// additional functions relating to |ASN1_OBJECT|. +// +// TODO(davidben): What's the relationship between asn1.h and obj.h? Most of +// obj.h deals with the large NID table, but then functions like |OBJ_get0_data| +// or |OBJ_dup| are general |ASN1_OBJECT| functions. + +DEFINE_STACK_OF(ASN1_OBJECT) + +// ASN1_OBJECT_create returns a newly-allocated |ASN1_OBJECT| with |len| bytes +// from |data| as the encoded OID, or NULL on error. |data| should contain the +// DER-encoded identifier, excluding the tag and length. +// +// |nid| should be |NID_undef|. Passing a NID value that does not match |data| +// will cause some functions to misbehave. |sn| and |ln| should be NULL. If +// non-NULL, they are stored as short and long names, respectively, but these +// values have no effect for |ASN1_OBJECT|s created through this function. +// +// TODO(davidben): Should we just ignore all those parameters? NIDs and names +// are only relevant for |ASN1_OBJECT|s in the obj.h table. +OPENSSL_EXPORT ASN1_OBJECT *ASN1_OBJECT_create(int nid, const uint8_t *data, + size_t len, const char *sn, + const char *ln); + +// ASN1_OBJECT_free releases memory associated with |a|. If |a| is a static +// |ASN1_OBJECT|, returned from |OBJ_nid2obj|, this function does nothing. +OPENSSL_EXPORT void ASN1_OBJECT_free(ASN1_OBJECT *a); + +// d2i_ASN1_OBJECT parses a DER-encoded ASN.1 OBJECT IDENTIFIER from up to |len| +// bytes at |*inp|, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **out, + const uint8_t **inp, long len); + +// i2d_ASN1_OBJECT marshals |in| as a DER-encoded ASN.1 OBJECT IDENTIFIER, as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_OBJECT(const ASN1_OBJECT *in, uint8_t **outp); + +// c2i_ASN1_OBJECT decodes |len| bytes from |*inp| as the contents of a +// DER-encoded OBJECT IDENTIFIER, excluding the tag and length. It behaves like +// |d2i_SAMPLE| except, on success, it always consumes all |len| bytes. +OPENSSL_EXPORT ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **out, + const uint8_t **inp, long len); + +// ASN1_OBJECT is an |ASN1_ITEM| with ASN.1 type OBJECT IDENTIFIER and C type +// |ASN1_OBJECT*|. +DECLARE_ASN1_ITEM(ASN1_OBJECT) + + +// Arbitrary elements. + +// An asn1_type_st (aka |ASN1_TYPE|) represents an arbitrary ASN.1 element, +// typically used for ANY types. It contains a |type| field and a |value| union +// dependent on |type|. +// +// WARNING: This struct has a complex representation. Callers must not construct +// |ASN1_TYPE| values manually. Use |ASN1_TYPE_set| and |ASN1_TYPE_set1| +// instead. Additionally, callers performing non-trivial operations on this type +// are encouraged to use |CBS| and |CBB| from , and +// convert to or from |ASN1_TYPE| with |d2i_ASN1_TYPE| or |i2d_ASN1_TYPE|. +// +// The |type| field corresponds to the tag of the ASN.1 element being +// represented: +// +// If |type| is a |V_ASN1_*| constant for an ASN.1 string-like type, as defined +// by |ASN1_STRING|, the tag matches the constant. |value| contains an +// |ASN1_STRING| pointer (equivalently, one of the more specific typedefs). See +// |ASN1_STRING| for details on the representation. Unlike |ASN1_STRING|, +// |ASN1_TYPE| does not use the |V_ASN1_NEG| flag for negative INTEGER and +// ENUMERATE values. For a negative value, the |ASN1_TYPE|'s |type| will be +// |V_ASN1_INTEGER| or |V_ASN1_ENUMERATED|, but |value| will an |ASN1_STRING| +// whose |type| is |V_ASN1_NEG_INTEGER| or |V_ASN1_NEG_ENUMERATED|. +// +// If |type| is |V_ASN1_OBJECT|, the tag is OBJECT IDENTIFIER and |value| +// contains an |ASN1_OBJECT| pointer. +// +// If |type| is |V_ASN1_NULL|, the tag is NULL. |value| contains a NULL pointer. +// +// If |type| is |V_ASN1_BOOLEAN|, the tag is BOOLEAN. |value| contains an +// |ASN1_BOOLEAN|. +// +// If |type| is |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or |V_ASN1_OTHER|, the tag is +// SEQUENCE, SET, or some arbitrary tag, respectively. |value| uses the +// corresponding |ASN1_STRING| representation. Although any type may be +// represented in |V_ASN1_OTHER|, the parser will always return the more +// specific encoding when available. +// +// Other values of |type| do not represent a valid ASN.1 value, though +// default-constructed objects may set |type| to -1. Such objects cannot be +// serialized. +struct asn1_type_st { + int type; + union { + char *ptr; + ASN1_BOOLEAN boolean; + ASN1_STRING *asn1_string; + ASN1_OBJECT *object; + ASN1_INTEGER *integer; + ASN1_ENUMERATED *enumerated; + ASN1_BIT_STRING *bit_string; + ASN1_OCTET_STRING *octet_string; + ASN1_PRINTABLESTRING *printablestring; + ASN1_T61STRING *t61string; + ASN1_IA5STRING *ia5string; + ASN1_GENERALSTRING *generalstring; + ASN1_BMPSTRING *bmpstring; + ASN1_UNIVERSALSTRING *universalstring; + ASN1_UTCTIME *utctime; + ASN1_GENERALIZEDTIME *generalizedtime; + ASN1_VISIBLESTRING *visiblestring; + ASN1_UTF8STRING *utf8string; + // set and sequence are left complete and still contain the entire element. + ASN1_STRING *set; + ASN1_STRING *sequence; + ASN1_VALUE *asn1_value; + } value; +}; + +DEFINE_STACK_OF(ASN1_TYPE) + +// ASN1_TYPE_new returns a newly-allocated |ASN1_TYPE|, or NULL on allocation +// failure. The resulting object has type -1 and must be initialized to be +// a valid ANY value. +OPENSSL_EXPORT ASN1_TYPE *ASN1_TYPE_new(void); + +// ASN1_TYPE_free releases memory associated with |a|. +OPENSSL_EXPORT void ASN1_TYPE_free(ASN1_TYPE *a); + +// d2i_ASN1_TYPE parses up to |len| bytes from |*inp| as an ASN.1 value of any +// type, as described in |d2i_SAMPLE|. Note this function only validates +// primitive, universal types supported by this library. Values of type +// |V_ASN1_SEQUENCE|, |V_ASN1_SET|, |V_ASN1_OTHER|, or an unsupported primitive +// type must be validated by the caller when interpreting. +// +// TODO(https://crbug.com/boringssl/354): This function currently also accepts +// BER, but this will be removed in the future. +OPENSSL_EXPORT ASN1_TYPE *d2i_ASN1_TYPE(ASN1_TYPE **out, const uint8_t **inp, + long len); + +// i2d_ASN1_TYPE marshals |in| as DER, as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_TYPE(const ASN1_TYPE *in, uint8_t **outp); + +// ASN1_ANY is an |ASN1_ITEM| with ASN.1 type ANY and C type |ASN1_TYPE*|. Note +// the |ASN1_ITEM| name and C type do not match. +DECLARE_ASN1_ITEM(ASN1_ANY) + +// ASN1_TYPE_get returns the type of |a|, which will be one of the |V_ASN1_*| +// constants, or zero if |a| is not fully initialized. +OPENSSL_EXPORT int ASN1_TYPE_get(const ASN1_TYPE *a); + +// ASN1_TYPE_set sets |a| to an |ASN1_TYPE| of type |type| and value |value|, +// releasing the previous contents of |a|. +// +// If |type| is |V_ASN1_BOOLEAN|, |a| is set to FALSE if |value| is NULL and +// TRUE otherwise. If setting |a| to TRUE, |value| may be an invalid pointer, +// such as (void*)1. +// +// If |type| is |V_ASN1_NULL|, |value| must be NULL. +// +// For other values of |type|, this function takes ownership of |value|, which +// must point to an object of the corresponding type. See |ASN1_TYPE| for +// details. +OPENSSL_EXPORT void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); + +// ASN1_TYPE_set1 behaves like |ASN1_TYPE_set| except it does not take ownership +// of |value|. It returns one on success and zero on error. +OPENSSL_EXPORT int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); + +// ASN1_TYPE_cmp returns zero if |a| and |b| are equal and some non-zero value +// otherwise. Note this function can only be used for equality checks, not an +// ordering. +OPENSSL_EXPORT int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b); + +typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY; + +// d2i_ASN1_SEQUENCE_ANY parses up to |len| bytes from |*inp| as a DER-encoded +// ASN.1 SEQUENCE OF ANY structure, as described in |d2i_SAMPLE|. The resulting +// |ASN1_SEQUENCE_ANY| owns its contents and thus must be released with +// |sk_ASN1_TYPE_pop_free| and |ASN1_TYPE_free|, not |sk_ASN1_TYPE_free|. +// +// TODO(https://crbug.com/boringssl/354): This function currently also accepts +// BER, but this will be removed in the future. +OPENSSL_EXPORT ASN1_SEQUENCE_ANY *d2i_ASN1_SEQUENCE_ANY(ASN1_SEQUENCE_ANY **out, + const uint8_t **inp, + long len); + +// i2d_ASN1_SEQUENCE_ANY marshals |in| as a DER-encoded SEQUENCE OF ANY +// structure, as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_SEQUENCE_ANY(const ASN1_SEQUENCE_ANY *in, + uint8_t **outp); + +// d2i_ASN1_SET_ANY parses up to |len| bytes from |*inp| as a DER-encoded ASN.1 +// SET OF ANY structure, as described in |d2i_SAMPLE|. The resulting +// |ASN1_SEQUENCE_ANY| owns its contents and thus must be released with +// |sk_ASN1_TYPE_pop_free| and |ASN1_TYPE_free|, not |sk_ASN1_TYPE_free|. +// +// TODO(https://crbug.com/boringssl/354): This function currently also accepts +// BER, but this will be removed in the future. +OPENSSL_EXPORT ASN1_SEQUENCE_ANY *d2i_ASN1_SET_ANY(ASN1_SEQUENCE_ANY **out, + const uint8_t **inp, + long len); + +// i2d_ASN1_SET_ANY marshals |in| as a DER-encoded SET OF ANY structure, as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_ASN1_SET_ANY(const ASN1_SEQUENCE_ANY *in, + uint8_t **outp); + + +// Human-readable output. +// +// The following functions output types in some human-readable format. These +// functions may be used for debugging and logging. However, the output should +// not be consumed programmatically. They may be ambiguous or lose information. + +// ASN1_UTCTIME_print writes a human-readable representation of |a| to |out|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int ASN1_UTCTIME_print(BIO *out, const ASN1_UTCTIME *a); + +// ASN1_GENERALIZEDTIME_print writes a human-readable representation of |a| to +// |out|. It returns one on success and zero on error. +OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_print(BIO *out, + const ASN1_GENERALIZEDTIME *a); + +// ASN1_TIME_print writes a human-readable representation of |a| to |out|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int ASN1_TIME_print(BIO *out, const ASN1_TIME *a); + +// ASN1_STRING_print writes a human-readable representation of |str| to |out|. +// It returns one on success and zero on error. Unprintable characters are +// replaced with '.'. +OPENSSL_EXPORT int ASN1_STRING_print(BIO *out, const ASN1_STRING *str); + +// The following flags must not collide with |XN_FLAG_*|. + +// ASN1_STRFLGS_ESC_2253 causes characters to be escaped as in RFC 2253, section +// 2.4. +#define ASN1_STRFLGS_ESC_2253 1 + +// ASN1_STRFLGS_ESC_CTRL causes all control characters to be escaped. +#define ASN1_STRFLGS_ESC_CTRL 2 + +// ASN1_STRFLGS_ESC_MSB causes all characters above 127 to be escaped. +#define ASN1_STRFLGS_ESC_MSB 4 + +// ASN1_STRFLGS_ESC_QUOTE causes the string to be surrounded by quotes, rather +// than using backslashes, when characters are escaped. Fewer characters will +// require escapes in this case. +#define ASN1_STRFLGS_ESC_QUOTE 8 + +// ASN1_STRFLGS_UTF8_CONVERT causes the string to be encoded as UTF-8, with each +// byte in the UTF-8 encoding treated as an individual character for purposes of +// escape sequences. If not set, each Unicode codepoint in the string is treated +// as a character, with wide characters escaped as "\Uxxxx" or "\Wxxxxxxxx". +// Note this can be ambiguous if |ASN1_STRFLGS_ESC_*| are all unset. In that +// case, backslashes are not escaped, but wide characters are. +#define ASN1_STRFLGS_UTF8_CONVERT 0x10 + +// ASN1_STRFLGS_IGNORE_TYPE causes the string type to be ignored. The +// |ASN1_STRING| in-memory representation will be printed directly. +#define ASN1_STRFLGS_IGNORE_TYPE 0x20 + +// ASN1_STRFLGS_SHOW_TYPE causes the string type to be included in the output. +#define ASN1_STRFLGS_SHOW_TYPE 0x40 + +// ASN1_STRFLGS_DUMP_ALL causes all strings to be printed as a hexdump, using +// RFC 2253 hexstring notation, such as "#0123456789ABCDEF". +#define ASN1_STRFLGS_DUMP_ALL 0x80 + +// ASN1_STRFLGS_DUMP_UNKNOWN behaves like |ASN1_STRFLGS_DUMP_ALL| but only +// applies to values of unknown type. If unset, unknown values will print +// their contents as single-byte characters with escape sequences. +#define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 + +// ASN1_STRFLGS_DUMP_DER causes hexdumped strings (as determined by +// |ASN1_STRFLGS_DUMP_ALL| or |ASN1_STRFLGS_DUMP_UNKNOWN|) to print the entire +// DER element as in RFC 2253, rather than only the contents of the +// |ASN1_STRING|. +#define ASN1_STRFLGS_DUMP_DER 0x200 + +// ASN1_STRFLGS_RFC2253 causes the string to be escaped as in RFC 2253, +// additionally escaping control characters. +#define ASN1_STRFLGS_RFC2253 \ + (ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +// ASN1_STRING_print_ex writes a human-readable representation of |str| to +// |out|. It returns the number of bytes written on success and -1 on error. If +// |out| is NULL, it returns the number of bytes it would have written, without +// writing anything. +// +// The |flags| should be a combination of combination of |ASN1_STRFLGS_*| +// constants. See the documentation for each flag for how it controls the +// output. If unsure, use |ASN1_STRFLGS_RFC2253|. +OPENSSL_EXPORT int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, + unsigned long flags); + +// ASN1_STRING_print_ex_fp behaves like |ASN1_STRING_print_ex| but writes to a +// |FILE| rather than a |BIO|. +OPENSSL_EXPORT int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, + unsigned long flags); + +// i2a_ASN1_INTEGER writes a human-readable representation of |a| to |bp|. It +// returns the number of bytes written on success, or a negative number on +// error. On error, this function may have written a partial output to |bp|. +OPENSSL_EXPORT int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a); + +// i2a_ASN1_ENUMERATED writes a human-readable representation of |a| to |bp|. It +// returns the number of bytes written on success, or a negative number on +// error. On error, this function may have written a partial output to |bp|. +OPENSSL_EXPORT int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a); + +// i2a_ASN1_OBJECT writes a human-readable representation of |a| to |bp|. It +// returns the number of bytes written on success, or a negative number on +// error. On error, this function may have written a partial output to |bp|. +OPENSSL_EXPORT int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a); + +// i2a_ASN1_STRING writes a text representation of |a|'s contents to |bp|. It +// returns the number of bytes written on success, or a negative number on +// error. On error, this function may have written a partial output to |bp|. +// |type| is ignored. +// +// This function does not decode |a| into a Unicode string. It only hex-encodes +// the internal representation of |a|. This is suitable for printing an OCTET +// STRING, but may not be human-readable for any other string type. +OPENSSL_EXPORT int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type); + +// i2t_ASN1_OBJECT calls |OBJ_obj2txt| with |always_return_oid| set to zero. +OPENSSL_EXPORT int i2t_ASN1_OBJECT(char *buf, int buf_len, + const ASN1_OBJECT *a); + + +// Low-level encoding functions. + +// ASN1_get_object parses a BER element from up to |max_len| bytes at |*inp|. It +// returns |V_ASN1_CONSTRUCTED| if it successfully parsed a constructed element, +// zero if it successfully parsed a primitive element, and 0x80 on error. On +// success, it additionally advances |*inp| to the element body, sets +// |*out_length|, |*out_tag|, and |*out_class| to the element's length, tag +// number, and tag class, respectively, +// +// Unlike OpenSSL, this function only supports DER. Indefinite and non-minimal +// lengths are rejected. +// +// This function is difficult to use correctly. Use |CBS_get_asn1| and related +// functions from bytestring.h. +OPENSSL_EXPORT int ASN1_get_object(const unsigned char **inp, long *out_length, + int *out_tag, int *out_class, long max_len); + +// ASN1_put_object writes the header for a DER or BER element to |*outp| and +// advances |*outp| by the number of bytes written. The caller is responsible +// for ensuring |*outp| has enough space for the output. The header describes an +// element with length |length|, tag number |tag|, and class |xclass|. |xclass| +// should be one of the |V_ASN1_*| tag class constants. The element is primitive +// if |constructed| is zero and constructed if it is one or two. If +// |constructed| is two, |length| is ignored and the element uses +// indefinite-length encoding. +// +// Use |CBB_add_asn1| instead. +OPENSSL_EXPORT void ASN1_put_object(unsigned char **outp, int constructed, + int length, int tag, int xclass); + +// ASN1_put_eoc writes two zero bytes to |*outp|, advances |*outp| to point past +// those bytes, and returns two. +// +// Use definite-length encoding instead. +OPENSSL_EXPORT int ASN1_put_eoc(unsigned char **outp); + +// ASN1_object_size returns the number of bytes needed to encode a DER or BER +// value with length |length| and tag number |tag|, or -1 on error. |tag| should +// not include the constructed bit or tag class. If |constructed| is zero or +// one, the result uses a definite-length encoding with minimally-encoded +// length, as in DER. If |constructed| is two, the result uses BER +// indefinite-length encoding. +// +// Use |CBB_add_asn1| instead. +OPENSSL_EXPORT int ASN1_object_size(int constructed, int length, int tag); + + +// Function declaration macros. +// +// The following macros declare functions for ASN.1 types. Prefer writing the +// prototypes directly. Particularly when |type|, |itname|, or |name| differ, +// the macros can be difficult to understand. + +#define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type) + +#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type) + +#define DECLARE_ASN1_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) + +#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) + +#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \ + OPENSSL_EXPORT type *d2i_##name(type **a, const unsigned char **in, \ + long len); \ + OPENSSL_EXPORT int i2d_##name(type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(itname) + +#define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \ + OPENSSL_EXPORT type *d2i_##name(type **a, const unsigned char **in, \ + long len); \ + OPENSSL_EXPORT int i2d_##name(const type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(name) + +#define DECLARE_ASN1_FUNCTIONS_const(name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS(name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name) + +#define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + OPENSSL_EXPORT type *name##_new(void); \ + OPENSSL_EXPORT void name##_free(type *a); + + +// Deprecated functions. + +// ASN1_STRING_set_default_mask does nothing. +OPENSSL_EXPORT void ASN1_STRING_set_default_mask(unsigned long mask); + +// ASN1_STRING_set_default_mask_asc returns one. +OPENSSL_EXPORT int ASN1_STRING_set_default_mask_asc(const char *p); + +// ASN1_STRING_get_default_mask returns |B_ASN1_UTF8STRING|. +OPENSSL_EXPORT unsigned long ASN1_STRING_get_default_mask(void); + +// ASN1_STRING_TABLE_cleanup does nothing. +OPENSSL_EXPORT void ASN1_STRING_TABLE_cleanup(void); + +// M_ASN1_* are legacy aliases for various |ASN1_STRING| functions. Use the +// functions themselves. +#define M_ASN1_STRING_length(x) ASN1_STRING_length(x) +#define M_ASN1_STRING_type(x) ASN1_STRING_type(x) +#define M_ASN1_STRING_data(x) ASN1_STRING_data(x) +#define M_ASN1_BIT_STRING_new() ASN1_BIT_STRING_new() +#define M_ASN1_BIT_STRING_free(a) ASN1_BIT_STRING_free(a) +#define M_ASN1_BIT_STRING_dup(a) ASN1_STRING_dup(a) +#define M_ASN1_BIT_STRING_cmp(a, b) ASN1_STRING_cmp(a, b) +#define M_ASN1_BIT_STRING_set(a, b, c) ASN1_BIT_STRING_set(a, b, c) +#define M_ASN1_INTEGER_new() ASN1_INTEGER_new() +#define M_ASN1_INTEGER_free(a) ASN1_INTEGER_free(a) +#define M_ASN1_INTEGER_dup(a) ASN1_INTEGER_dup(a) +#define M_ASN1_INTEGER_cmp(a, b) ASN1_INTEGER_cmp(a, b) +#define M_ASN1_ENUMERATED_new() ASN1_ENUMERATED_new() +#define M_ASN1_ENUMERATED_free(a) ASN1_ENUMERATED_free(a) +#define M_ASN1_ENUMERATED_dup(a) ASN1_STRING_dup(a) +#define M_ASN1_ENUMERATED_cmp(a, b) ASN1_STRING_cmp(a, b) +#define M_ASN1_OCTET_STRING_new() ASN1_OCTET_STRING_new() +#define M_ASN1_OCTET_STRING_free(a) ASN1_OCTET_STRING_free() +#define M_ASN1_OCTET_STRING_dup(a) ASN1_OCTET_STRING_dup(a) +#define M_ASN1_OCTET_STRING_cmp(a, b) ASN1_OCTET_STRING_cmp(a, b) +#define M_ASN1_OCTET_STRING_set(a, b, c) ASN1_OCTET_STRING_set(a, b, c) +#define M_ASN1_OCTET_STRING_print(a, b) ASN1_STRING_print(a, b) +#define M_ASN1_PRINTABLESTRING_new() ASN1_PRINTABLESTRING_new() +#define M_ASN1_PRINTABLESTRING_free(a) ASN1_PRINTABLESTRING_free(a) +#define M_ASN1_IA5STRING_new() ASN1_IA5STRING_new() +#define M_ASN1_IA5STRING_free(a) ASN1_IA5STRING_free(a) +#define M_ASN1_IA5STRING_dup(a) ASN1_STRING_dup(a) +#define M_ASN1_UTCTIME_new() ASN1_UTCTIME_new() +#define M_ASN1_UTCTIME_free(a) ASN1_UTCTIME_free(a) +#define M_ASN1_UTCTIME_dup(a) ASN1_STRING_dup(a) +#define M_ASN1_T61STRING_new() ASN1_T61STRING_new() +#define M_ASN1_T61STRING_free(a) ASN1_T61STRING_free(a) +#define M_ASN1_GENERALIZEDTIME_new() ASN1_GENERALIZEDTIME_new() +#define M_ASN1_GENERALIZEDTIME_free(a) ASN1_GENERALIZEDTIME_free(a) +#define M_ASN1_GENERALIZEDTIME_dup(a) ASN1_STRING_dup(a) +#define M_ASN1_GENERALSTRING_new() ASN1_GENERALSTRING_new() +#define M_ASN1_GENERALSTRING_free(a) ASN1_GENERALSTRING_free(a) +#define M_ASN1_UNIVERSALSTRING_new() ASN1_UNIVERSALSTRING_new() +#define M_ASN1_UNIVERSALSTRING_free(a) ASN1_UNIVERSALSTRING_free(a) +#define M_ASN1_BMPSTRING_new() ASN1_BMPSTRING_new() +#define M_ASN1_BMPSTRING_free(a) ASN1_BMPSTRING_free(a) +#define M_ASN1_VISIBLESTRING_new() ASN1_VISIBLESTRING_new() +#define M_ASN1_VISIBLESTRING_free(a) ASN1_VISIBLESTRING_free(a) +#define M_ASN1_UTF8STRING_new() ASN1_UTF8STRING_new() +#define M_ASN1_UTF8STRING_free(a) ASN1_UTF8STRING_free(a) + +// B_ASN1_PRINTABLE is a bitmask for an ad-hoc subset of string-like types. Note +// the presence of |B_ASN1_UNKNOWN| means it includes types which |ASN1_tag2bit| +// maps to |B_ASN1_UNKNOWN|. +// +// Do not use this. Despite the name, it has no connection to PrintableString or +// printable characters. See https://crbug.com/boringssl/412. +#define B_ASN1_PRINTABLE \ + (B_ASN1_NUMERICSTRING | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | \ + B_ASN1_IA5STRING | B_ASN1_BIT_STRING | B_ASN1_UNIVERSALSTRING | \ + B_ASN1_BMPSTRING | B_ASN1_UTF8STRING | B_ASN1_SEQUENCE | B_ASN1_UNKNOWN) + +// ASN1_PRINTABLE_new returns a newly-allocated |ASN1_STRING| with type -1, or +// NULL on error. The resulting |ASN1_STRING| is not a valid ASN.1 value until +// initialized with a value. +OPENSSL_EXPORT ASN1_STRING *ASN1_PRINTABLE_new(void); + +// ASN1_PRINTABLE_free calls |ASN1_STRING_free|. +OPENSSL_EXPORT void ASN1_PRINTABLE_free(ASN1_STRING *str); + +// d2i_ASN1_PRINTABLE parses up to |len| bytes from |*inp| as a DER-encoded +// CHOICE of an ad-hoc subset of string-like types, as described in +// |d2i_SAMPLE|. +// +// Do not use this. Despite, the name it has no connection to PrintableString or +// printable characters. See https://crbug.com/boringssl/412. +// +// TODO(https://crbug.com/boringssl/354): This function currently also accepts +// BER, but this will be removed in the future. +OPENSSL_EXPORT ASN1_STRING *d2i_ASN1_PRINTABLE(ASN1_STRING **out, + const uint8_t **inp, long len); + +// i2d_ASN1_PRINTABLE marshals |in| as DER, as described in |i2d_SAMPLE|. +// +// Do not use this. Despite the name, it has no connection to PrintableString or +// printable characters. See https://crbug.com/boringssl/412. +OPENSSL_EXPORT int i2d_ASN1_PRINTABLE(const ASN1_STRING *in, uint8_t **outp); + +// ASN1_PRINTABLE is an |ASN1_ITEM| whose ASN.1 type is a CHOICE of an ad-hoc +// subset of string-like types, and whose C type is |ASN1_STRING*|. +// +// Do not use this. Despite the name, it has no connection to PrintableString or +// printable characters. See https://crbug.com/boringssl/412. +DECLARE_ASN1_ITEM(ASN1_PRINTABLE) + +// ASN1_INTEGER_set sets |a| to an INTEGER with value |v|. It returns one on +// success and zero on error. +// +// Use |ASN1_INTEGER_set_uint64| and |ASN1_INTEGER_set_int64| instead. +OPENSSL_EXPORT int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); + +// ASN1_ENUMERATED_set sets |a| to an ENUMERATED with value |v|. It returns one +// on success and zero on error. +// +// Use |ASN1_ENUMERATED_set_uint64| and |ASN1_ENUMERATED_set_int64| instead. +OPENSSL_EXPORT int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v); + +// ASN1_INTEGER_get returns the value of |a| as a |long|, or -1 if |a| is out of +// range or the wrong type. +// +// WARNING: This function's return value cannot distinguish errors from -1. +// Use |ASN1_INTEGER_get_uint64| and |ASN1_INTEGER_get_int64| instead. +OPENSSL_EXPORT long ASN1_INTEGER_get(const ASN1_INTEGER *a); + +// ASN1_ENUMERATED_get returns the value of |a| as a |long|, or -1 if |a| is out +// of range or the wrong type. +// +// WARNING: This function's return value cannot distinguish errors from -1. +// Use |ASN1_ENUMERATED_get_uint64| and |ASN1_ENUMERATED_get_int64| instead. +OPENSSL_EXPORT long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(ASN1_OBJECT, ASN1_OBJECT_free) +BORINGSSL_MAKE_DELETER(ASN1_STRING, ASN1_STRING_free) +BORINGSSL_MAKE_DELETER(ASN1_TYPE, ASN1_TYPE_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define ASN1_R_ASN1_LENGTH_MISMATCH 100 +#define ASN1_R_AUX_ERROR 101 +#define ASN1_R_BAD_GET_ASN1_OBJECT_CALL 102 +#define ASN1_R_BAD_OBJECT_HEADER 103 +#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 104 +#define ASN1_R_BN_LIB 105 +#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106 +#define ASN1_R_BUFFER_TOO_SMALL 107 +#define ASN1_R_CONTEXT_NOT_INITIALISED 108 +#define ASN1_R_DECODE_ERROR 109 +#define ASN1_R_DEPTH_EXCEEDED 110 +#define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 111 +#define ASN1_R_ENCODE_ERROR 112 +#define ASN1_R_ERROR_GETTING_TIME 113 +#define ASN1_R_EXPECTING_AN_ASN1_SEQUENCE 114 +#define ASN1_R_EXPECTING_AN_INTEGER 115 +#define ASN1_R_EXPECTING_AN_OBJECT 116 +#define ASN1_R_EXPECTING_A_BOOLEAN 117 +#define ASN1_R_EXPECTING_A_TIME 118 +#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119 +#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120 +#define ASN1_R_FIELD_MISSING 121 +#define ASN1_R_FIRST_NUM_TOO_LARGE 122 +#define ASN1_R_HEADER_TOO_LONG 123 +#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 124 +#define ASN1_R_ILLEGAL_BOOLEAN 125 +#define ASN1_R_ILLEGAL_CHARACTERS 126 +#define ASN1_R_ILLEGAL_FORMAT 127 +#define ASN1_R_ILLEGAL_HEX 128 +#define ASN1_R_ILLEGAL_IMPLICIT_TAG 129 +#define ASN1_R_ILLEGAL_INTEGER 130 +#define ASN1_R_ILLEGAL_NESTED_TAGGING 131 +#define ASN1_R_ILLEGAL_NULL 132 +#define ASN1_R_ILLEGAL_NULL_VALUE 133 +#define ASN1_R_ILLEGAL_OBJECT 134 +#define ASN1_R_ILLEGAL_OPTIONAL_ANY 135 +#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 136 +#define ASN1_R_ILLEGAL_TAGGED_ANY 137 +#define ASN1_R_ILLEGAL_TIME_VALUE 138 +#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 139 +#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 140 +#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 141 +#define ASN1_R_INVALID_BMPSTRING 142 +#define ASN1_R_INVALID_DIGIT 143 +#define ASN1_R_INVALID_MODIFIER 144 +#define ASN1_R_INVALID_NUMBER 145 +#define ASN1_R_INVALID_OBJECT_ENCODING 146 +#define ASN1_R_INVALID_SEPARATOR 147 +#define ASN1_R_INVALID_TIME_FORMAT 148 +#define ASN1_R_INVALID_UNIVERSALSTRING 149 +#define ASN1_R_INVALID_UTF8STRING 150 +#define ASN1_R_LIST_ERROR 151 +#define ASN1_R_MISSING_ASN1_EOS 152 +#define ASN1_R_MISSING_EOC 153 +#define ASN1_R_MISSING_SECOND_NUMBER 154 +#define ASN1_R_MISSING_VALUE 155 +#define ASN1_R_MSTRING_NOT_UNIVERSAL 156 +#define ASN1_R_MSTRING_WRONG_TAG 157 +#define ASN1_R_NESTED_ASN1_ERROR 158 +#define ASN1_R_NESTED_ASN1_STRING 159 +#define ASN1_R_NON_HEX_CHARACTERS 160 +#define ASN1_R_NOT_ASCII_FORMAT 161 +#define ASN1_R_NOT_ENOUGH_DATA 162 +#define ASN1_R_NO_MATCHING_CHOICE_TYPE 163 +#define ASN1_R_NULL_IS_WRONG_LENGTH 164 +#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 165 +#define ASN1_R_ODD_NUMBER_OF_CHARS 166 +#define ASN1_R_SECOND_NUMBER_TOO_LARGE 167 +#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 168 +#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 169 +#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 170 +#define ASN1_R_SHORT_LINE 171 +#define ASN1_R_STREAMING_NOT_SUPPORTED 172 +#define ASN1_R_STRING_TOO_LONG 173 +#define ASN1_R_STRING_TOO_SHORT 174 +#define ASN1_R_TAG_VALUE_TOO_HIGH 175 +#define ASN1_R_TIME_NOT_ASCII_FORMAT 176 +#define ASN1_R_TOO_LONG 177 +#define ASN1_R_TYPE_NOT_CONSTRUCTED 178 +#define ASN1_R_TYPE_NOT_PRIMITIVE 179 +#define ASN1_R_UNEXPECTED_EOC 180 +#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 181 +#define ASN1_R_UNKNOWN_FORMAT 182 +#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 183 +#define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 184 +#define ASN1_R_UNKNOWN_TAG 185 +#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 186 +#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 187 +#define ASN1_R_UNSUPPORTED_TYPE 188 +#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 189 +#define ASN1_R_WRONG_TAG 190 +#define ASN1_R_WRONG_TYPE 191 +#define ASN1_R_NESTED_TOO_DEEP 192 +#define ASN1_R_BAD_TEMPLATE 193 +#define ASN1_R_INVALID_BIT_STRING_PADDING 194 +#define ASN1_R_WRONG_INTEGER_TYPE 195 +#define ASN1_R_INVALID_INTEGER 196 + +#endif // OPENSSL_HEADER_ASN1_H diff --git a/lib/boringssl/include/openssl/asn1_mac.h b/lib/boringssl/include/openssl/asn1_mac.h new file mode 100644 index 00000000..666e5696 --- /dev/null +++ b/lib/boringssl/include/openssl/asn1_mac.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "asn1.h" diff --git a/lib/boringssl/include/openssl/asn1t.h b/lib/boringssl/include/openssl/asn1t.h new file mode 100644 index 00000000..7547b60a --- /dev/null +++ b/lib/boringssl/include/openssl/asn1t.h @@ -0,0 +1,666 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef OPENSSL_HEADER_ASN1T_H +#define OPENSSL_HEADER_ASN1T_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Legacy ASN.1 library template definitions. + * + * This header is used to define new types in OpenSSL's ASN.1 implementation. It + * is deprecated and will be unexported from the library. Use the new |CBS| and + * |CBB| library in instead. */ + + +typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; +typedef struct ASN1_TLC_st ASN1_TLC; + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr)) + + +/* Macros for start and end of ASN1_ITEM definition */ + +#define ASN1_ITEM_start(itname) \ + const ASN1_ITEM itname##_it = { + +#define ASN1_ITEM_end(itname) \ + }; + +/* Macros to aid ASN1 template writing */ + +#define ASN1_ITEM_TEMPLATE(tname) \ + static const ASN1_TEMPLATE tname##_item_tt + +#define ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) + + +/* This is a ASN1 type which just embeds a template */ + +/* This pair helps declare a SEQUENCE. We can do: + * + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END(stname) + * + * This will produce an ASN1_ITEM called stname_it + * for a structure called stname. + * + * If you want the same structure but a different + * name then use: + * + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END_name(stname, itname) + * + * This will create an item called itname_it using + * a structure called stname. + */ + +#define ASN1_SEQUENCE(tname) \ + static const ASN1_TEMPLATE tname##_seq_tt[] + +#define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) + +#define ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_SEQUENCE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, cb, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_ref(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), cb, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_enc(tname, enc, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, cb, offsetof(tname, enc)}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +#define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +#define ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + + +/* This pair helps declare a CHOICE type. We can do: + * + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname) + * + * This will produce an ASN1_ITEM called chname_it + * for a structure called chname. The structure + * definition must look like this: + * typedef struct { + * int type; + * union { + * ASN1_SOMETHING *opt1; + * ASN1_SOMEOTHER *opt2; + * } value; + * } chname; + * + * the name of the selector must be 'type'. + * to use an alternative selector name use the + * ASN1_CHOICE_END_selector() version. + */ + +#define ASN1_CHOICE(tname) \ + static const ASN1_TEMPLATE tname##_ch_tt[] + +#define ASN1_CHOICE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, cb, 0}; \ + ASN1_CHOICE(tname) + +#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) + +#define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type) + +#define ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_CHOICE_END_cb(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/* This helps with the template wrapper form of ASN1_ITEM */ + +#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \ + (flags), (tag), 0,\ + #name, ASN1_ITEM_ref(type) } + +/* These help with SEQUENCE or CHOICE components */ + +/* used to declare other types */ + +#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ + (flags), (tag), offsetof(stname, field),\ + #field, ASN1_ITEM_ref(type) } + +/* implicit and explicit helper macros */ + +#define ASN1_IMP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type) + +#define ASN1_EXP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type) + +/* Any defined by macros: the field used is in the table itself */ + +#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +/* Plain simple type */ +#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) + +/* OPTIONAL simple type */ +#define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* IMPLICIT tagged simple type */ +#define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) + +/* IMPLICIT tagged OPTIONAL simple type */ +#define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* Same as above but EXPLICIT */ + +#define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) +#define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* SEQUENCE OF type */ +#define ASN1_SEQUENCE_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) + +/* OPTIONAL SEQUENCE OF */ +#define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Same as above but for SET OF */ + +#define ASN1_SET_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) + +#define ASN1_SET_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ + +#define ASN1_IMP_SET_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_EXP_SET_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +/* Macros for the ASN1_ADB structure */ + +#define ASN1_ADB(name) \ + static const ASN1_ADB_TABLE name##_adbtbl[] + +#define ASN1_ADB_END(name, flags, field, app_table, def, none) \ + ;\ + static const ASN1_ADB name##_adb = {\ + flags,\ + offsetof(name, field),\ + app_table,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + } + +#define ADB_ENTRY(val, template) {val, template} + +#define ASN1_ADB_TEMPLATE(name) \ + static const ASN1_TEMPLATE name##_tt + +/* This is the ASN1 template structure that defines + * a wrapper round the actual type. It determines the + * actual position of the field in the value structure, + * various flags such as OPTIONAL and the field name. + */ + +struct ASN1_TEMPLATE_st { +uint32_t flags; /* Various flags */ +int tag; /* tag, not used if no tagging */ +unsigned long offset; /* Offset of this field in structure */ +const char *field_name; /* Field name */ +ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ +}; + +/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ + +#define ASN1_TEMPLATE_item(t) (t->item_ptr) +#define ASN1_TEMPLATE_adb(t) (t->item_ptr) + +typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; +typedef struct ASN1_ADB_st ASN1_ADB; + +typedef struct asn1_must_be_null_st ASN1_MUST_BE_NULL; + +struct ASN1_ADB_st { + uint32_t flags; /* Various flags */ + unsigned long offset; /* Offset of selector field */ + ASN1_MUST_BE_NULL *unused; + const ASN1_ADB_TABLE *tbl; /* Table of possible types */ + long tblcount; /* Number of entries in tbl */ + const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ + const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ +}; + +struct ASN1_ADB_TABLE_st { + int value; /* NID for an object */ + const ASN1_TEMPLATE tt; /* item for this value */ +}; + +/* template flags */ + +/* Field is optional */ +#define ASN1_TFLG_OPTIONAL (0x1) + +/* Field is a SET OF */ +#define ASN1_TFLG_SET_OF (0x1 << 1) + +/* Field is a SEQUENCE OF */ +#define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) + +/* Mask for SET OF or SEQUENCE OF */ +#define ASN1_TFLG_SK_MASK (0x3 << 1) + +/* These flags mean the tag should be taken from the + * tag field. If EXPLICIT then the underlying type + * is used for the inner tag. + */ + +/* IMPLICIT tagging */ +#define ASN1_TFLG_IMPTAG (0x1 << 3) + + +/* EXPLICIT tagging, inner tag from underlying type */ +#define ASN1_TFLG_EXPTAG (0x2 << 3) + +#define ASN1_TFLG_TAG_MASK (0x3 << 3) + +/* context specific IMPLICIT */ +#define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT + +/* context specific EXPLICIT */ +#define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT + +/* If tagging is in force these determine the + * type of tag to use. Otherwise the tag is + * determined by the underlying type. These + * values reflect the actual octet format. + */ + +/* Universal tag */ +#define ASN1_TFLG_UNIVERSAL (0x0<<6) +/* Application tag */ +#define ASN1_TFLG_APPLICATION (0x1<<6) +/* Context specific tag */ +#define ASN1_TFLG_CONTEXT (0x2<<6) +/* Private tag */ +#define ASN1_TFLG_PRIVATE (0x3<<6) + +#define ASN1_TFLG_TAG_CLASS (0x3<<6) + +/* These are for ANY DEFINED BY type. In this case + * the 'item' field points to an ASN1_ADB structure + * which contains a table of values to decode the + * relevant type + */ + +#define ASN1_TFLG_ADB_MASK (0x3<<8) + +#define ASN1_TFLG_ADB_OID (0x1<<8) + +/* This is the actual ASN1 item itself */ + +struct ASN1_ITEM_st { +char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */ +int utype; /* underlying type */ +const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */ +long tcount; /* Number of templates if SEQUENCE or CHOICE */ +const void *funcs; /* functions that handle this type */ +long size; /* Structure size (usually)*/ +const char *sname; /* Structure name */ +}; + +/* These are values for the itype field and + * determine how the type is interpreted. + * + * For PRIMITIVE types the underlying type + * determines the behaviour if items is NULL. + * + * Otherwise templates must contain a single + * template and the type is treated in the + * same way as the type specified in the template. + * + * For SEQUENCE types the templates field points + * to the members, the size field is the + * structure size. + * + * For CHOICE types the templates field points + * to each possible member (typically a union) + * and the 'size' field is the offset of the + * selector. + * + * The 'funcs' field is used for application + * specific functions. + * + * The EXTERN type uses a new style d2i/i2d. + * The new style should be used where possible + * because it avoids things like the d2i IMPLICIT + * hack. + * + * MSTRING is a multiple string type, it is used + * for a CHOICE of character strings where the + * actual strings all occupy an ASN1_STRING + * structure. In this case the 'utype' field + * has a special meaning, it is used as a mask + * of acceptable types using the B_ASN1 constants. + * + */ + +#define ASN1_ITYPE_PRIMITIVE 0x0 + +#define ASN1_ITYPE_SEQUENCE 0x1 + +#define ASN1_ITYPE_CHOICE 0x2 + +#define ASN1_ITYPE_EXTERN 0x4 + +#define ASN1_ITYPE_MSTRING 0x5 + +/* Deprecated tag and length cache */ +struct ASN1_TLC_st; + +/* This is the ASN1_AUX structure: it handles various + * miscellaneous requirements. For example the use of + * reference counts and an informational callback. + * + * The "informational callback" is called at various + * points during the ASN1 encoding and decoding. It can + * be used to provide minor customisation of the structures + * used. This is most useful where the supplied routines + * *almost* do the right thing but need some extra help + * at a few points. If the callback returns zero then + * it is assumed a fatal error has occurred and the + * main operation should be abandoned. + * + * If major changes in the default behaviour are required + * then an external type is more appropriate. + */ + +typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it, + void *exarg); + +typedef struct ASN1_AUX_st { + void *app_data; + uint32_t flags; + int ref_offset; /* Offset of reference value */ + ASN1_aux_cb *asn1_cb; + int enc_offset; /* Offset of ASN1_ENCODING structure */ +} ASN1_AUX; + +/* Flags in ASN1_AUX */ + +/* Use a reference count */ +#define ASN1_AFLG_REFCOUNT 1 +/* Save the encoding of structure (useful for signatures) */ +#define ASN1_AFLG_ENCODING 2 + +/* operation values for asn1_cb */ + +#define ASN1_OP_NEW_PRE 0 +#define ASN1_OP_NEW_POST 1 +#define ASN1_OP_FREE_PRE 2 +#define ASN1_OP_FREE_POST 3 +#define ASN1_OP_D2I_PRE 4 +#define ASN1_OP_D2I_POST 5 +/* ASN1_OP_I2D_PRE and ASN1_OP_I2D_POST are not supported. We leave the + * constants undefined so code relying on them does not accidentally compile. */ +#define ASN1_OP_PRINT_PRE 8 +#define ASN1_OP_PRINT_POST 9 +#define ASN1_OP_STREAM_PRE 10 +#define ASN1_OP_STREAM_POST 11 +#define ASN1_OP_DETACHED_PRE 12 +#define ASN1_OP_DETACHED_POST 13 + +/* Macro to implement a primitive type */ +#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0) +#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement a multi string type */ +#define IMPLEMENT_ASN1_MSTRING(itname, mask) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \ + ASN1_ITEM_end(itname) + +#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_EXTERN, \ + tag, \ + NULL, \ + 0, \ + &fptrs, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +/* Macro to implement standard functions in terms of ASN1_ITEM structures */ + +#define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname) + +#define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname) + +#define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \ + IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname) + +#define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname) + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname) + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \ + pre stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + pre void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ + stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +#define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +/* This includes evil casts to remove const: they will go away when full + * ASN1 constification is done. + */ +#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(const stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ + stname *stname##_dup(stname *x) { \ + return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \ + } + +#define IMPLEMENT_ASN1_DUP_FUNCTION_const(stname) \ + stname *stname##_dup(const stname *x) { \ + return ASN1_item_dup(ASN1_ITEM_rptr(stname), (void *)x); \ + } + +#define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ + IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) + +#define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +/* external definitions for primitive types */ + +DECLARE_ASN1_ITEM(ASN1_SEQUENCE) + +DEFINE_STACK_OF(ASN1_VALUE) + + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // OPENSSL_HEADER_ASN1T_H diff --git a/lib/boringssl/include/openssl/base.h b/lib/boringssl/include/openssl/base.h new file mode 100644 index 00000000..67429c09 --- /dev/null +++ b/lib/boringssl/include/openssl/base.h @@ -0,0 +1,659 @@ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_BASE_H +#define OPENSSL_HEADER_BASE_H + + +// This file should be the first included by all BoringSSL headers. + +#include +#include +#include + +#if defined(__MINGW32__) +// stdio.h is needed on MinGW for __MINGW_PRINTF_FORMAT. +#include +#endif + +#if defined(__APPLE__) +#include +#endif + +// Include a BoringSSL-only header so consumers including this header without +// setting up include paths do not accidentally pick up the system +// opensslconf.h. +#include +#include + +#if defined(BORINGSSL_PREFIX) +#include +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) +#define OPENSSL_64_BIT +#define OPENSSL_X86_64 +#elif defined(__x86) || defined(__i386) || defined(__i386__) || defined(_M_IX86) +#define OPENSSL_32_BIT +#define OPENSSL_X86 +#elif defined(__AARCH64EL__) || defined(_M_ARM64) +#define OPENSSL_64_BIT +#define OPENSSL_AARCH64 +#elif defined(__ARMEL__) || defined(_M_ARM) +#define OPENSSL_32_BIT +#define OPENSSL_ARM +#elif defined(__MIPSEL__) && !defined(__LP64__) +#define OPENSSL_32_BIT +#define OPENSSL_MIPS +#elif defined(__MIPSEL__) && defined(__LP64__) +#define OPENSSL_64_BIT +#define OPENSSL_MIPS64 +#elif defined(__riscv) && __SIZEOF_POINTER__ == 8 +#define OPENSSL_64_BIT +#define OPENSSL_RISCV64 +#elif defined(__riscv) && __SIZEOF_POINTER__ == 4 +#define OPENSSL_32_BIT +#elif defined(__pnacl__) +#define OPENSSL_32_BIT +#define OPENSSL_PNACL +#elif defined(__wasm__) +#define OPENSSL_32_BIT +#elif defined(__asmjs__) +#define OPENSSL_32_BIT +#elif defined(__myriad2__) +#define OPENSSL_32_BIT +#else +// Note BoringSSL only supports standard 32-bit and 64-bit two's-complement, +// little-endian architectures. Functions will not produce the correct answer +// on other systems. Run the crypto_test binary, notably +// crypto/compiler_test.cc, before adding a new architecture. +#error "Unknown target CPU" +#endif + +#if defined(__APPLE__) +#define OPENSSL_APPLE +// Note |TARGET_OS_MAC| is set for all Apple OS variants. |TARGET_OS_OSX| +// targets macOS specifically. +#if defined(TARGET_OS_OSX) && TARGET_OS_OSX +#define OPENSSL_MACOS +#endif +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#define OPENSSL_IOS +#endif +#endif + +#if defined(_WIN32) +#define OPENSSL_WINDOWS +#endif + +// Trusty isn't Linux but currently defines __linux__. As a workaround, we +// exclude it here. +// TODO(b/169780122): Remove this workaround once Trusty no longer defines it. +#if defined(__linux__) && !defined(__TRUSTY__) +#define OPENSSL_LINUX +#endif + +#if defined(__Fuchsia__) +#define OPENSSL_FUCHSIA +#endif + +#if defined(__TRUSTY__) +#define OPENSSL_TRUSTY +#define OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED +#endif + +#if defined(__ANDROID_API__) +#define OPENSSL_ANDROID +#endif + +#if defined(__FreeBSD__) +#define OPENSSL_FREEBSD +#endif + +// BoringSSL requires platform's locking APIs to make internal global state +// thread-safe, including the PRNG. On some single-threaded embedded platforms, +// locking APIs may not exist, so this dependency may be disabled with the +// following build flag. +// +// IMPORTANT: Doing so means the consumer promises the library will never be +// used in any multi-threaded context. It causes BoringSSL to be globally +// thread-unsafe. Setting it inappropriately will subtly and unpredictably +// corrupt memory and leak secret keys. +// +// Do not set this flag on any platform where threads are possible. BoringSSL +// maintainers will not provide support for any consumers that do so. Changes +// which break such unsupported configurations will not be reverted. +#if !defined(OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED) +#define OPENSSL_THREADS +#endif + +#define OPENSSL_IS_BORINGSSL +#define OPENSSL_VERSION_NUMBER 0x1010107f +#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER + +// BORINGSSL_API_VERSION is a positive integer that increments as BoringSSL +// changes over time. The value itself is not meaningful. It will be incremented +// whenever is convenient to coordinate an API change with consumers. This will +// not denote any special point in development. +// +// A consumer may use this symbol in the preprocessor to temporarily build +// against multiple revisions of BoringSSL at the same time. It is not +// recommended to do so for longer than is necessary. +#define BORINGSSL_API_VERSION 21 + +#if defined(BORINGSSL_SHARED_LIBRARY) + +#if defined(OPENSSL_WINDOWS) + +#if defined(BORINGSSL_IMPLEMENTATION) +#define OPENSSL_EXPORT __declspec(dllexport) +#else +#define OPENSSL_EXPORT __declspec(dllimport) +#endif + +#else // defined(OPENSSL_WINDOWS) + +#if defined(BORINGSSL_IMPLEMENTATION) +#define OPENSSL_EXPORT __attribute__((visibility("default"))) +#else +#define OPENSSL_EXPORT +#endif + +#endif // defined(OPENSSL_WINDOWS) + +#else // defined(BORINGSSL_SHARED_LIBRARY) + +#define OPENSSL_EXPORT + +#endif // defined(BORINGSSL_SHARED_LIBRARY) + +#if defined(_MSC_VER) + +// OPENSSL_DEPRECATED is used to mark a function as deprecated. Use +// of any functions so marked in caller code will produce a warning. +// OPENSSL_BEGIN_ALLOW_DEPRECATED and OPENSSL_END_ALLOW_DEPRECATED +// can be used to suppress the warning in regions of caller code. +#define OPENSSL_DEPRECATED __declspec(deprecated) +#define OPENSSL_BEGIN_ALLOW_DEPRECATED \ + __pragma(warning(push)) __pragma(warning(disable : 4996)) +#define OPENSSL_END_ALLOW_DEPRECATED __pragma(warning(pop)) + +#elif defined(__GNUC__) || defined(__clang__) + +#define OPENSSL_DEPRECATED __attribute__((__deprecated__)) +#define OPENSSL_BEGIN_ALLOW_DEPRECATED \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#define OPENSSL_END_ALLOW_DEPRECATED _Pragma("GCC diagnostic pop") + +#else + +#define OPENSSL_DEPRECATED +#define OPENSSL_BEGIN_ALLOW_DEPRECATED +#define OPENSSL_END_ALLOW_DEPRECATED + +#endif + + +#if defined(__GNUC__) || defined(__clang__) +// MinGW has two different printf implementations. Ensure the format macro +// matches the selected implementation. See +// https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/. +#if defined(__MINGW_PRINTF_FORMAT) +#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) \ + __attribute__( \ + (__format__(__MINGW_PRINTF_FORMAT, string_index, first_to_check))) +#else +#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) \ + __attribute__((__format__(__printf__, string_index, first_to_check))) +#endif +#else +#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) +#endif + +// OPENSSL_MSVC_PRAGMA emits a pragma on MSVC and nothing on other compilers. +#if defined(_MSC_VER) +#define OPENSSL_MSVC_PRAGMA(arg) __pragma(arg) +#else +#define OPENSSL_MSVC_PRAGMA(arg) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define OPENSSL_UNUSED __attribute__((unused)) +#else +#define OPENSSL_UNUSED +#endif + +// C and C++ handle inline functions differently. In C++, an inline function is +// defined in just the header file, potentially emitted in multiple compilation +// units (in cases the compiler did not inline), but each copy must be identical +// to satsify ODR. In C, a non-static inline must be manually emitted in exactly +// one compilation unit with a separate extern inline declaration. +// +// In both languages, exported inline functions referencing file-local symbols +// are problematic. C forbids this altogether (though GCC and Clang seem not to +// enforce it). It works in C++, but ODR requires the definitions be identical, +// including all names in the definitions resolving to the "same entity". In +// practice, this is unlikely to be a problem, but an inline function that +// returns a pointer to a file-local symbol +// could compile oddly. +// +// Historically, we used static inline in headers. However, to satisfy ODR, use +// plain inline in C++, to allow inline consumer functions to call our header +// functions. Plain inline would also work better with C99 inline, but that is +// not used much in practice, extern inline is tedious, and there are conflicts +// with the old gnu89 model: +// https://stackoverflow.com/questions/216510/extern-inline +#if defined(__cplusplus) +#define OPENSSL_INLINE inline +#else +// Add OPENSSL_UNUSED so that, should an inline function be emitted via macro +// (e.g. a |STACK_OF(T)| implementation) in a source file without tripping +// clang's -Wunused-function. +#define OPENSSL_INLINE static inline OPENSSL_UNUSED +#endif + +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) && \ + !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) +#define BORINGSSL_UNSAFE_DETERMINISTIC_MODE +#endif + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define OPENSSL_ASAN +#endif +#if __has_feature(thread_sanitizer) +#define OPENSSL_TSAN +#endif +#if __has_feature(memory_sanitizer) +#define OPENSSL_MSAN +#define OPENSSL_ASM_INCOMPATIBLE +#endif +#endif + +#if defined(OPENSSL_ASM_INCOMPATIBLE) +#undef OPENSSL_ASM_INCOMPATIBLE +#if !defined(OPENSSL_NO_ASM) +#define OPENSSL_NO_ASM +#endif +#endif // OPENSSL_ASM_INCOMPATIBLE + +#if defined(__cplusplus) +// enums can be predeclared, but only in C++ and only if given an explicit type. +// C doesn't support setting an explicit type for enums thus a #define is used +// to do this only for C++. However, the ABI type between C and C++ need to have +// equal sizes, which is confirmed in a unittest. +#define BORINGSSL_ENUM_INT : int +enum ssl_early_data_reason_t BORINGSSL_ENUM_INT; +enum ssl_encryption_level_t BORINGSSL_ENUM_INT; +enum ssl_private_key_result_t BORINGSSL_ENUM_INT; +enum ssl_renegotiate_mode_t BORINGSSL_ENUM_INT; +enum ssl_select_cert_result_t BORINGSSL_ENUM_INT; +enum ssl_select_cert_result_t BORINGSSL_ENUM_INT; +enum ssl_ticket_aead_result_t BORINGSSL_ENUM_INT; +enum ssl_verify_result_t BORINGSSL_ENUM_INT; +#else +#define BORINGSSL_ENUM_INT +#endif + +// ossl_ssize_t is a signed type which is large enough to fit the size of any +// valid memory allocation. We prefer using |size_t|, but sometimes we need a +// signed type for OpenSSL API compatibility. This type can be used in such +// cases to avoid overflow. +// +// Not all |size_t| values fit in |ossl_ssize_t|, but all |size_t| values that +// are sizes of or indices into C objects, can be converted without overflow. +typedef ptrdiff_t ossl_ssize_t; + +// CBS_ASN1_TAG is the type used by |CBS| and |CBB| for ASN.1 tags. See that +// header for details. This type is defined in base.h as a forward declaration. +typedef uint32_t CBS_ASN1_TAG; + +// CRYPTO_THREADID is a dummy value. +typedef int CRYPTO_THREADID; + +// An |ASN1_NULL| is an opaque type. asn1.h represents the ASN.1 NULL value as +// an opaque, non-NULL |ASN1_NULL*| pointer. +typedef struct asn1_null_st ASN1_NULL; + +typedef int ASN1_BOOLEAN; +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct asn1_object_st ASN1_OBJECT; +typedef struct asn1_pctx_st ASN1_PCTX; +typedef struct asn1_string_st ASN1_BIT_STRING; +typedef struct asn1_string_st ASN1_BMPSTRING; +typedef struct asn1_string_st ASN1_ENUMERATED; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; +typedef struct asn1_string_st ASN1_GENERALSTRING; +typedef struct asn1_string_st ASN1_IA5STRING; +typedef struct asn1_string_st ASN1_INTEGER; +typedef struct asn1_string_st ASN1_OCTET_STRING; +typedef struct asn1_string_st ASN1_PRINTABLESTRING; +typedef struct asn1_string_st ASN1_STRING; +typedef struct asn1_string_st ASN1_T61STRING; +typedef struct asn1_string_st ASN1_TIME; +typedef struct asn1_string_st ASN1_UNIVERSALSTRING; +typedef struct asn1_string_st ASN1_UTCTIME; +typedef struct asn1_string_st ASN1_UTF8STRING; +typedef struct asn1_string_st ASN1_VISIBLESTRING; +typedef struct asn1_type_st ASN1_TYPE; +typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID; +typedef struct BASIC_CONSTRAINTS_st BASIC_CONSTRAINTS; +typedef struct DIST_POINT_st DIST_POINT; +typedef struct DSA_SIG_st DSA_SIG; +typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT; +typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS; +typedef struct Netscape_spkac_st NETSCAPE_SPKAC; +typedef struct Netscape_spki_st NETSCAPE_SPKI; +typedef struct RIPEMD160state_st RIPEMD160_CTX; +typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM; +typedef struct X509_algor_st X509_ALGOR; +typedef struct X509_crl_st X509_CRL; +typedef struct X509_extension_st X509_EXTENSION; +typedef struct X509_info_st X509_INFO; +typedef struct X509_name_entry_st X509_NAME_ENTRY; +typedef struct X509_name_st X509_NAME; +typedef struct X509_pubkey_st X509_PUBKEY; +typedef struct X509_req_st X509_REQ; +typedef struct X509_sig_st X509_SIG; +typedef struct bignum_ctx BN_CTX; +typedef struct bignum_st BIGNUM; +typedef struct bio_method_st BIO_METHOD; +typedef struct bio_st BIO; +typedef struct blake2b_state_st BLAKE2B_CTX; +typedef struct bn_gencb_st BN_GENCB; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct buf_mem_st BUF_MEM; +typedef struct cbb_st CBB; +typedef struct cbs_st CBS; +typedef struct cmac_ctx_st CMAC_CTX; +typedef struct conf_st CONF; +typedef struct conf_value_st CONF_VALUE; +typedef struct crypto_buffer_pool_st CRYPTO_BUFFER_POOL; +typedef struct crypto_buffer_st CRYPTO_BUFFER; +typedef struct ctr_drbg_state_st CTR_DRBG_STATE; +typedef struct dh_st DH; +typedef struct dsa_st DSA; +typedef struct ec_group_st EC_GROUP; +typedef struct ec_key_st EC_KEY; +typedef struct ec_point_st EC_POINT; +typedef struct ecdsa_method_st ECDSA_METHOD; +typedef struct ecdsa_sig_st ECDSA_SIG; +typedef struct engine_st ENGINE; +typedef struct env_md_ctx_st EVP_MD_CTX; +typedef struct env_md_st EVP_MD; +typedef struct evp_aead_st EVP_AEAD; +typedef struct evp_aead_ctx_st EVP_AEAD_CTX; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_encode_ctx_st EVP_ENCODE_CTX; +typedef struct evp_hpke_aead_st EVP_HPKE_AEAD; +typedef struct evp_hpke_ctx_st EVP_HPKE_CTX; +typedef struct evp_hpke_kdf_st EVP_HPKE_KDF; +typedef struct evp_hpke_kem_st EVP_HPKE_KEM; +typedef struct evp_hpke_key_st EVP_HPKE_KEY; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; +typedef struct evp_pkey_st EVP_PKEY; +typedef struct hmac_ctx_st HMAC_CTX; +typedef struct md4_state_st MD4_CTX; +typedef struct md5_state_st MD5_CTX; +typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS; +typedef struct pkcs12_st PKCS12; +typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; +typedef struct private_key_st X509_PKEY; +typedef struct rand_meth_st RAND_METHOD; +typedef struct rc4_key_st RC4_KEY; +typedef struct rsa_meth_st RSA_METHOD; +typedef struct rsa_pss_params_st RSA_PSS_PARAMS; +typedef struct rsa_st RSA; +typedef struct sha256_state_st SHA256_CTX; +typedef struct sha512_state_st SHA512_CTX; +typedef struct sha_state_st SHA_CTX; +typedef struct spake2_ctx_st SPAKE2_CTX; +typedef struct srtp_protection_profile_st SRTP_PROTECTION_PROFILE; +typedef struct ssl_cipher_st SSL_CIPHER; +typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_early_callback_ctx SSL_CLIENT_HELLO; +typedef struct ssl_ech_keys_st SSL_ECH_KEYS; +typedef struct ssl_method_st SSL_METHOD; +typedef struct ssl_private_key_method_st SSL_PRIVATE_KEY_METHOD; +typedef struct ssl_quic_method_st SSL_QUIC_METHOD; +typedef struct ssl_session_st SSL_SESSION; +typedef struct ssl_st SSL; +typedef struct ssl_ticket_aead_method_st SSL_TICKET_AEAD_METHOD; +typedef struct st_ERR_FNS ERR_FNS; +typedef struct trust_token_st TRUST_TOKEN; +typedef struct trust_token_client_st TRUST_TOKEN_CLIENT; +typedef struct trust_token_issuer_st TRUST_TOKEN_ISSUER; +typedef struct trust_token_method_st TRUST_TOKEN_METHOD; +typedef struct v3_ext_ctx X509V3_CTX; +typedef struct x509_attributes_st X509_ATTRIBUTE; +typedef struct x509_lookup_st X509_LOOKUP; +typedef struct x509_lookup_method_st X509_LOOKUP_METHOD; +typedef struct x509_object_st X509_OBJECT; +typedef struct x509_revoked_st X509_REVOKED; +typedef struct x509_st X509; +typedef struct x509_store_ctx_st X509_STORE_CTX; +typedef struct x509_store_st X509_STORE; +typedef struct x509_trust_st X509_TRUST; + +typedef void *OPENSSL_BLOCK; + + +#if defined(__cplusplus) +} // extern C +#elif !defined(BORINGSSL_NO_CXX) +#define BORINGSSL_NO_CXX +#endif + +#if defined(BORINGSSL_PREFIX) +#define BSSL_NAMESPACE_BEGIN \ + namespace bssl { \ + inline namespace BORINGSSL_PREFIX { +#define BSSL_NAMESPACE_END \ + } \ + } +#else +#define BSSL_NAMESPACE_BEGIN namespace bssl { +#define BSSL_NAMESPACE_END } +#endif + +// MSVC doesn't set __cplusplus to 201103 to indicate C++11 support (see +// https://connect.microsoft.com/VisualStudio/feedback/details/763051/a-value-of-predefined-macro-cplusplus-is-still-199711l) +// so MSVC is just assumed to support C++11. +#if !defined(BORINGSSL_NO_CXX) && __cplusplus < 201103L && !defined(_MSC_VER) +#define BORINGSSL_NO_CXX +#endif + +#if !defined(BORINGSSL_NO_CXX) + +extern "C++" { + +#include + +// STLPort, used by some Android consumers, not have std::unique_ptr. +#if defined(_STLPORT_VERSION) +#define BORINGSSL_NO_CXX +#endif + +} // extern C++ +#endif // !BORINGSSL_NO_CXX + +#if defined(BORINGSSL_NO_CXX) + +#define BORINGSSL_MAKE_DELETER(type, deleter) +#define BORINGSSL_MAKE_UP_REF(type, up_ref_func) + +#else + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +namespace internal { + +// The Enable parameter is ignored and only exists so specializations can use +// SFINAE. +template +struct DeleterImpl {}; + +struct Deleter { + template + void operator()(T *ptr) { + // Rather than specialize Deleter for each type, we specialize + // DeleterImpl. This allows bssl::UniquePtr to be used while only + // including base.h as long as the destructor is not emitted. This matches + // std::unique_ptr's behavior on forward-declared types. + // + // DeleterImpl itself is specialized in the corresponding module's header + // and must be included to release an object. If not included, the compiler + // will error that DeleterImpl does not have a method Free. + DeleterImpl::Free(ptr); + } +}; + +template +class StackAllocated { + public: + StackAllocated() { init(&ctx_); } + ~StackAllocated() { cleanup(&ctx_); } + + StackAllocated(const StackAllocated &) = delete; + StackAllocated& operator=(const StackAllocated &) = delete; + + T *get() { return &ctx_; } + const T *get() const { return &ctx_; } + + T *operator->() { return &ctx_; } + const T *operator->() const { return &ctx_; } + + void Reset() { + cleanup(&ctx_); + init(&ctx_); + } + + private: + T ctx_; +}; + +template +class StackAllocatedMovable { + public: + StackAllocatedMovable() { init(&ctx_); } + ~StackAllocatedMovable() { cleanup(&ctx_); } + + StackAllocatedMovable(StackAllocatedMovable &&other) { + init(&ctx_); + move(&ctx_, &other.ctx_); + } + StackAllocatedMovable &operator=(StackAllocatedMovable &&other) { + move(&ctx_, &other.ctx_); + return *this; + } + + T *get() { return &ctx_; } + const T *get() const { return &ctx_; } + + T *operator->() { return &ctx_; } + const T *operator->() const { return &ctx_; } + + void Reset() { + cleanup(&ctx_); + init(&ctx_); + } + + private: + T ctx_; +}; + +} // namespace internal + +#define BORINGSSL_MAKE_DELETER(type, deleter) \ + namespace internal { \ + template <> \ + struct DeleterImpl { \ + static void Free(type *ptr) { deleter(ptr); } \ + }; \ + } + +// Holds ownership of heap-allocated BoringSSL structures. Sample usage: +// bssl::UniquePtr rsa(RSA_new()); +// bssl::UniquePtr bio(BIO_new(BIO_s_mem())); +template +using UniquePtr = std::unique_ptr; + +#define BORINGSSL_MAKE_UP_REF(type, up_ref_func) \ + inline UniquePtr UpRef(type *v) { \ + if (v != nullptr) { \ + up_ref_func(v); \ + } \ + return UniquePtr(v); \ + } \ + \ + inline UniquePtr UpRef(const UniquePtr &ptr) { \ + return UpRef(ptr.get()); \ + } + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif // !BORINGSSL_NO_CXX + +#endif // OPENSSL_HEADER_BASE_H diff --git a/lib/boringssl/include/openssl/base64.h b/lib/boringssl/include/openssl/base64.h new file mode 100644 index 00000000..369ba9c3 --- /dev/null +++ b/lib/boringssl/include/openssl/base64.h @@ -0,0 +1,198 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BASE64_H +#define OPENSSL_HEADER_BASE64_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// base64 functions. +// +// For historical reasons, these functions have the EVP_ prefix but just do +// base64 encoding and decoding. Note that BoringSSL is a cryptography library, +// so these functions are implemented with side channel protections, at a +// performance cost. For other base64 uses, use a general-purpose base64 +// implementation. + + +// Encoding + +// EVP_EncodeBlock encodes |src_len| bytes from |src| and writes the +// result to |dst| with a trailing NUL. It returns the number of bytes +// written, not including this trailing NUL. +OPENSSL_EXPORT size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, + size_t src_len); + +// EVP_EncodedLength sets |*out_len| to the number of bytes that will be needed +// to call |EVP_EncodeBlock| on an input of length |len|. This includes the +// final NUL that |EVP_EncodeBlock| writes. It returns one on success or zero +// on error. +OPENSSL_EXPORT int EVP_EncodedLength(size_t *out_len, size_t len); + + +// Decoding + +// EVP_DecodedLength sets |*out_len| to the maximum number of bytes that will +// be needed to call |EVP_DecodeBase64| on an input of length |len|. It returns +// one on success or zero if |len| is not a valid length for a base64-encoded +// string. +OPENSSL_EXPORT int EVP_DecodedLength(size_t *out_len, size_t len); + +// EVP_DecodeBase64 decodes |in_len| bytes from base64 and writes +// |*out_len| bytes to |out|. |max_out| is the size of the output +// buffer. If it is not enough for the maximum output size, the +// operation fails. It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_DecodeBase64(uint8_t *out, size_t *out_len, + size_t max_out, const uint8_t *in, + size_t in_len); + + +// Deprecated functions. +// +// OpenSSL provides a streaming base64 implementation, however its behavior is +// very specific to PEM. It is also very lenient of invalid input. Use of any of +// these functions is thus deprecated. + +// EVP_ENCODE_CTX_new returns a newly-allocated |EVP_ENCODE_CTX| or NULL on +// error. The caller must release the result with |EVP_ENCODE_CTX_free| when +// done. +OPENSSL_EXPORT EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void); + +// EVP_ENCODE_CTX_free releases memory associated with |ctx|. +OPENSSL_EXPORT void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx); + +// EVP_EncodeInit initialises |*ctx|, which is typically stack +// allocated, for an encoding operation. +// +// NOTE: The encoding operation breaks its output with newlines every +// 64 characters of output (48 characters of input). Use +// EVP_EncodeBlock to encode raw base64. +OPENSSL_EXPORT void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); + +// EVP_EncodeUpdate encodes |in_len| bytes from |in| and writes an encoded +// version of them to |out| and sets |*out_len| to the number of bytes written. +// Some state may be contained in |ctx| so |EVP_EncodeFinal| must be used to +// flush it before using the encoded data. +OPENSSL_EXPORT void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + size_t in_len); + +// EVP_EncodeFinal flushes any remaining output bytes from |ctx| to |out| and +// sets |*out_len| to the number of bytes written. +OPENSSL_EXPORT void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, + int *out_len); + +// EVP_DecodeInit initialises |*ctx|, which is typically stack allocated, for +// a decoding operation. +// +// TODO(davidben): This isn't a straight-up base64 decode either. Document +// and/or fix exactly what's going on here; maximum line length and such. +OPENSSL_EXPORT void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); + +// EVP_DecodeUpdate decodes |in_len| bytes from |in| and writes the decoded +// data to |out| and sets |*out_len| to the number of bytes written. Some state +// may be contained in |ctx| so |EVP_DecodeFinal| must be used to flush it +// before using the encoded data. +// +// It returns -1 on error, one if a full line of input was processed and zero +// if the line was short (i.e. it was the last line). +OPENSSL_EXPORT int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + size_t in_len); + +// EVP_DecodeFinal flushes any remaining output bytes from |ctx| to |out| and +// sets |*out_len| to the number of bytes written. It returns one on success +// and minus one on error. +OPENSSL_EXPORT int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, + int *out_len); + +// EVP_DecodeBlock encodes |src_len| bytes from |src| and writes the result to +// |dst|. It returns the number of bytes written or -1 on error. +// +// WARNING: EVP_DecodeBlock's return value does not take padding into +// account. It also strips leading whitespace and trailing +// whitespace and minuses. +OPENSSL_EXPORT int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, + size_t src_len); + + +struct evp_encode_ctx_st { + // data_used indicates the number of bytes of |data| that are valid. When + // encoding, |data| will be filled and encoded as a lump. When decoding, only + // the first four bytes of |data| will be used. + unsigned data_used; + uint8_t data[48]; + + // eof_seen indicates that the end of the base64 data has been seen when + // decoding. Only whitespace can follow. + char eof_seen; + + // error_encountered indicates that invalid base64 data was found. This will + // cause all future calls to fail. + char error_encountered; +}; + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_BASE64_H diff --git a/lib/boringssl/include/openssl/bio.h b/lib/boringssl/include/openssl/bio.h new file mode 100644 index 00000000..707a4b15 --- /dev/null +++ b/lib/boringssl/include/openssl/bio.h @@ -0,0 +1,954 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BIO_H +#define OPENSSL_HEADER_BIO_H + +#include + +#include // For FILE + +#include +#include // for ERR_print_errors_fp +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// BIO abstracts over a file-descriptor like interface. + + +// Allocation and freeing. + +DEFINE_STACK_OF(BIO) + +// BIO_new creates a new BIO with the given method and a reference count of one. +// It returns the fresh |BIO|, or NULL on error. +OPENSSL_EXPORT BIO *BIO_new(const BIO_METHOD *method); + +// BIO_free decrements the reference count of |bio|. If the reference count +// drops to zero, it calls the destroy callback, if present, on the method and +// frees |bio| itself. It then repeats that for the next BIO in the chain, if +// any. +// +// It returns one on success or zero otherwise. +OPENSSL_EXPORT int BIO_free(BIO *bio); + +// BIO_vfree performs the same actions as |BIO_free|, but has a void return +// value. This is provided for API-compat. +// +// TODO(fork): remove. +OPENSSL_EXPORT void BIO_vfree(BIO *bio); + +// BIO_up_ref increments the reference count of |bio| and returns one. +OPENSSL_EXPORT int BIO_up_ref(BIO *bio); + + +// Basic I/O. + +// BIO_read attempts to read |len| bytes into |data|. It returns the number of +// bytes read, zero on EOF, or a negative number on error. +OPENSSL_EXPORT int BIO_read(BIO *bio, void *data, int len); + +// BIO_gets reads a line from |bio| and writes at most |size| bytes into |buf|. +// It returns the number of bytes read or a negative number on error. This +// function's output always includes a trailing NUL byte, so it will read at +// most |size - 1| bytes. +// +// If the function read a complete line, the output will include the newline +// character, '\n'. If no newline was found before |size - 1| bytes or EOF, it +// outputs the bytes which were available. +OPENSSL_EXPORT int BIO_gets(BIO *bio, char *buf, int size); + +// BIO_write writes |len| bytes from |data| to |bio|. It returns the number of +// bytes written or a negative number on error. +OPENSSL_EXPORT int BIO_write(BIO *bio, const void *data, int len); + +// BIO_write_all writes |len| bytes from |data| to |bio|, looping as necessary. +// It returns one if all bytes were successfully written and zero on error. +OPENSSL_EXPORT int BIO_write_all(BIO *bio, const void *data, size_t len); + +// BIO_puts writes a NUL terminated string from |buf| to |bio|. It returns the +// number of bytes written or a negative number on error. +OPENSSL_EXPORT int BIO_puts(BIO *bio, const char *buf); + +// BIO_flush flushes any buffered output. It returns one on success and zero +// otherwise. +OPENSSL_EXPORT int BIO_flush(BIO *bio); + + +// Low-level control functions. +// +// These are generic functions for sending control requests to a BIO. In +// general one should use the wrapper functions like |BIO_get_close|. + +// BIO_ctrl sends the control request |cmd| to |bio|. The |cmd| argument should +// be one of the |BIO_C_*| values. +OPENSSL_EXPORT long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg); + +// BIO_ptr_ctrl acts like |BIO_ctrl| but passes the address of a |void*| +// pointer as |parg| and returns the value that is written to it, or NULL if +// the control request returns <= 0. +OPENSSL_EXPORT char *BIO_ptr_ctrl(BIO *bp, int cmd, long larg); + +// BIO_int_ctrl acts like |BIO_ctrl| but passes the address of a copy of |iarg| +// as |parg|. +OPENSSL_EXPORT long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); + +// BIO_reset resets |bio| to its initial state, the precise meaning of which +// depends on the concrete type of |bio|. It returns one on success and zero +// otherwise. +OPENSSL_EXPORT int BIO_reset(BIO *bio); + +// BIO_eof returns non-zero when |bio| has reached end-of-file. The precise +// meaning of which depends on the concrete type of |bio|. Note that in the +// case of BIO_pair this always returns non-zero. +OPENSSL_EXPORT int BIO_eof(BIO *bio); + +// BIO_set_flags ORs |flags| with |bio->flags|. +OPENSSL_EXPORT void BIO_set_flags(BIO *bio, int flags); + +// BIO_test_flags returns |bio->flags| AND |flags|. +OPENSSL_EXPORT int BIO_test_flags(const BIO *bio, int flags); + +// BIO_should_read returns non-zero if |bio| encountered a temporary error +// while reading (i.e. EAGAIN), indicating that the caller should retry the +// read. +OPENSSL_EXPORT int BIO_should_read(const BIO *bio); + +// BIO_should_write returns non-zero if |bio| encountered a temporary error +// while writing (i.e. EAGAIN), indicating that the caller should retry the +// write. +OPENSSL_EXPORT int BIO_should_write(const BIO *bio); + +// BIO_should_retry returns non-zero if the reason that caused a failed I/O +// operation is temporary and thus the operation should be retried. Otherwise, +// it was a permanent error and it returns zero. +OPENSSL_EXPORT int BIO_should_retry(const BIO *bio); + +// BIO_should_io_special returns non-zero if |bio| encountered a temporary +// error while performing a special I/O operation, indicating that the caller +// should retry. The operation that caused the error is returned by +// |BIO_get_retry_reason|. +OPENSSL_EXPORT int BIO_should_io_special(const BIO *bio); + +// BIO_RR_CONNECT indicates that a connect would have blocked +#define BIO_RR_CONNECT 0x02 + +// BIO_RR_ACCEPT indicates that an accept would have blocked +#define BIO_RR_ACCEPT 0x03 + +// BIO_get_retry_reason returns the special I/O operation that needs to be +// retried. The return value is one of the |BIO_RR_*| values. +OPENSSL_EXPORT int BIO_get_retry_reason(const BIO *bio); + +// BIO_set_retry_reason sets the special I/O operation that needs to be retried +// to |reason|, which should be one of the |BIO_RR_*| values. +OPENSSL_EXPORT void BIO_set_retry_reason(BIO *bio, int reason); + +// BIO_clear_flags ANDs |bio->flags| with the bitwise-complement of |flags|. +OPENSSL_EXPORT void BIO_clear_flags(BIO *bio, int flags); + +// BIO_set_retry_read sets the |BIO_FLAGS_READ| and |BIO_FLAGS_SHOULD_RETRY| +// flags on |bio|. +OPENSSL_EXPORT void BIO_set_retry_read(BIO *bio); + +// BIO_set_retry_write sets the |BIO_FLAGS_WRITE| and |BIO_FLAGS_SHOULD_RETRY| +// flags on |bio|. +OPENSSL_EXPORT void BIO_set_retry_write(BIO *bio); + +// BIO_get_retry_flags gets the |BIO_FLAGS_READ|, |BIO_FLAGS_WRITE|, +// |BIO_FLAGS_IO_SPECIAL| and |BIO_FLAGS_SHOULD_RETRY| flags from |bio|. +OPENSSL_EXPORT int BIO_get_retry_flags(BIO *bio); + +// BIO_clear_retry_flags clears the |BIO_FLAGS_READ|, |BIO_FLAGS_WRITE|, +// |BIO_FLAGS_IO_SPECIAL| and |BIO_FLAGS_SHOULD_RETRY| flags from |bio|. +OPENSSL_EXPORT void BIO_clear_retry_flags(BIO *bio); + +// BIO_method_type returns the type of |bio|, which is one of the |BIO_TYPE_*| +// values. +OPENSSL_EXPORT int BIO_method_type(const BIO *bio); + +// These are passed to the BIO callback +#define BIO_CB_FREE 0x01 +#define BIO_CB_READ 0x02 +#define BIO_CB_WRITE 0x03 +#define BIO_CB_PUTS 0x04 +#define BIO_CB_GETS 0x05 +#define BIO_CB_CTRL 0x06 + +// The callback is called before and after the underling operation, +// The BIO_CB_RETURN flag indicates if it is after the call +#define BIO_CB_RETURN 0x80 + +// bio_info_cb is the type of a callback function that can be called for most +// BIO operations. The |event| argument is one of |BIO_CB_*| and can be ORed +// with |BIO_CB_RETURN| if the callback is being made after the operation in +// question. In that case, |return_value| will contain the return value from +// the operation. +typedef long (*bio_info_cb)(BIO *bio, int event, const char *parg, int cmd, + long larg, long return_value); + +// BIO_callback_ctrl allows the callback function to be manipulated. The |cmd| +// arg will generally be |BIO_CTRL_SET_CALLBACK| but arbitrary command values +// can be interpreted by the |BIO|. +OPENSSL_EXPORT long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp); + +// BIO_pending returns the number of bytes pending to be read. +OPENSSL_EXPORT size_t BIO_pending(const BIO *bio); + +// BIO_ctrl_pending calls |BIO_pending| and exists only for compatibility with +// OpenSSL. +OPENSSL_EXPORT size_t BIO_ctrl_pending(const BIO *bio); + +// BIO_wpending returns the number of bytes pending to be written. +OPENSSL_EXPORT size_t BIO_wpending(const BIO *bio); + +// BIO_set_close sets the close flag for |bio|. The meaning of which depends on +// the type of |bio| but, for example, a memory BIO interprets the close flag +// as meaning that it owns its buffer. It returns one on success and zero +// otherwise. +OPENSSL_EXPORT int BIO_set_close(BIO *bio, int close_flag); + +// BIO_number_read returns the number of bytes that have been read from +// |bio|. +OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio); + +// BIO_number_written returns the number of bytes that have been written to +// |bio|. +OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio); + + +// Managing chains of BIOs. +// +// BIOs can be put into chains where the output of one is used as the input of +// the next etc. The most common case is a buffering BIO, which accepts and +// buffers writes until flushed into the next BIO in the chain. + +// BIO_push adds |appended_bio| to the end of the chain with |bio| at the head. +// It returns |bio|. Note that |appended_bio| may be the head of a chain itself +// and thus this function can be used to join two chains. +// +// BIO_push takes ownership of the caller's reference to |appended_bio|. +OPENSSL_EXPORT BIO *BIO_push(BIO *bio, BIO *appended_bio); + +// BIO_pop removes |bio| from the head of a chain and returns the next BIO in +// the chain, or NULL if there is no next BIO. +// +// The caller takes ownership of the chain's reference to |bio|. +OPENSSL_EXPORT BIO *BIO_pop(BIO *bio); + +// BIO_next returns the next BIO in the chain after |bio|, or NULL if there is +// no such BIO. +OPENSSL_EXPORT BIO *BIO_next(BIO *bio); + +// BIO_free_all calls |BIO_free|. +// +// TODO(fork): update callers and remove. +OPENSSL_EXPORT void BIO_free_all(BIO *bio); + +// BIO_find_type walks a chain of BIOs and returns the first that matches +// |type|, which is one of the |BIO_TYPE_*| values. +OPENSSL_EXPORT BIO *BIO_find_type(BIO *bio, int type); + +// BIO_copy_next_retry sets the retry flags and |retry_reason| of |bio| from +// the next BIO in the chain. +OPENSSL_EXPORT void BIO_copy_next_retry(BIO *bio); + + +// Printf functions. + +// BIO_printf behaves like |printf| but outputs to |bio| rather than a |FILE|. +// It returns the number of bytes written or a negative number on error. +OPENSSL_EXPORT int BIO_printf(BIO *bio, const char *format, ...) + OPENSSL_PRINTF_FORMAT_FUNC(2, 3); + + +// Utility functions. + +// BIO_indent prints min(|indent|, |max_indent|) spaces. It returns one on +// success and zero otherwise. +OPENSSL_EXPORT int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent); + +// BIO_hexdump writes a hex dump of |data| to |bio|. Each line will be indented +// by |indent| spaces. It returns one on success and zero otherwise. +OPENSSL_EXPORT int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, + unsigned indent); + +// ERR_print_errors prints the current contents of the error stack to |bio| +// using human readable strings where possible. +OPENSSL_EXPORT void ERR_print_errors(BIO *bio); + +// BIO_read_asn1 reads a single ASN.1 object from |bio|. If successful it sets +// |*out| to be an allocated buffer (that should be freed with |OPENSSL_free|), +// |*out_size| to the length, in bytes, of that buffer and returns one. +// Otherwise it returns zero. +// +// If the length of the object is greater than |max_len| or 2^32 then the +// function will fail. Long-form tags are not supported. If the length of the +// object is indefinite the full contents of |bio| are read, unless it would be +// greater than |max_len|, in which case the function fails. +// +// If the function fails then some unknown amount of data may have been read +// from |bio|. +OPENSSL_EXPORT int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, + size_t max_len); + + +// Memory BIOs. +// +// Memory BIOs can be used as a read-only source (with |BIO_new_mem_buf|) or a +// writable sink (with |BIO_new|, |BIO_s_mem| and |BIO_mem_contents|). Data +// written to a writable, memory BIO can be recalled by reading from it. +// +// Calling |BIO_reset| on a read-only BIO resets it to the original contents. +// On a writable BIO, it clears any data. +// +// If the close flag is set to |BIO_NOCLOSE| (not the default) then the +// underlying |BUF_MEM| will not be freed when the |BIO| is freed. +// +// Memory BIOs support |BIO_gets| and |BIO_puts|. +// +// |BIO_ctrl_pending| returns the number of bytes currently stored. + +// BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close +// flag" is passed to a BIO function. +#define BIO_NOCLOSE 0 +#define BIO_CLOSE 1 + +// BIO_s_mem returns a |BIO_METHOD| that uses a in-memory buffer. +OPENSSL_EXPORT const BIO_METHOD *BIO_s_mem(void); + +// BIO_new_mem_buf creates read-only BIO that reads from |len| bytes at |buf|. +// It returns the BIO or NULL on error. This function does not copy or take +// ownership of |buf|. The caller must ensure the memory pointed to by |buf| +// outlives the |BIO|. +// +// If |len| is negative, then |buf| is treated as a NUL-terminated string, but +// don't depend on this in new code. +OPENSSL_EXPORT BIO *BIO_new_mem_buf(const void *buf, ossl_ssize_t len); + +// BIO_mem_contents sets |*out_contents| to point to the current contents of +// |bio| and |*out_len| to contain the length of that data. It returns one on +// success and zero otherwise. +OPENSSL_EXPORT int BIO_mem_contents(const BIO *bio, + const uint8_t **out_contents, + size_t *out_len); + +// BIO_get_mem_data sets |*contents| to point to the current contents of |bio| +// and returns the length of the data. +// +// WARNING: don't use this, use |BIO_mem_contents|. A return value of zero from +// this function can mean either that it failed or that the memory buffer is +// empty. +OPENSSL_EXPORT long BIO_get_mem_data(BIO *bio, char **contents); + +// BIO_get_mem_ptr sets |*out| to a BUF_MEM containing the current contents of +// |bio|. It returns one on success or zero on error. +OPENSSL_EXPORT int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out); + +// BIO_set_mem_buf sets |b| as the contents of |bio|. If |take_ownership| is +// non-zero, then |b| will be freed when |bio| is closed. Returns one on +// success or zero otherwise. +OPENSSL_EXPORT int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership); + +// BIO_set_mem_eof_return sets the value that will be returned from reading +// |bio| when empty. If |eof_value| is zero then an empty memory BIO will +// return EOF (that is it will return zero and |BIO_should_retry| will be +// false). If |eof_value| is non zero then it will return |eof_value| when it +// is empty and it will set the read retry flag (that is |BIO_read_retry| is +// true). To avoid ambiguity with a normal positive return value, |eof_value| +// should be set to a negative value, typically -1. +// +// For a read-only BIO, the default is zero (EOF). For a writable BIO, the +// default is -1 so that additional data can be written once exhausted. +OPENSSL_EXPORT int BIO_set_mem_eof_return(BIO *bio, int eof_value); + + +// File descriptor BIOs. +// +// File descriptor BIOs are wrappers around the system's |read| and |write| +// functions. If the close flag is set then then |close| is called on the +// underlying file descriptor when the BIO is freed. +// +// |BIO_reset| attempts to seek the file pointer to the start of file using +// |lseek|. + +// BIO_s_fd returns a |BIO_METHOD| for file descriptor fds. +OPENSSL_EXPORT const BIO_METHOD *BIO_s_fd(void); + +// BIO_new_fd creates a new file descriptor BIO wrapping |fd|. If |close_flag| +// is non-zero, then |fd| will be closed when the BIO is. +OPENSSL_EXPORT BIO *BIO_new_fd(int fd, int close_flag); + +// BIO_set_fd sets the file descriptor of |bio| to |fd|. If |close_flag| is +// non-zero then |fd| will be closed when |bio| is. It returns one on success +// or zero on error. +// +// This function may also be used with socket BIOs (see |BIO_s_socket| and +// |BIO_new_socket|). +OPENSSL_EXPORT int BIO_set_fd(BIO *bio, int fd, int close_flag); + +// BIO_get_fd returns the file descriptor currently in use by |bio| or -1 if +// |bio| does not wrap a file descriptor. If there is a file descriptor and +// |out_fd| is not NULL, it also sets |*out_fd| to the file descriptor. +// +// This function may also be used with socket BIOs (see |BIO_s_socket| and +// |BIO_new_socket|). +OPENSSL_EXPORT int BIO_get_fd(BIO *bio, int *out_fd); + + +// File BIOs. +// +// File BIOs are wrappers around a C |FILE| object. +// +// |BIO_flush| on a file BIO calls |fflush| on the wrapped stream. +// +// |BIO_reset| attempts to seek the file pointer to the start of file using +// |fseek|. +// +// Setting the close flag causes |fclose| to be called on the stream when the +// BIO is freed. + +// BIO_s_file returns a BIO_METHOD that wraps a |FILE|. +OPENSSL_EXPORT const BIO_METHOD *BIO_s_file(void); + +// BIO_new_file creates a file BIO by opening |filename| with the given mode. +// See the |fopen| manual page for details of the mode argument. +OPENSSL_EXPORT BIO *BIO_new_file(const char *filename, const char *mode); + +// BIO_new_fp creates a new file BIO that wraps the given |FILE|. If +// |close_flag| is |BIO_CLOSE|, then |fclose| will be called on |stream| when +// the BIO is closed. +OPENSSL_EXPORT BIO *BIO_new_fp(FILE *stream, int close_flag); + +// BIO_get_fp sets |*out_file| to the current |FILE| for |bio|. It returns one +// on success and zero otherwise. +OPENSSL_EXPORT int BIO_get_fp(BIO *bio, FILE **out_file); + +// BIO_set_fp sets the |FILE| for |bio|. If |close_flag| is |BIO_CLOSE| then +// |fclose| will be called on |file| when |bio| is closed. It returns one on +// success and zero otherwise. +OPENSSL_EXPORT int BIO_set_fp(BIO *bio, FILE *file, int close_flag); + +// BIO_read_filename opens |filename| for reading and sets the result as the +// |FILE| for |bio|. It returns one on success and zero otherwise. The |FILE| +// will be closed when |bio| is freed. +OPENSSL_EXPORT int BIO_read_filename(BIO *bio, const char *filename); + +// BIO_write_filename opens |filename| for writing and sets the result as the +// |FILE| for |bio|. It returns one on success and zero otherwise. The |FILE| +// will be closed when |bio| is freed. +OPENSSL_EXPORT int BIO_write_filename(BIO *bio, const char *filename); + +// BIO_append_filename opens |filename| for appending and sets the result as +// the |FILE| for |bio|. It returns one on success and zero otherwise. The +// |FILE| will be closed when |bio| is freed. +OPENSSL_EXPORT int BIO_append_filename(BIO *bio, const char *filename); + +// BIO_rw_filename opens |filename| for reading and writing and sets the result +// as the |FILE| for |bio|. It returns one on success and zero otherwise. The +// |FILE| will be closed when |bio| is freed. +OPENSSL_EXPORT int BIO_rw_filename(BIO *bio, const char *filename); + +// BIO_tell returns the file offset of |bio|, or a negative number on error or +// if |bio| does not support the operation. +// +// TODO(https://crbug.com/boringssl/465): On platforms where |long| is 32-bit, +// this function cannot report 64-bit offsets. +OPENSSL_EXPORT long BIO_tell(BIO *bio); + +// BIO_seek sets the file offset of |bio| to |offset|. It returns a non-negative +// number on success and a negative number on error. If |bio| is a file +// descriptor |BIO|, it returns the resulting file offset on success. If |bio| +// is a file |BIO|, it returns zero on success. +// +// WARNING: This function's return value conventions differs from most functions +// in this library. +// +// TODO(https://crbug.com/boringssl/465): On platforms where |long| is 32-bit, +// this function cannot handle 64-bit offsets. +OPENSSL_EXPORT long BIO_seek(BIO *bio, long offset); + + +// Socket BIOs. +// +// Socket BIOs behave like file descriptor BIOs but, on Windows systems, wrap +// the system's |recv| and |send| functions instead of |read| and |write|. On +// Windows, file descriptors are provided by C runtime and are not +// interchangeable with sockets. +// +// Socket BIOs may be used with |BIO_set_fd| and |BIO_get_fd|. +// +// TODO(davidben): Add separate APIs and fix the internals to use |SOCKET|s +// around rather than rely on int casts. + +OPENSSL_EXPORT const BIO_METHOD *BIO_s_socket(void); + +// BIO_new_socket allocates and initialises a fresh BIO which will read and +// write to the socket |fd|. If |close_flag| is |BIO_CLOSE| then closing the +// BIO will close |fd|. It returns the fresh |BIO| or NULL on error. +OPENSSL_EXPORT BIO *BIO_new_socket(int fd, int close_flag); + + +// Connect BIOs. +// +// A connection BIO creates a network connection and transfers data over the +// resulting socket. + +OPENSSL_EXPORT const BIO_METHOD *BIO_s_connect(void); + +// BIO_new_connect returns a BIO that connects to the given hostname and port. +// The |host_and_optional_port| argument should be of the form +// "www.example.com" or "www.example.com:443". If the port is omitted, it must +// be provided with |BIO_set_conn_port|. +// +// It returns the new BIO on success, or NULL on error. +OPENSSL_EXPORT BIO *BIO_new_connect(const char *host_and_optional_port); + +// BIO_set_conn_hostname sets |host_and_optional_port| as the hostname and +// optional port that |bio| will connect to. If the port is omitted, it must be +// provided with |BIO_set_conn_port|. +// +// It returns one on success and zero otherwise. +OPENSSL_EXPORT int BIO_set_conn_hostname(BIO *bio, + const char *host_and_optional_port); + +// BIO_set_conn_port sets |port_str| as the port or service name that |bio| +// will connect to. It returns one on success and zero otherwise. +OPENSSL_EXPORT int BIO_set_conn_port(BIO *bio, const char *port_str); + +// BIO_set_conn_int_port sets |*port| as the port that |bio| will connect to. +// It returns one on success and zero otherwise. +OPENSSL_EXPORT int BIO_set_conn_int_port(BIO *bio, const int *port); + +// BIO_set_nbio sets whether |bio| will use non-blocking I/O operations. It +// returns one on success and zero otherwise. +OPENSSL_EXPORT int BIO_set_nbio(BIO *bio, int on); + +// BIO_do_connect connects |bio| if it has not been connected yet. It returns +// one on success and <= 0 otherwise. +OPENSSL_EXPORT int BIO_do_connect(BIO *bio); + + +// Datagram BIOs. +// +// TODO(fork): not implemented. + +#define BIO_CTRL_DGRAM_QUERY_MTU 40 // as kernel for current MTU + +#define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for MTU. want to use + this if asking the kernel fails */ + +#define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU was exceed in + the previous write operation. */ + +// BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT is unsupported as it is unused by consumers +// and depends on |timeval|, which is not 2038-clean on all platforms. + +#define BIO_CTRL_DGRAM_GET_PEER 46 + +#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 + + +// BIO Pairs. +// +// BIO pairs provide a "loopback" like system: a pair of BIOs where data +// written to one can be read from the other and vice versa. + +// BIO_new_bio_pair sets |*out1| and |*out2| to two freshly created BIOs where +// data written to one can be read from the other and vice versa. The +// |writebuf1| argument gives the size of the buffer used in |*out1| and +// |writebuf2| for |*out2|. It returns one on success and zero on error. +OPENSSL_EXPORT int BIO_new_bio_pair(BIO **out1, size_t writebuf1, BIO **out2, + size_t writebuf2); + +// BIO_ctrl_get_read_request returns the number of bytes that the other side of +// |bio| tried (unsuccessfully) to read. +OPENSSL_EXPORT size_t BIO_ctrl_get_read_request(BIO *bio); + +// BIO_ctrl_get_write_guarantee returns the number of bytes that |bio| (which +// must have been returned by |BIO_new_bio_pair|) will accept on the next +// |BIO_write| call. +OPENSSL_EXPORT size_t BIO_ctrl_get_write_guarantee(BIO *bio); + +// BIO_shutdown_wr marks |bio| as closed, from the point of view of the other +// side of the pair. Future |BIO_write| calls on |bio| will fail. It returns +// one on success and zero otherwise. +OPENSSL_EXPORT int BIO_shutdown_wr(BIO *bio); + + +// Custom BIOs. +// +// Consumers can create custom |BIO|s by filling in a |BIO_METHOD| and using +// low-level control functions to set state. + +// BIO_get_new_index returns a new "type" value for a custom |BIO|. +OPENSSL_EXPORT int BIO_get_new_index(void); + +// BIO_meth_new returns a newly-allocated |BIO_METHOD| or NULL on allocation +// error. The |type| specifies the type that will be returned by +// |BIO_method_type|. If this is unnecessary, this value may be zero. The |name| +// parameter is vestigial and may be NULL. +// +// Use the |BIO_meth_set_*| functions below to initialize the |BIO_METHOD|. The +// function implementations may use |BIO_set_data| and |BIO_get_data| to add +// method-specific state to associated |BIO|s. Additionally, |BIO_set_init| must +// be called after an associated |BIO| is fully initialized. State set via +// |BIO_set_data| may be released by configuring a destructor with +// |BIO_meth_set_destroy|. +OPENSSL_EXPORT BIO_METHOD *BIO_meth_new(int type, const char *name); + +// BIO_meth_free releases memory associated with |method|. +OPENSSL_EXPORT void BIO_meth_free(BIO_METHOD *method); + +// BIO_meth_set_create sets a function to be called on |BIO_new| for |method| +// and returns one. The function should return one on success and zero on +// error. +OPENSSL_EXPORT int BIO_meth_set_create(BIO_METHOD *method, + int (*create)(BIO *)); + +// BIO_meth_set_destroy sets a function to release data associated with a |BIO| +// and returns one. The function's return value is ignored. +OPENSSL_EXPORT int BIO_meth_set_destroy(BIO_METHOD *method, + int (*destroy)(BIO *)); + +// BIO_meth_set_write sets the implementation of |BIO_write| for |method| and +// returns one. |BIO_METHOD|s which implement |BIO_write| should also implement +// |BIO_CTRL_FLUSH|. (See |BIO_meth_set_ctrl|.) +OPENSSL_EXPORT int BIO_meth_set_write(BIO_METHOD *method, + int (*write)(BIO *, const char *, int)); + +// BIO_meth_set_read sets the implementation of |BIO_read| for |method| and +// returns one. +OPENSSL_EXPORT int BIO_meth_set_read(BIO_METHOD *method, + int (*read)(BIO *, char *, int)); + +// BIO_meth_set_gets sets the implementation of |BIO_gets| for |method| and +// returns one. +OPENSSL_EXPORT int BIO_meth_set_gets(BIO_METHOD *method, + int (*gets)(BIO *, char *, int)); + +// BIO_meth_set_ctrl sets the implementation of |BIO_ctrl| for |method| and +// returns one. +OPENSSL_EXPORT int BIO_meth_set_ctrl(BIO_METHOD *method, + long (*ctrl)(BIO *, int, long, void *)); + +// BIO_set_data sets custom data on |bio|. It may be retried with +// |BIO_get_data|. +OPENSSL_EXPORT void BIO_set_data(BIO *bio, void *ptr); + +// BIO_get_data returns custom data on |bio| set by |BIO_get_data|. +OPENSSL_EXPORT void *BIO_get_data(BIO *bio); + +// BIO_set_init sets whether |bio| has been fully initialized. Until fully +// initialized, |BIO_read| and |BIO_write| will fail. +OPENSSL_EXPORT void BIO_set_init(BIO *bio, int init); + +// BIO_get_init returns whether |bio| has been fully initialized. +OPENSSL_EXPORT int BIO_get_init(BIO *bio); + +// These are values of the |cmd| argument to |BIO_ctrl|. + +// BIO_CTRL_RESET implements |BIO_reset|. The arguments are unused. +#define BIO_CTRL_RESET 1 + +// BIO_CTRL_EOF implements |BIO_eof|. The arguments are unused. +#define BIO_CTRL_EOF 2 + +// BIO_CTRL_INFO is a legacy command that returns information specific to the +// type of |BIO|. It is not safe to call generically and should not be +// implemented in new |BIO| types. +#define BIO_CTRL_INFO 3 + +// BIO_CTRL_GET_CLOSE returns the close flag set by |BIO_CTRL_SET_CLOSE|. The +// arguments are unused. +#define BIO_CTRL_GET_CLOSE 8 + +// BIO_CTRL_SET_CLOSE implements |BIO_set_close|. The |larg| argument is the +// close flag. +#define BIO_CTRL_SET_CLOSE 9 + +// BIO_CTRL_PENDING implements |BIO_pending|. The arguments are unused. +#define BIO_CTRL_PENDING 10 + +// BIO_CTRL_FLUSH implements |BIO_flush|. The arguments are unused. +#define BIO_CTRL_FLUSH 11 + +// BIO_CTRL_WPENDING implements |BIO_wpending|. The arguments are unused. +#define BIO_CTRL_WPENDING 13 + +// BIO_CTRL_SET_CALLBACK sets an informational callback of type +// int cb(BIO *bio, int state, int ret) +#define BIO_CTRL_SET_CALLBACK 14 + +// BIO_CTRL_GET_CALLBACK returns the callback set by |BIO_CTRL_SET_CALLBACK|. +#define BIO_CTRL_GET_CALLBACK 15 + +// The following are never used, but are defined to aid porting existing code. +#define BIO_CTRL_SET 4 +#define BIO_CTRL_GET 5 +#define BIO_CTRL_PUSH 6 +#define BIO_CTRL_POP 7 +#define BIO_CTRL_DUP 12 +#define BIO_CTRL_SET_FILENAME 30 + + +// Deprecated functions. + +// BIO_f_base64 returns a filter |BIO| that base64-encodes data written into +// it, and decodes data read from it. |BIO_gets| is not supported. Call +// |BIO_flush| when done writing, to signal that no more data are to be +// encoded. The flag |BIO_FLAGS_BASE64_NO_NL| may be set to encode all the data +// on one line. +// +// Use |EVP_EncodeBlock| and |EVP_DecodeBase64| instead. +OPENSSL_EXPORT const BIO_METHOD *BIO_f_base64(void); + +OPENSSL_EXPORT void BIO_set_retry_special(BIO *bio); + +// BIO_set_write_buffer_size returns zero. +OPENSSL_EXPORT int BIO_set_write_buffer_size(BIO *bio, int buffer_size); + +// BIO_set_shutdown sets a method-specific "shutdown" bit on |bio|. +OPENSSL_EXPORT void BIO_set_shutdown(BIO *bio, int shutdown); + +// BIO_get_shutdown returns the method-specific "shutdown" bit. +OPENSSL_EXPORT int BIO_get_shutdown(BIO *bio); + +// BIO_meth_set_puts returns one. |BIO_puts| is implemented with |BIO_write| in +// BoringSSL. +OPENSSL_EXPORT int BIO_meth_set_puts(BIO_METHOD *method, + int (*puts)(BIO *, const char *)); + + +// Private functions + +#define BIO_FLAGS_READ 0x01 +#define BIO_FLAGS_WRITE 0x02 +#define BIO_FLAGS_IO_SPECIAL 0x04 +#define BIO_FLAGS_RWS (BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL) +#define BIO_FLAGS_SHOULD_RETRY 0x08 +#define BIO_FLAGS_BASE64_NO_NL 0x100 +// BIO_FLAGS_MEM_RDONLY is used with memory BIOs. It means we shouldn't free up +// or change the data in any way. +#define BIO_FLAGS_MEM_RDONLY 0x200 + +// These are the 'types' of BIOs +#define BIO_TYPE_NONE 0 +#define BIO_TYPE_MEM (1 | 0x0400) +#define BIO_TYPE_FILE (2 | 0x0400) +#define BIO_TYPE_FD (4 | 0x0400 | 0x0100) +#define BIO_TYPE_SOCKET (5 | 0x0400 | 0x0100) +#define BIO_TYPE_NULL (6 | 0x0400) +#define BIO_TYPE_SSL (7 | 0x0200) +#define BIO_TYPE_MD (8 | 0x0200) // passive filter +#define BIO_TYPE_BUFFER (9 | 0x0200) // filter +#define BIO_TYPE_CIPHER (10 | 0x0200) // filter +#define BIO_TYPE_BASE64 (11 | 0x0200) // filter +#define BIO_TYPE_CONNECT (12 | 0x0400 | 0x0100) // socket - connect +#define BIO_TYPE_ACCEPT (13 | 0x0400 | 0x0100) // socket for accept +#define BIO_TYPE_PROXY_CLIENT (14 | 0x0200) // client proxy BIO +#define BIO_TYPE_PROXY_SERVER (15 | 0x0200) // server proxy BIO +#define BIO_TYPE_NBIO_TEST (16 | 0x0200) // server proxy BIO +#define BIO_TYPE_NULL_FILTER (17 | 0x0200) +#define BIO_TYPE_BER (18 | 0x0200) // BER -> bin filter +#define BIO_TYPE_BIO (19 | 0x0400) // (half a) BIO pair +#define BIO_TYPE_LINEBUFFER (20 | 0x0200) // filter +#define BIO_TYPE_DGRAM (21 | 0x0400 | 0x0100) +#define BIO_TYPE_ASN1 (22 | 0x0200) // filter +#define BIO_TYPE_COMP (23 | 0x0200) // filter + +// BIO_TYPE_DESCRIPTOR denotes that the |BIO| responds to the |BIO_C_SET_FD| +// (|BIO_set_fd|) and |BIO_C_GET_FD| (|BIO_get_fd|) control hooks. +#define BIO_TYPE_DESCRIPTOR 0x0100 // socket, fd, connect or accept +#define BIO_TYPE_FILTER 0x0200 +#define BIO_TYPE_SOURCE_SINK 0x0400 + +// BIO_TYPE_START is the first user-allocated |BIO| type. No pre-defined type, +// flag bits aside, may exceed this value. +#define BIO_TYPE_START 128 + +struct bio_method_st { + int type; + const char *name; + int (*bwrite)(BIO *, const char *, int); + int (*bread)(BIO *, char *, int); + // TODO(fork): remove bputs. + int (*bputs)(BIO *, const char *); + int (*bgets)(BIO *, char *, int); + long (*ctrl)(BIO *, int, long, void *); + int (*create)(BIO *); + int (*destroy)(BIO *); + long (*callback_ctrl)(BIO *, int, bio_info_cb); +}; + +struct bio_st { + const BIO_METHOD *method; + + // init is non-zero if this |BIO| has been initialised. + int init; + // shutdown is often used by specific |BIO_METHOD|s to determine whether + // they own some underlying resource. This flag can often by controlled by + // |BIO_set_close|. For example, whether an fd BIO closes the underlying fd + // when it, itself, is closed. + int shutdown; + int flags; + int retry_reason; + // num is a BIO-specific value. For example, in fd BIOs it's used to store a + // file descriptor. + int num; + CRYPTO_refcount_t references; + void *ptr; + // next_bio points to the next |BIO| in a chain. This |BIO| owns a reference + // to |next_bio|. + BIO *next_bio; // used by filter BIOs + size_t num_read, num_write; +}; + +#define BIO_C_SET_CONNECT 100 +#define BIO_C_DO_STATE_MACHINE 101 +#define BIO_C_SET_NBIO 102 +#define BIO_C_SET_PROXY_PARAM 103 +#define BIO_C_SET_FD 104 +#define BIO_C_GET_FD 105 +#define BIO_C_SET_FILE_PTR 106 +#define BIO_C_GET_FILE_PTR 107 +#define BIO_C_SET_FILENAME 108 +#define BIO_C_SET_SSL 109 +#define BIO_C_SET_MD 111 +#define BIO_C_GET_MD 112 +#define BIO_C_GET_CIPHER_STATUS 113 +#define BIO_C_SET_BUF_MEM 114 +#define BIO_C_GET_BUF_MEM_PTR 115 +#define BIO_C_GET_BUFF_NUM_LINES 116 +#define BIO_C_SET_BUFF_SIZE 117 +#define BIO_C_SET_ACCEPT 118 +#define BIO_C_SSL_MODE 119 +#define BIO_C_GET_MD_CTX 120 +#define BIO_C_GET_PROXY_PARAM 121 +#define BIO_C_SET_BUFF_READ_DATA 122 // data to read first +#define BIO_C_GET_ACCEPT 124 +#define BIO_C_FILE_SEEK 128 +#define BIO_C_GET_CIPHER_CTX 129 +#define BIO_C_SET_BUF_MEM_EOF_RETURN 130 // return end of input value +#define BIO_C_SET_BIND_MODE 131 +#define BIO_C_GET_BIND_MODE 132 +#define BIO_C_FILE_TELL 133 +#define BIO_C_GET_SOCKS 134 +#define BIO_C_SET_SOCKS 135 + +#define BIO_C_SET_WRITE_BUF_SIZE 136 // for BIO_s_bio +#define BIO_C_GET_WRITE_BUF_SIZE 137 +#define BIO_C_GET_WRITE_GUARANTEE 140 +#define BIO_C_GET_READ_REQUEST 141 +#define BIO_C_SHUTDOWN_WR 142 +#define BIO_C_NREAD0 143 +#define BIO_C_NREAD 144 +#define BIO_C_NWRITE0 145 +#define BIO_C_NWRITE 146 +#define BIO_C_RESET_READ_REQUEST 147 +#define BIO_C_SET_MD_CTX 148 + +#define BIO_C_SET_PREFIX 149 +#define BIO_C_GET_PREFIX 150 +#define BIO_C_SET_SUFFIX 151 +#define BIO_C_GET_SUFFIX 152 + +#define BIO_C_SET_EX_ARG 153 +#define BIO_C_GET_EX_ARG 154 + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(BIO, BIO_free) +BORINGSSL_MAKE_UP_REF(BIO, BIO_up_ref) +BORINGSSL_MAKE_DELETER(BIO_METHOD, BIO_meth_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define BIO_R_BAD_FOPEN_MODE 100 +#define BIO_R_BROKEN_PIPE 101 +#define BIO_R_CONNECT_ERROR 102 +#define BIO_R_ERROR_SETTING_NBIO 103 +#define BIO_R_INVALID_ARGUMENT 104 +#define BIO_R_IN_USE 105 +#define BIO_R_KEEPALIVE 106 +#define BIO_R_NBIO_CONNECT_ERROR 107 +#define BIO_R_NO_HOSTNAME_SPECIFIED 108 +#define BIO_R_NO_PORT_SPECIFIED 109 +#define BIO_R_NO_SUCH_FILE 110 +#define BIO_R_NULL_PARAMETER 111 +#define BIO_R_SYS_LIB 112 +#define BIO_R_UNABLE_TO_CREATE_SOCKET 113 +#define BIO_R_UNINITIALIZED 114 +#define BIO_R_UNSUPPORTED_METHOD 115 +#define BIO_R_WRITE_TO_READ_ONLY_BIO 116 + +#endif // OPENSSL_HEADER_BIO_H diff --git a/lib/boringssl/include/openssl/blake2.h b/lib/boringssl/include/openssl/blake2.h new file mode 100644 index 00000000..9ec1e6c6 --- /dev/null +++ b/lib/boringssl/include/openssl/blake2.h @@ -0,0 +1,62 @@ +/* Copyright (c) 2021, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_BLAKE2_H +#define OPENSSL_HEADER_BLAKE2_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#define BLAKE2B256_DIGEST_LENGTH (256 / 8) +#define BLAKE2B_CBLOCK 128 + +struct blake2b_state_st { + uint64_t h[8]; + uint64_t t_low, t_high; + union { + uint8_t bytes[BLAKE2B_CBLOCK]; + uint64_t words[16]; + } block; + size_t block_used; +}; + +// BLAKE2B256_Init initialises |b2b| to perform a BLAKE2b-256 hash. There are no +// pointers inside |b2b| thus release of |b2b| is purely managed by the caller. +OPENSSL_EXPORT void BLAKE2B256_Init(BLAKE2B_CTX *b2b); + +// BLAKE2B256_Update appends |len| bytes from |data| to the digest being +// calculated by |b2b|. +OPENSSL_EXPORT void BLAKE2B256_Update(BLAKE2B_CTX *b2b, const void *data, + size_t len); + +// BLAKE2B256_Final completes the digest calculated by |b2b| and writes +// |BLAKE2B256_DIGEST_LENGTH| bytes to |out|. +OPENSSL_EXPORT void BLAKE2B256_Final(uint8_t out[BLAKE2B256_DIGEST_LENGTH], + BLAKE2B_CTX *b2b); + +// BLAKE2B256 writes the BLAKE2b-256 digset of |len| bytes from |data| to +// |out|. +OPENSSL_EXPORT void BLAKE2B256(const uint8_t *data, size_t len, + uint8_t out[BLAKE2B256_DIGEST_LENGTH]); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_BLAKE2_H diff --git a/lib/boringssl/include/openssl/blowfish.h b/lib/boringssl/include/openssl/blowfish.h new file mode 100644 index 00000000..293b1755 --- /dev/null +++ b/lib/boringssl/include/openssl/blowfish.h @@ -0,0 +1,93 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BLOWFISH_H +#define OPENSSL_HEADER_BLOWFISH_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define BF_ENCRYPT 1 +#define BF_DECRYPT 0 + +#define BF_ROUNDS 16 +#define BF_BLOCK 8 + +typedef struct bf_key_st { + uint32_t P[BF_ROUNDS + 2]; + uint32_t S[4 * 256]; +} BF_KEY; + +OPENSSL_EXPORT void BF_set_key(BF_KEY *key, size_t len, const uint8_t *data); +OPENSSL_EXPORT void BF_encrypt(uint32_t *data, const BF_KEY *key); +OPENSSL_EXPORT void BF_decrypt(uint32_t *data, const BF_KEY *key); + +OPENSSL_EXPORT void BF_ecb_encrypt(const uint8_t *in, uint8_t *out, + const BF_KEY *key, int enc); +OPENSSL_EXPORT void BF_cbc_encrypt(const uint8_t *in, uint8_t *out, + size_t length, const BF_KEY *schedule, + uint8_t *ivec, int enc); + + +#ifdef __cplusplus +} +#endif + +#endif // OPENSSL_HEADER_BLOWFISH_H diff --git a/lib/boringssl/include/openssl/bn.h b/lib/boringssl/include/openssl/bn.h new file mode 100644 index 00000000..a03e41f1 --- /dev/null +++ b/lib/boringssl/include/openssl/bn.h @@ -0,0 +1,1089 @@ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the Eric Young open source + * license provided above. + * + * The binary polynomial arithmetic software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#ifndef OPENSSL_HEADER_BN_H +#define OPENSSL_HEADER_BN_H + +#include +#include + +#include // for PRIu64 and friends +#include // for FILE* + +#if defined(__cplusplus) +extern "C" { +#endif + + +// BN provides support for working with arbitrary sized integers. For example, +// although the largest integer supported by the compiler might be 64 bits, BN +// will allow you to work with much larger numbers. +// +// This library is developed for use inside BoringSSL, and uses implementation +// strategies that may not be ideal for other applications. Non-cryptographic +// uses should use a more general-purpose integer library, especially if +// performance-sensitive. +// +// Many functions in BN scale quadratically or higher in the bit length of their +// input. Callers at this layer are assumed to have capped input sizes within +// their performance tolerances. + + +// BN_ULONG is the native word size when working with big integers. +// +// Note: on some platforms, inttypes.h does not define print format macros in +// C++ unless |__STDC_FORMAT_MACROS| defined. This is due to text in C99 which +// was never adopted in any C++ standard and explicitly overruled in C++11. As +// this is a public header, bn.h does not define |__STDC_FORMAT_MACROS| itself. +// Projects which use |BN_*_FMT*| with outdated C headers may need to define it +// externally. +#if defined(OPENSSL_64_BIT) +typedef uint64_t BN_ULONG; +#define BN_BITS2 64 +#define BN_DEC_FMT1 "%" PRIu64 +#define BN_DEC_FMT2 "%019" PRIu64 +#define BN_HEX_FMT1 "%" PRIx64 +#define BN_HEX_FMT2 "%016" PRIx64 +#elif defined(OPENSSL_32_BIT) +typedef uint32_t BN_ULONG; +#define BN_BITS2 32 +#define BN_DEC_FMT1 "%" PRIu32 +#define BN_DEC_FMT2 "%09" PRIu32 +#define BN_HEX_FMT1 "%" PRIx32 +#define BN_HEX_FMT2 "%08" PRIx32 +#else +#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" +#endif + + +// Allocation and freeing. + +// BN_new creates a new, allocated BIGNUM and initialises it. +OPENSSL_EXPORT BIGNUM *BN_new(void); + +// BN_init initialises a stack allocated |BIGNUM|. +OPENSSL_EXPORT void BN_init(BIGNUM *bn); + +// BN_free frees the data referenced by |bn| and, if |bn| was originally +// allocated on the heap, frees |bn| also. +OPENSSL_EXPORT void BN_free(BIGNUM *bn); + +// BN_clear_free erases and frees the data referenced by |bn| and, if |bn| was +// originally allocated on the heap, frees |bn| also. +OPENSSL_EXPORT void BN_clear_free(BIGNUM *bn); + +// BN_dup allocates a new BIGNUM and sets it equal to |src|. It returns the +// allocated BIGNUM on success or NULL otherwise. +OPENSSL_EXPORT BIGNUM *BN_dup(const BIGNUM *src); + +// BN_copy sets |dest| equal to |src| and returns |dest| or NULL on allocation +// failure. +OPENSSL_EXPORT BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src); + +// BN_clear sets |bn| to zero and erases the old data. +OPENSSL_EXPORT void BN_clear(BIGNUM *bn); + +// BN_value_one returns a static BIGNUM with value 1. +OPENSSL_EXPORT const BIGNUM *BN_value_one(void); + + +// Basic functions. + +// BN_num_bits returns the minimum number of bits needed to represent the +// absolute value of |bn|. +OPENSSL_EXPORT unsigned BN_num_bits(const BIGNUM *bn); + +// BN_num_bytes returns the minimum number of bytes needed to represent the +// absolute value of |bn|. +// +// While |size_t| is the preferred type for byte counts, callers can assume that +// |BIGNUM|s are bounded such that this value, and its corresponding bit count, +// will always fit in |int|. +OPENSSL_EXPORT unsigned BN_num_bytes(const BIGNUM *bn); + +// BN_zero sets |bn| to zero. +OPENSSL_EXPORT void BN_zero(BIGNUM *bn); + +// BN_one sets |bn| to one. It returns one on success or zero on allocation +// failure. +OPENSSL_EXPORT int BN_one(BIGNUM *bn); + +// BN_set_word sets |bn| to |value|. It returns one on success or zero on +// allocation failure. +OPENSSL_EXPORT int BN_set_word(BIGNUM *bn, BN_ULONG value); + +// BN_set_u64 sets |bn| to |value|. It returns one on success or zero on +// allocation failure. +OPENSSL_EXPORT int BN_set_u64(BIGNUM *bn, uint64_t value); + +// BN_set_negative sets the sign of |bn|. +OPENSSL_EXPORT void BN_set_negative(BIGNUM *bn, int sign); + +// BN_is_negative returns one if |bn| is negative and zero otherwise. +OPENSSL_EXPORT int BN_is_negative(const BIGNUM *bn); + + +// Conversion functions. + +// BN_bin2bn sets |*ret| to the value of |len| bytes from |in|, interpreted as +// a big-endian number, and returns |ret|. If |ret| is NULL then a fresh +// |BIGNUM| is allocated and returned. It returns NULL on allocation +// failure. +OPENSSL_EXPORT BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret); + +// BN_bn2bin serialises the absolute value of |in| to |out| as a big-endian +// integer, which must have |BN_num_bytes| of space available. It returns the +// number of bytes written. Note this function leaks the magnitude of |in|. If +// |in| is secret, use |BN_bn2bin_padded| instead. +OPENSSL_EXPORT size_t BN_bn2bin(const BIGNUM *in, uint8_t *out); + +// BN_le2bn sets |*ret| to the value of |len| bytes from |in|, interpreted as +// a little-endian number, and returns |ret|. If |ret| is NULL then a fresh +// |BIGNUM| is allocated and returned. It returns NULL on allocation +// failure. +OPENSSL_EXPORT BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret); + +// BN_bn2le_padded serialises the absolute value of |in| to |out| as a +// little-endian integer, which must have |len| of space available, padding +// out the remainder of out with zeros. If |len| is smaller than |BN_num_bytes|, +// the function fails and returns 0. Otherwise, it returns 1. +OPENSSL_EXPORT int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in); + +// BN_bn2bin_padded serialises the absolute value of |in| to |out| as a +// big-endian integer. The integer is padded with leading zeros up to size +// |len|. If |len| is smaller than |BN_num_bytes|, the function fails and +// returns 0. Otherwise, it returns 1. +OPENSSL_EXPORT int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in); + +// BN_bn2cbb_padded behaves like |BN_bn2bin_padded| but writes to a |CBB|. +OPENSSL_EXPORT int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in); + +// BN_bn2hex returns an allocated string that contains a NUL-terminated, hex +// representation of |bn|. If |bn| is negative, the first char in the resulting +// string will be '-'. Returns NULL on allocation failure. +OPENSSL_EXPORT char *BN_bn2hex(const BIGNUM *bn); + +// BN_hex2bn parses the leading hex number from |in|, which may be proceeded by +// a '-' to indicate a negative number and may contain trailing, non-hex data. +// If |outp| is not NULL, it constructs a BIGNUM equal to the hex number and +// stores it in |*outp|. If |*outp| is NULL then it allocates a new BIGNUM and +// updates |*outp|. It returns the number of bytes of |in| processed or zero on +// error. +OPENSSL_EXPORT int BN_hex2bn(BIGNUM **outp, const char *in); + +// BN_bn2dec returns an allocated string that contains a NUL-terminated, +// decimal representation of |bn|. If |bn| is negative, the first char in the +// resulting string will be '-'. Returns NULL on allocation failure. +// +// Converting an arbitrarily large integer to decimal is quadratic in the bit +// length of |a|. This function assumes the caller has capped the input within +// performance tolerances. +OPENSSL_EXPORT char *BN_bn2dec(const BIGNUM *a); + +// BN_dec2bn parses the leading decimal number from |in|, which may be +// proceeded by a '-' to indicate a negative number and may contain trailing, +// non-decimal data. If |outp| is not NULL, it constructs a BIGNUM equal to the +// decimal number and stores it in |*outp|. If |*outp| is NULL then it +// allocates a new BIGNUM and updates |*outp|. It returns the number of bytes +// of |in| processed or zero on error. +// +// Converting an arbitrarily large integer to decimal is quadratic in the bit +// length of |a|. This function assumes the caller has capped the input within +// performance tolerances. +OPENSSL_EXPORT int BN_dec2bn(BIGNUM **outp, const char *in); + +// BN_asc2bn acts like |BN_dec2bn| or |BN_hex2bn| depending on whether |in| +// begins with "0X" or "0x" (indicating hex) or not (indicating decimal). A +// leading '-' is still permitted and comes before the optional 0X/0x. It +// returns one on success or zero on error. +OPENSSL_EXPORT int BN_asc2bn(BIGNUM **outp, const char *in); + +// BN_print writes a hex encoding of |a| to |bio|. It returns one on success +// and zero on error. +OPENSSL_EXPORT int BN_print(BIO *bio, const BIGNUM *a); + +// BN_print_fp acts like |BIO_print|, but wraps |fp| in a |BIO| first. +OPENSSL_EXPORT int BN_print_fp(FILE *fp, const BIGNUM *a); + +// BN_get_word returns the absolute value of |bn| as a single word. If |bn| is +// too large to be represented as a single word, the maximum possible value +// will be returned. +OPENSSL_EXPORT BN_ULONG BN_get_word(const BIGNUM *bn); + +// BN_get_u64 sets |*out| to the absolute value of |bn| as a |uint64_t| and +// returns one. If |bn| is too large to be represented as a |uint64_t|, it +// returns zero. +OPENSSL_EXPORT int BN_get_u64(const BIGNUM *bn, uint64_t *out); + + +// ASN.1 functions. + +// BN_parse_asn1_unsigned parses a non-negative DER INTEGER from |cbs| writes +// the result to |ret|. It returns one on success and zero on failure. +OPENSSL_EXPORT int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret); + +// BN_marshal_asn1 marshals |bn| as a non-negative DER INTEGER and appends the +// result to |cbb|. It returns one on success and zero on failure. +OPENSSL_EXPORT int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn); + + +// BIGNUM pools. +// +// Certain BIGNUM operations need to use many temporary variables and +// allocating and freeing them can be quite slow. Thus such operations typically +// take a |BN_CTX| parameter, which contains a pool of |BIGNUMs|. The |ctx| +// argument to a public function may be NULL, in which case a local |BN_CTX| +// will be created just for the lifetime of that call. +// +// A function must call |BN_CTX_start| first. Then, |BN_CTX_get| may be called +// repeatedly to obtain temporary |BIGNUM|s. All |BN_CTX_get| calls must be made +// before calling any other functions that use the |ctx| as an argument. +// +// Finally, |BN_CTX_end| must be called before returning from the function. +// When |BN_CTX_end| is called, the |BIGNUM| pointers obtained from +// |BN_CTX_get| become invalid. + +// BN_CTX_new returns a new, empty BN_CTX or NULL on allocation failure. +OPENSSL_EXPORT BN_CTX *BN_CTX_new(void); + +// BN_CTX_free frees all BIGNUMs contained in |ctx| and then frees |ctx| +// itself. +OPENSSL_EXPORT void BN_CTX_free(BN_CTX *ctx); + +// BN_CTX_start "pushes" a new entry onto the |ctx| stack and allows future +// calls to |BN_CTX_get|. +OPENSSL_EXPORT void BN_CTX_start(BN_CTX *ctx); + +// BN_CTX_get returns a new |BIGNUM|, or NULL on allocation failure. Once +// |BN_CTX_get| has returned NULL, all future calls will also return NULL until +// |BN_CTX_end| is called. +OPENSSL_EXPORT BIGNUM *BN_CTX_get(BN_CTX *ctx); + +// BN_CTX_end invalidates all |BIGNUM|s returned from |BN_CTX_get| since the +// matching |BN_CTX_start| call. +OPENSSL_EXPORT void BN_CTX_end(BN_CTX *ctx); + + +// Simple arithmetic + +// BN_add sets |r| = |a| + |b|, where |r| may be the same pointer as either |a| +// or |b|. It returns one on success and zero on allocation failure. +OPENSSL_EXPORT int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +// BN_uadd sets |r| = |a| + |b|, where |a| and |b| are non-negative and |r| may +// be the same pointer as either |a| or |b|. It returns one on success and zero +// on allocation failure. +OPENSSL_EXPORT int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +// BN_add_word adds |w| to |a|. It returns one on success and zero otherwise. +OPENSSL_EXPORT int BN_add_word(BIGNUM *a, BN_ULONG w); + +// BN_sub sets |r| = |a| - |b|, where |r| may be the same pointer as either |a| +// or |b|. It returns one on success and zero on allocation failure. +OPENSSL_EXPORT int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +// BN_usub sets |r| = |a| - |b|, where |a| and |b| are non-negative integers, +// |b| < |a| and |r| may be the same pointer as either |a| or |b|. It returns +// one on success and zero on allocation failure. +OPENSSL_EXPORT int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +// BN_sub_word subtracts |w| from |a|. It returns one on success and zero on +// allocation failure. +OPENSSL_EXPORT int BN_sub_word(BIGNUM *a, BN_ULONG w); + +// BN_mul sets |r| = |a| * |b|, where |r| may be the same pointer as |a| or +// |b|. Returns one on success and zero otherwise. +OPENSSL_EXPORT int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx); + +// BN_mul_word sets |bn| = |bn| * |w|. It returns one on success or zero on +// allocation failure. +OPENSSL_EXPORT int BN_mul_word(BIGNUM *bn, BN_ULONG w); + +// BN_sqr sets |r| = |a|^2 (i.e. squares), where |r| may be the same pointer as +// |a|. Returns one on success and zero otherwise. This is more efficient than +// BN_mul(r, a, a, ctx). +OPENSSL_EXPORT int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); + +// BN_div divides |numerator| by |divisor| and places the result in |quotient| +// and the remainder in |rem|. Either of |quotient| or |rem| may be NULL, in +// which case the respective value is not returned. The result is rounded +// towards zero; thus if |numerator| is negative, the remainder will be zero or +// negative. It returns one on success or zero on error. +OPENSSL_EXPORT int BN_div(BIGNUM *quotient, BIGNUM *rem, + const BIGNUM *numerator, const BIGNUM *divisor, + BN_CTX *ctx); + +// BN_div_word sets |numerator| = |numerator|/|divisor| and returns the +// remainder or (BN_ULONG)-1 on error. +OPENSSL_EXPORT BN_ULONG BN_div_word(BIGNUM *numerator, BN_ULONG divisor); + +// BN_sqrt sets |*out_sqrt| (which may be the same |BIGNUM| as |in|) to the +// square root of |in|, using |ctx|. It returns one on success or zero on +// error. Negative numbers and non-square numbers will result in an error with +// appropriate errors on the error queue. +OPENSSL_EXPORT int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx); + + +// Comparison functions + +// BN_cmp returns a value less than, equal to or greater than zero if |a| is +// less than, equal to or greater than |b|, respectively. +OPENSSL_EXPORT int BN_cmp(const BIGNUM *a, const BIGNUM *b); + +// BN_cmp_word is like |BN_cmp| except it takes its second argument as a +// |BN_ULONG| instead of a |BIGNUM|. +OPENSSL_EXPORT int BN_cmp_word(const BIGNUM *a, BN_ULONG b); + +// BN_ucmp returns a value less than, equal to or greater than zero if the +// absolute value of |a| is less than, equal to or greater than the absolute +// value of |b|, respectively. +OPENSSL_EXPORT int BN_ucmp(const BIGNUM *a, const BIGNUM *b); + +// BN_equal_consttime returns one if |a| is equal to |b|, and zero otherwise. +// It takes an amount of time dependent on the sizes of |a| and |b|, but +// independent of the contents (including the signs) of |a| and |b|. +OPENSSL_EXPORT int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b); + +// BN_abs_is_word returns one if the absolute value of |bn| equals |w| and zero +// otherwise. +OPENSSL_EXPORT int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w); + +// BN_is_zero returns one if |bn| is zero and zero otherwise. +OPENSSL_EXPORT int BN_is_zero(const BIGNUM *bn); + +// BN_is_one returns one if |bn| equals one and zero otherwise. +OPENSSL_EXPORT int BN_is_one(const BIGNUM *bn); + +// BN_is_word returns one if |bn| is exactly |w| and zero otherwise. +OPENSSL_EXPORT int BN_is_word(const BIGNUM *bn, BN_ULONG w); + +// BN_is_odd returns one if |bn| is odd and zero otherwise. +OPENSSL_EXPORT int BN_is_odd(const BIGNUM *bn); + +// BN_is_pow2 returns 1 if |a| is a power of two, and 0 otherwise. +OPENSSL_EXPORT int BN_is_pow2(const BIGNUM *a); + + +// Bitwise operations. + +// BN_lshift sets |r| equal to |a| << n. The |a| and |r| arguments may be the +// same |BIGNUM|. It returns one on success and zero on allocation failure. +OPENSSL_EXPORT int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); + +// BN_lshift1 sets |r| equal to |a| << 1, where |r| and |a| may be the same +// pointer. It returns one on success and zero on allocation failure. +OPENSSL_EXPORT int BN_lshift1(BIGNUM *r, const BIGNUM *a); + +// BN_rshift sets |r| equal to |a| >> n, where |r| and |a| may be the same +// pointer. It returns one on success and zero on allocation failure. +OPENSSL_EXPORT int BN_rshift(BIGNUM *r, const BIGNUM *a, int n); + +// BN_rshift1 sets |r| equal to |a| >> 1, where |r| and |a| may be the same +// pointer. It returns one on success and zero on allocation failure. +OPENSSL_EXPORT int BN_rshift1(BIGNUM *r, const BIGNUM *a); + +// BN_set_bit sets the |n|th, least-significant bit in |a|. For example, if |a| +// is 2 then setting bit zero will make it 3. It returns one on success or zero +// on allocation failure. +OPENSSL_EXPORT int BN_set_bit(BIGNUM *a, int n); + +// BN_clear_bit clears the |n|th, least-significant bit in |a|. For example, if +// |a| is 3, clearing bit zero will make it two. It returns one on success or +// zero on allocation failure. +OPENSSL_EXPORT int BN_clear_bit(BIGNUM *a, int n); + +// BN_is_bit_set returns one if the |n|th least-significant bit in |a| exists +// and is set. Otherwise, it returns zero. +OPENSSL_EXPORT int BN_is_bit_set(const BIGNUM *a, int n); + +// BN_mask_bits truncates |a| so that it is only |n| bits long. It returns one +// on success or zero if |n| is negative. +// +// This differs from OpenSSL which additionally returns zero if |a|'s word +// length is less than or equal to |n|, rounded down to a number of words. Note +// word size is platform-dependent, so this behavior is also difficult to rely +// on in OpenSSL and not very useful. +OPENSSL_EXPORT int BN_mask_bits(BIGNUM *a, int n); + +// BN_count_low_zero_bits returns the number of low-order zero bits in |bn|, or +// the number of factors of two which divide it. It returns zero if |bn| is +// zero. +OPENSSL_EXPORT int BN_count_low_zero_bits(const BIGNUM *bn); + + +// Modulo arithmetic. + +// BN_mod_word returns |a| mod |w| or (BN_ULONG)-1 on error. +OPENSSL_EXPORT BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); + +// BN_mod_pow2 sets |r| = |a| mod 2^|e|. It returns 1 on success and +// 0 on error. +OPENSSL_EXPORT int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e); + +// BN_nnmod_pow2 sets |r| = |a| mod 2^|e| where |r| is always positive. +// It returns 1 on success and 0 on error. +OPENSSL_EXPORT int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e); + +// BN_mod is a helper macro that calls |BN_div| and discards the quotient. +#define BN_mod(rem, numerator, divisor, ctx) \ + BN_div(NULL, (rem), (numerator), (divisor), (ctx)) + +// BN_nnmod is a non-negative modulo function. It acts like |BN_mod|, but 0 <= +// |rem| < |divisor| is always true. It returns one on success and zero on +// error. +OPENSSL_EXPORT int BN_nnmod(BIGNUM *rem, const BIGNUM *numerator, + const BIGNUM *divisor, BN_CTX *ctx); + +// BN_mod_add sets |r| = |a| + |b| mod |m|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); + +// BN_mod_add_quick acts like |BN_mod_add| but requires that |a| and |b| be +// non-negative and less than |m|. +OPENSSL_EXPORT int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); + +// BN_mod_sub sets |r| = |a| - |b| mod |m|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); + +// BN_mod_sub_quick acts like |BN_mod_sub| but requires that |a| and |b| be +// non-negative and less than |m|. +OPENSSL_EXPORT int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); + +// BN_mod_mul sets |r| = |a|*|b| mod |m|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); + +// BN_mod_sqr sets |r| = |a|^2 mod |m|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, + BN_CTX *ctx); + +// BN_mod_lshift sets |r| = (|a| << n) mod |m|, where |r| and |a| may be the +// same pointer. It returns one on success and zero on error. +OPENSSL_EXPORT int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, + const BIGNUM *m, BN_CTX *ctx); + +// BN_mod_lshift_quick acts like |BN_mod_lshift| but requires that |a| be +// non-negative and less than |m|. +OPENSSL_EXPORT int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, + const BIGNUM *m); + +// BN_mod_lshift1 sets |r| = (|a| << 1) mod |m|, where |r| and |a| may be the +// same pointer. It returns one on success and zero on error. +OPENSSL_EXPORT int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, + BN_CTX *ctx); + +// BN_mod_lshift1_quick acts like |BN_mod_lshift1| but requires that |a| be +// non-negative and less than |m|. +OPENSSL_EXPORT int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, + const BIGNUM *m); + +// BN_mod_sqrt returns a newly-allocated |BIGNUM|, r, such that +// r^2 == a (mod p). It returns NULL on error or if |a| is not a square mod |p|. +// In the latter case, it will add |BN_R_NOT_A_SQUARE| to the error queue. +// If |a| is a square and |p| > 2, there are two possible square roots. This +// function may return either and may even select one non-deterministically. +// +// This function only works if |p| is a prime. If |p| is composite, it may fail +// or return an arbitrary value. Callers should not pass attacker-controlled +// values of |p|. +OPENSSL_EXPORT BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); + + +// Random and prime number generation. + +// The following are values for the |top| parameter of |BN_rand|. +#define BN_RAND_TOP_ANY (-1) +#define BN_RAND_TOP_ONE 0 +#define BN_RAND_TOP_TWO 1 + +// The following are values for the |bottom| parameter of |BN_rand|. +#define BN_RAND_BOTTOM_ANY 0 +#define BN_RAND_BOTTOM_ODD 1 + +// BN_rand sets |rnd| to a random number of length |bits|. It returns one on +// success and zero otherwise. +// +// |top| must be one of the |BN_RAND_TOP_*| values. If |BN_RAND_TOP_ONE|, the +// most-significant bit, if any, will be set. If |BN_RAND_TOP_TWO|, the two +// most significant bits, if any, will be set. If |BN_RAND_TOP_ANY|, no extra +// action will be taken and |BN_num_bits(rnd)| may not equal |bits| if the most +// significant bits randomly ended up as zeros. +// +// |bottom| must be one of the |BN_RAND_BOTTOM_*| values. If +// |BN_RAND_BOTTOM_ODD|, the least-significant bit, if any, will be set. If +// |BN_RAND_BOTTOM_ANY|, no extra action will be taken. +OPENSSL_EXPORT int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); + +// BN_pseudo_rand is an alias for |BN_rand|. +OPENSSL_EXPORT int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); + +// BN_rand_range is equivalent to |BN_rand_range_ex| with |min_inclusive| set +// to zero and |max_exclusive| set to |range|. +OPENSSL_EXPORT int BN_rand_range(BIGNUM *rnd, const BIGNUM *range); + +// BN_rand_range_ex sets |rnd| to a random value in +// [min_inclusive..max_exclusive). It returns one on success and zero +// otherwise. +OPENSSL_EXPORT int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive, + const BIGNUM *max_exclusive); + +// BN_pseudo_rand_range is an alias for BN_rand_range. +OPENSSL_EXPORT int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range); + +#define BN_GENCB_GENERATED 0 +#define BN_GENCB_PRIME_TEST 1 + +// bn_gencb_st, or |BN_GENCB|, holds a callback function that is used by +// generation functions that can take a very long time to complete. Use +// |BN_GENCB_set| to initialise a |BN_GENCB| structure. +// +// The callback receives the address of that |BN_GENCB| structure as its last +// argument and the user is free to put an arbitrary pointer in |arg|. The other +// arguments are set as follows: +// event=BN_GENCB_GENERATED, n=i: after generating the i'th possible prime +// number. +// event=BN_GENCB_PRIME_TEST, n=-1: when finished trial division primality +// checks. +// event=BN_GENCB_PRIME_TEST, n=i: when the i'th primality test has finished. +// +// The callback can return zero to abort the generation progress or one to +// allow it to continue. +// +// When other code needs to call a BN generation function it will often take a +// BN_GENCB argument and may call the function with other argument values. +struct bn_gencb_st { + void *arg; // callback-specific data + int (*callback)(int event, int n, struct bn_gencb_st *); +}; + +// BN_GENCB_new returns a newly-allocated |BN_GENCB| object, or NULL on +// allocation failure. The result must be released with |BN_GENCB_free| when +// done. +OPENSSL_EXPORT BN_GENCB *BN_GENCB_new(void); + +// BN_GENCB_free releases memory associated with |callback|. +OPENSSL_EXPORT void BN_GENCB_free(BN_GENCB *callback); + +// BN_GENCB_set configures |callback| to call |f| and sets |callout->arg| to +// |arg|. +OPENSSL_EXPORT void BN_GENCB_set(BN_GENCB *callback, + int (*f)(int event, int n, BN_GENCB *), + void *arg); + +// BN_GENCB_call calls |callback|, if not NULL, and returns the return value of +// the callback, or 1 if |callback| is NULL. +OPENSSL_EXPORT int BN_GENCB_call(BN_GENCB *callback, int event, int n); + +// BN_GENCB_get_arg returns |callback->arg|. +OPENSSL_EXPORT void *BN_GENCB_get_arg(const BN_GENCB *callback); + +// BN_generate_prime_ex sets |ret| to a prime number of |bits| length. If safe +// is non-zero then the prime will be such that (ret-1)/2 is also a prime. +// (This is needed for Diffie-Hellman groups to ensure that the only subgroups +// are of size 2 and (p-1)/2.). +// +// If |add| is not NULL, the prime will fulfill the condition |ret| % |add| == +// |rem| in order to suit a given generator. (If |rem| is NULL then |ret| % +// |add| == 1.) +// +// If |cb| is not NULL, it will be called during processing to give an +// indication of progress. See the comments for |BN_GENCB|. It returns one on +// success and zero otherwise. +OPENSSL_EXPORT int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, + BN_GENCB *cb); + +// BN_prime_checks_for_validation can be used as the |checks| argument to the +// primarily testing functions when validating an externally-supplied candidate +// prime. It gives a false positive rate of at most 2^{-128}. (The worst case +// false positive rate for a single iteration is 1/4 per +// https://eprint.iacr.org/2018/749. (1/4)^64 = 2^{-128}.) +#define BN_prime_checks_for_validation 64 + +// BN_prime_checks_for_generation can be used as the |checks| argument to the +// primality testing functions when generating random primes. It gives a false +// positive rate at most the security level of the corresponding RSA key size. +// +// Note this value only performs enough checks if the candidate prime was +// selected randomly. If validating an externally-supplied candidate, especially +// one that may be selected adversarially, use |BN_prime_checks_for_validation| +// instead. +#define BN_prime_checks_for_generation 0 + +// bn_primality_result_t enumerates the outcomes of primality-testing. +enum bn_primality_result_t { + bn_probably_prime, + bn_composite, + bn_non_prime_power_composite, +}; + +// BN_enhanced_miller_rabin_primality_test tests whether |w| is probably a prime +// number using the Enhanced Miller-Rabin Test (FIPS 186-4 C.3.2) with +// |checks| iterations and returns the result in |out_result|. Enhanced +// Miller-Rabin tests primality for odd integers greater than 3, returning +// |bn_probably_prime| if the number is probably prime, +// |bn_non_prime_power_composite| if the number is a composite that is not the +// power of a single prime, and |bn_composite| otherwise. It returns one on +// success and zero on failure. If |cb| is not NULL, then it is called during +// each iteration of the primality test. +// +// See |BN_prime_checks_for_validation| and |BN_prime_checks_for_generation| for +// recommended values of |checks|. +OPENSSL_EXPORT int BN_enhanced_miller_rabin_primality_test( + enum bn_primality_result_t *out_result, const BIGNUM *w, int checks, + BN_CTX *ctx, BN_GENCB *cb); + +// BN_primality_test sets |*is_probably_prime| to one if |candidate| is +// probably a prime number by the Miller-Rabin test or zero if it's certainly +// not. +// +// If |do_trial_division| is non-zero then |candidate| will be tested against a +// list of small primes before Miller-Rabin tests. The probability of this +// function returning a false positive is at most 2^{2*checks}. See +// |BN_prime_checks_for_validation| and |BN_prime_checks_for_generation| for +// recommended values of |checks|. +// +// If |cb| is not NULL then it is called during the checking process. See the +// comment above |BN_GENCB|. +// +// The function returns one on success and zero on error. +OPENSSL_EXPORT int BN_primality_test(int *is_probably_prime, + const BIGNUM *candidate, int checks, + BN_CTX *ctx, int do_trial_division, + BN_GENCB *cb); + +// BN_is_prime_fasttest_ex returns one if |candidate| is probably a prime +// number by the Miller-Rabin test, zero if it's certainly not and -1 on error. +// +// If |do_trial_division| is non-zero then |candidate| will be tested against a +// list of small primes before Miller-Rabin tests. The probability of this +// function returning one when |candidate| is composite is at most 2^{2*checks}. +// See |BN_prime_checks_for_validation| and |BN_prime_checks_for_generation| for +// recommended values of |checks|. +// +// If |cb| is not NULL then it is called during the checking process. See the +// comment above |BN_GENCB|. +// +// WARNING: deprecated. Use |BN_primality_test|. +OPENSSL_EXPORT int BN_is_prime_fasttest_ex(const BIGNUM *candidate, int checks, + BN_CTX *ctx, int do_trial_division, + BN_GENCB *cb); + +// BN_is_prime_ex acts the same as |BN_is_prime_fasttest_ex| with +// |do_trial_division| set to zero. +// +// WARNING: deprecated: Use |BN_primality_test|. +OPENSSL_EXPORT int BN_is_prime_ex(const BIGNUM *candidate, int checks, + BN_CTX *ctx, BN_GENCB *cb); + + +// Number theory functions + +// BN_gcd sets |r| = gcd(|a|, |b|). It returns one on success and zero +// otherwise. +OPENSSL_EXPORT int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx); + +// BN_mod_inverse sets |out| equal to |a|^-1, mod |n|. If |out| is NULL, a +// fresh BIGNUM is allocated. It returns the result or NULL on error. +// +// If |n| is even then the operation is performed using an algorithm that avoids +// some branches but which isn't constant-time. This function shouldn't be used +// for secret values; use |BN_mod_inverse_blinded| instead. Or, if |n| is +// guaranteed to be prime, use +// |BN_mod_exp_mont_consttime(out, a, m_minus_2, m, ctx, m_mont)|, taking +// advantage of Fermat's Little Theorem. +OPENSSL_EXPORT BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, + const BIGNUM *n, BN_CTX *ctx); + +// BN_mod_inverse_blinded sets |out| equal to |a|^-1, mod |n|, where |n| is the +// Montgomery modulus for |mont|. |a| must be non-negative and must be less +// than |n|. |n| must be greater than 1. |a| is blinded (masked by a random +// value) to protect it against side-channel attacks. On failure, if the failure +// was caused by |a| having no inverse mod |n| then |*out_no_inverse| will be +// set to one; otherwise it will be set to zero. +// +// Note this function may incorrectly report |a| has no inverse if the random +// blinding value has no inverse. It should only be used when |n| has few +// non-invertible elements, such as an RSA modulus. +OPENSSL_EXPORT int BN_mod_inverse_blinded(BIGNUM *out, int *out_no_inverse, + const BIGNUM *a, + const BN_MONT_CTX *mont, BN_CTX *ctx); + +// BN_mod_inverse_odd sets |out| equal to |a|^-1, mod |n|. |a| must be +// non-negative and must be less than |n|. |n| must be odd. This function +// shouldn't be used for secret values; use |BN_mod_inverse_blinded| instead. +// Or, if |n| is guaranteed to be prime, use +// |BN_mod_exp_mont_consttime(out, a, m_minus_2, m, ctx, m_mont)|, taking +// advantage of Fermat's Little Theorem. It returns one on success or zero on +// failure. On failure, if the failure was caused by |a| having no inverse mod +// |n| then |*out_no_inverse| will be set to one; otherwise it will be set to +// zero. +int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a, + const BIGNUM *n, BN_CTX *ctx); + + +// Montgomery arithmetic. + +// BN_MONT_CTX contains the precomputed values needed to work in a specific +// Montgomery domain. + +// BN_MONT_CTX_new_for_modulus returns a fresh |BN_MONT_CTX| given the modulus, +// |mod| or NULL on error. Note this function assumes |mod| is public. +OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new_for_modulus(const BIGNUM *mod, + BN_CTX *ctx); + +// BN_MONT_CTX_new_consttime behaves like |BN_MONT_CTX_new_for_modulus| but +// treats |mod| as secret. +OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new_consttime(const BIGNUM *mod, + BN_CTX *ctx); + +// BN_MONT_CTX_free frees memory associated with |mont|. +OPENSSL_EXPORT void BN_MONT_CTX_free(BN_MONT_CTX *mont); + +// BN_MONT_CTX_copy sets |to| equal to |from|. It returns |to| on success or +// NULL on error. +OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, + const BN_MONT_CTX *from); + +// BN_to_montgomery sets |ret| equal to |a| in the Montgomery domain. |a| is +// assumed to be in the range [0, n), where |n| is the Montgomery modulus. It +// returns one on success or zero on error. +OPENSSL_EXPORT int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, + const BN_MONT_CTX *mont, BN_CTX *ctx); + +// BN_from_montgomery sets |ret| equal to |a| * R^-1, i.e. translates values out +// of the Montgomery domain. |a| is assumed to be in the range [0, n*R), where +// |n| is the Montgomery modulus. Note n < R, so inputs in the range [0, n*n) +// are valid. This function returns one on success or zero on error. +OPENSSL_EXPORT int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, + const BN_MONT_CTX *mont, BN_CTX *ctx); + +// BN_mod_mul_montgomery set |r| equal to |a| * |b|, in the Montgomery domain. +// Both |a| and |b| must already be in the Montgomery domain (by +// |BN_to_montgomery|). In particular, |a| and |b| are assumed to be in the +// range [0, n), where |n| is the Montgomery modulus. It returns one on success +// or zero on error. +OPENSSL_EXPORT int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, + const BN_MONT_CTX *mont, BN_CTX *ctx); + + +// Exponentiation. + +// BN_exp sets |r| equal to |a|^{|p|}. It does so with a square-and-multiply +// algorithm that leaks side-channel information. It returns one on success or +// zero otherwise. +OPENSSL_EXPORT int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); + +// BN_mod_exp sets |r| equal to |a|^{|p|} mod |m|. It does so with the best +// algorithm for the values provided. It returns one on success or zero +// otherwise. The |BN_mod_exp_mont_consttime| variant must be used if the +// exponent is secret. +OPENSSL_EXPORT int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +// BN_mod_exp_mont behaves like |BN_mod_exp| but treats |a| as secret and +// requires 0 <= |a| < |m|. +OPENSSL_EXPORT int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + const BN_MONT_CTX *mont); + +// BN_mod_exp_mont_consttime behaves like |BN_mod_exp| but treats |a|, |p|, and +// |m| as secret and requires 0 <= |a| < |m|. +OPENSSL_EXPORT int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, + BN_CTX *ctx, + const BN_MONT_CTX *mont); + + +// Deprecated functions + +// BN_bn2mpi serialises the value of |in| to |out|, using a format that consists +// of the number's length in bytes represented as a 4-byte big-endian number, +// and the number itself in big-endian format, where the most significant bit +// signals a negative number. (The representation of numbers with the MSB set is +// prefixed with null byte). |out| must have sufficient space available; to +// find the needed amount of space, call the function with |out| set to NULL. +OPENSSL_EXPORT size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out); + +// BN_mpi2bn parses |len| bytes from |in| and returns the resulting value. The +// bytes at |in| are expected to be in the format emitted by |BN_bn2mpi|. +// +// If |out| is NULL then a fresh |BIGNUM| is allocated and returned, otherwise +// |out| is reused and returned. On error, NULL is returned and the error queue +// is updated. +OPENSSL_EXPORT BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out); + +// BN_mod_exp_mont_word is like |BN_mod_exp_mont| except that the base |a| is +// given as a |BN_ULONG| instead of a |BIGNUM *|. It returns one on success +// or zero otherwise. +OPENSSL_EXPORT int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + const BN_MONT_CTX *mont); + +// BN_mod_exp2_mont calculates (a1^p1) * (a2^p2) mod m. It returns 1 on success +// or zero otherwise. +OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, + const BIGNUM *p1, const BIGNUM *a2, + const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, const BN_MONT_CTX *mont); + +// BN_MONT_CTX_new returns a fresh |BN_MONT_CTX| or NULL on allocation failure. +// Use |BN_MONT_CTX_new_for_modulus| instead. +OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new(void); + +// BN_MONT_CTX_set sets up a Montgomery context given the modulus, |mod|. It +// returns one on success and zero on error. Use |BN_MONT_CTX_new_for_modulus| +// instead. +OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, + BN_CTX *ctx); + +// BN_bn2binpad behaves like |BN_bn2bin_padded|, but it returns |len| on success +// and -1 on error. +// +// Use |BN_bn2bin_padded| instead. It is |size_t|-clean. +OPENSSL_EXPORT int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len); + +// BN_prime_checks is a deprecated alias for |BN_prime_checks_for_validation|. +// Use |BN_prime_checks_for_generation| or |BN_prime_checks_for_validation| +// instead. (This defaults to the |_for_validation| value in order to be +// conservative.) +#define BN_prime_checks BN_prime_checks_for_validation + +// BN_secure_new calls |BN_new|. +OPENSSL_EXPORT BIGNUM *BN_secure_new(void); + + +// Private functions + +struct bignum_st { + // d is a pointer to an array of |width| |BN_BITS2|-bit chunks in + // little-endian order. This stores the absolute value of the number. + BN_ULONG *d; + // width is the number of elements of |d| which are valid. This value is not + // necessarily minimal; the most-significant words of |d| may be zero. + // |width| determines a potentially loose upper-bound on the absolute value + // of the |BIGNUM|. + // + // Functions taking |BIGNUM| inputs must compute the same answer for all + // possible widths. |bn_minimal_width|, |bn_set_minimal_width|, and other + // helpers may be used to recover the minimal width, provided it is not + // secret. If it is secret, use a different algorithm. Functions may output + // minimal or non-minimal |BIGNUM|s depending on secrecy requirements, but + // those which cause widths to unboundedly grow beyond the minimal value + // should be documented such. + // + // Note this is different from historical |BIGNUM| semantics. + int width; + // dmax is number of elements of |d| which are allocated. + int dmax; + // neg is one if the number if negative and zero otherwise. + int neg; + // flags is a bitmask of |BN_FLG_*| values + int flags; +}; + +struct bn_mont_ctx_st { + // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form. It + // is guaranteed to have the same width as |N|. + BIGNUM RR; + // N is the modulus. It is always stored in minimal form, so |N.width| + // determines R. + BIGNUM N; + BN_ULONG n0[2]; // least significant words of (R*Ri-1)/N +}; + +OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l); + +#define BN_FLG_MALLOCED 0x01 +#define BN_FLG_STATIC_DATA 0x02 +// |BN_FLG_CONSTTIME| has been removed and intentionally omitted so code relying +// on it will not compile. Consumers outside BoringSSL should use the +// higher-level cryptographic algorithms exposed by other modules. Consumers +// within the library should call the appropriate timing-sensitive algorithm +// directly. + + +#if defined(__cplusplus) +} // extern C + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(BIGNUM, BN_free) +BORINGSSL_MAKE_DELETER(BN_CTX, BN_CTX_free) +BORINGSSL_MAKE_DELETER(BN_MONT_CTX, BN_MONT_CTX_free) + +class BN_CTXScope { + public: + BN_CTXScope(BN_CTX *ctx) : ctx_(ctx) { BN_CTX_start(ctx_); } + ~BN_CTXScope() { BN_CTX_end(ctx_); } + + private: + BN_CTX *ctx_; + + BN_CTXScope(BN_CTXScope &) = delete; + BN_CTXScope &operator=(BN_CTXScope &) = delete; +}; + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#endif + +#define BN_R_ARG2_LT_ARG3 100 +#define BN_R_BAD_RECIPROCAL 101 +#define BN_R_BIGNUM_TOO_LONG 102 +#define BN_R_BITS_TOO_SMALL 103 +#define BN_R_CALLED_WITH_EVEN_MODULUS 104 +#define BN_R_DIV_BY_ZERO 105 +#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 106 +#define BN_R_INPUT_NOT_REDUCED 107 +#define BN_R_INVALID_RANGE 108 +#define BN_R_NEGATIVE_NUMBER 109 +#define BN_R_NOT_A_SQUARE 110 +#define BN_R_NOT_INITIALIZED 111 +#define BN_R_NO_INVERSE 112 +#define BN_R_PRIVATE_KEY_TOO_LARGE 113 +#define BN_R_P_IS_NOT_PRIME 114 +#define BN_R_TOO_MANY_ITERATIONS 115 +#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 116 +#define BN_R_BAD_ENCODING 117 +#define BN_R_ENCODE_ERROR 118 +#define BN_R_INVALID_INPUT 119 + +#endif // OPENSSL_HEADER_BN_H diff --git a/lib/boringssl/include/openssl/buf.h b/lib/boringssl/include/openssl/buf.h new file mode 100644 index 00000000..a57f000a --- /dev/null +++ b/lib/boringssl/include/openssl/buf.h @@ -0,0 +1,137 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BUFFER_H +#define OPENSSL_HEADER_BUFFER_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Memory and string functions, see also mem.h. + + +// buf_mem_st (aka |BUF_MEM|) is a generic buffer object used by OpenSSL. +struct buf_mem_st { + size_t length; // current number of bytes + char *data; + size_t max; // size of buffer +}; + +// BUF_MEM_new creates a new BUF_MEM which has no allocated data buffer. +OPENSSL_EXPORT BUF_MEM *BUF_MEM_new(void); + +// BUF_MEM_free frees |buf->data| if needed and then frees |buf| itself. +OPENSSL_EXPORT void BUF_MEM_free(BUF_MEM *buf); + +// BUF_MEM_reserve ensures |buf| has capacity |cap| and allocates memory if +// needed. It returns one on success and zero on error. +OPENSSL_EXPORT int BUF_MEM_reserve(BUF_MEM *buf, size_t cap); + +// BUF_MEM_grow ensures that |buf| has length |len| and allocates memory if +// needed. If the length of |buf| increased, the new bytes are filled with +// zeros. It returns the length of |buf|, or zero if there's an error. +OPENSSL_EXPORT size_t BUF_MEM_grow(BUF_MEM *buf, size_t len); + +// BUF_MEM_grow_clean calls |BUF_MEM_grow|. BoringSSL always zeros memory +// allocated memory on free. +OPENSSL_EXPORT size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len); + +// BUF_MEM_append appends |in| to |buf|. It returns one on success and zero on +// error. +OPENSSL_EXPORT int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len); + + +// Deprecated functions. + +// BUF_strdup calls |OPENSSL_strdup|. +OPENSSL_EXPORT char *BUF_strdup(const char *str); + +// BUF_strnlen calls |OPENSSL_strnlen|. +OPENSSL_EXPORT size_t BUF_strnlen(const char *str, size_t max_len); + +// BUF_strndup calls |OPENSSL_strndup|. +OPENSSL_EXPORT char *BUF_strndup(const char *str, size_t size); + +// BUF_memdup calls |OPENSSL_memdup|. +OPENSSL_EXPORT void *BUF_memdup(const void *data, size_t size); + +// BUF_strlcpy calls |OPENSSL_strlcpy|. +OPENSSL_EXPORT size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size); + +// BUF_strlcat calls |OPENSSL_strlcat|. +OPENSSL_EXPORT size_t BUF_strlcat(char *dst, const char *src, size_t dst_size); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(BUF_MEM, BUF_MEM_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#endif // OPENSSL_HEADER_BUFFER_H diff --git a/lib/boringssl/include/openssl/buffer.h b/lib/boringssl/include/openssl/buffer.h new file mode 100644 index 00000000..c6b721c2 --- /dev/null +++ b/lib/boringssl/include/openssl/buffer.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "buf.h" diff --git a/lib/boringssl/include/openssl/bytestring.h b/lib/boringssl/include/openssl/bytestring.h new file mode 100644 index 00000000..33e13ef8 --- /dev/null +++ b/lib/boringssl/include/openssl/bytestring.h @@ -0,0 +1,656 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_BYTESTRING_H +#define OPENSSL_HEADER_BYTESTRING_H + +#include + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Bytestrings are used for parsing and building TLS and ASN.1 messages. +// +// A "CBS" (CRYPTO ByteString) represents a string of bytes in memory and +// provides utility functions for safely parsing length-prefixed structures +// like TLS and ASN.1 from it. +// +// A "CBB" (CRYPTO ByteBuilder) is a memory buffer that grows as needed and +// provides utility functions for building length-prefixed messages. + + +// CRYPTO ByteString + +struct cbs_st { + const uint8_t *data; + size_t len; + +#if !defined(BORINGSSL_NO_CXX) + // Allow implicit conversions to and from bssl::Span. + cbs_st(bssl::Span span) + : data(span.data()), len(span.size()) {} + operator bssl::Span() const { + return bssl::MakeConstSpan(data, len); + } + + // Defining any constructors requires we explicitly default the others. + cbs_st() = default; + cbs_st(const cbs_st &) = default; + cbs_st &operator=(const cbs_st &) = default; +#endif +}; + +// CBS_init sets |cbs| to point to |data|. It does not take ownership of +// |data|. +OPENSSL_EXPORT void CBS_init(CBS *cbs, const uint8_t *data, size_t len); + +// CBS_skip advances |cbs| by |len| bytes. It returns one on success and zero +// otherwise. +OPENSSL_EXPORT int CBS_skip(CBS *cbs, size_t len); + +// CBS_data returns a pointer to the contents of |cbs|. +OPENSSL_EXPORT const uint8_t *CBS_data(const CBS *cbs); + +// CBS_len returns the number of bytes remaining in |cbs|. +OPENSSL_EXPORT size_t CBS_len(const CBS *cbs); + +// CBS_stow copies the current contents of |cbs| into |*out_ptr| and +// |*out_len|. If |*out_ptr| is not NULL, the contents are freed with +// OPENSSL_free. It returns one on success and zero on allocation failure. On +// success, |*out_ptr| should be freed with OPENSSL_free. If |cbs| is empty, +// |*out_ptr| will be NULL. +OPENSSL_EXPORT int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len); + +// CBS_strdup copies the current contents of |cbs| into |*out_ptr| as a +// NUL-terminated C string. If |*out_ptr| is not NULL, the contents are freed +// with OPENSSL_free. It returns one on success and zero on allocation +// failure. On success, |*out_ptr| should be freed with OPENSSL_free. +// +// NOTE: If |cbs| contains NUL bytes, the string will be truncated. Call +// |CBS_contains_zero_byte(cbs)| to check for NUL bytes. +OPENSSL_EXPORT int CBS_strdup(const CBS *cbs, char **out_ptr); + +// CBS_contains_zero_byte returns one if the current contents of |cbs| contains +// a NUL byte and zero otherwise. +OPENSSL_EXPORT int CBS_contains_zero_byte(const CBS *cbs); + +// CBS_mem_equal compares the current contents of |cbs| with the |len| bytes +// starting at |data|. If they're equal, it returns one, otherwise zero. If the +// lengths match, it uses a constant-time comparison. +OPENSSL_EXPORT int CBS_mem_equal(const CBS *cbs, const uint8_t *data, + size_t len); + +// CBS_get_u8 sets |*out| to the next uint8_t from |cbs| and advances |cbs|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u8(CBS *cbs, uint8_t *out); + +// CBS_get_u16 sets |*out| to the next, big-endian uint16_t from |cbs| and +// advances |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u16(CBS *cbs, uint16_t *out); + +// CBS_get_u16le sets |*out| to the next, little-endian uint16_t from |cbs| and +// advances |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u16le(CBS *cbs, uint16_t *out); + +// CBS_get_u24 sets |*out| to the next, big-endian 24-bit value from |cbs| and +// advances |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u24(CBS *cbs, uint32_t *out); + +// CBS_get_u32 sets |*out| to the next, big-endian uint32_t value from |cbs| +// and advances |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u32(CBS *cbs, uint32_t *out); + +// CBS_get_u32le sets |*out| to the next, little-endian uint32_t value from +// |cbs| and advances |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u32le(CBS *cbs, uint32_t *out); + +// CBS_get_u64 sets |*out| to the next, big-endian uint64_t value from |cbs| +// and advances |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u64(CBS *cbs, uint64_t *out); + +// CBS_get_u64le sets |*out| to the next, little-endian uint64_t value from +// |cbs| and advances |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u64le(CBS *cbs, uint64_t *out); + +// CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens +// |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_last_u8(CBS *cbs, uint8_t *out); + +// CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances +// |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_bytes(CBS *cbs, CBS *out, size_t len); + +// CBS_copy_bytes copies the next |len| bytes from |cbs| to |out| and advances +// |cbs|. It returns one on success and zero on error. +OPENSSL_EXPORT int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len); + +// CBS_get_u8_length_prefixed sets |*out| to the contents of an 8-bit, +// length-prefixed value from |cbs| and advances |cbs| over it. It returns one +// on success and zero on error. +OPENSSL_EXPORT int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out); + +// CBS_get_u16_length_prefixed sets |*out| to the contents of a 16-bit, +// big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It +// returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out); + +// CBS_get_u24_length_prefixed sets |*out| to the contents of a 24-bit, +// big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It +// returns one on success and zero on error. +OPENSSL_EXPORT int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out); + +// CBS_get_until_first finds the first instance of |c| in |cbs|. If found, it +// sets |*out| to the text before the match, advances |cbs| over it, and returns +// one. Otherwise, it returns zero and leaves |cbs| unmodified. +OPENSSL_EXPORT int CBS_get_until_first(CBS *cbs, CBS *out, uint8_t c); + +// CBS_get_u64_decimal reads a decimal integer from |cbs| and writes it to +// |*out|. It stops reading at the end of the string, or the first non-digit +// character. It returns one on success and zero on error. This function behaves +// analogously to |strtoul| except it does not accept empty inputs, leading +// zeros, or negative values. +OPENSSL_EXPORT int CBS_get_u64_decimal(CBS *cbs, uint64_t *out); + + +// Parsing ASN.1 +// +// |CBS| may be used to parse DER structures. Rather than using a schema +// compiler, the following functions act on tag-length-value elements in the +// serialization itself. Thus the caller is responsible for looping over a +// SEQUENCE, branching on CHOICEs or OPTIONAL fields, checking for trailing +// data, and handling explict vs. implicit tagging. +// +// Tags are represented as |CBS_ASN1_TAG| values in memory. The upper few bits +// store the class and constructed bit, and the remaining bits store the tag +// number. Note this differs from the DER serialization, to support tag numbers +// beyond 31. Consumers must use the constants defined below to decompose or +// assemble tags. +// +// This library treats an element's constructed bit as part of its tag. In DER, +// the constructed bit is computable from the type. The constants for universal +// types have the bit set. Callers must set it correctly for tagged types. +// Explicitly-tagged types are always constructed, and implicitly-tagged types +// inherit the underlying type's bit. + +// CBS_ASN1_TAG_SHIFT is how much the in-memory representation shifts the class +// and constructed bits from the DER serialization. +#define CBS_ASN1_TAG_SHIFT 24 + +// CBS_ASN1_CONSTRUCTED may be ORed into a tag to set the constructed bit. +#define CBS_ASN1_CONSTRUCTED (0x20u << CBS_ASN1_TAG_SHIFT) + +// The following values specify the tag class and may be ORed into a tag number +// to produce the final tag. If none is used, the tag will be UNIVERSAL. +#define CBS_ASN1_UNIVERSAL (0u << CBS_ASN1_TAG_SHIFT) +#define CBS_ASN1_APPLICATION (0x40u << CBS_ASN1_TAG_SHIFT) +#define CBS_ASN1_CONTEXT_SPECIFIC (0x80u << CBS_ASN1_TAG_SHIFT) +#define CBS_ASN1_PRIVATE (0xc0u << CBS_ASN1_TAG_SHIFT) + +// CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class. This will +// give one of the four values above. +#define CBS_ASN1_CLASS_MASK (0xc0u << CBS_ASN1_TAG_SHIFT) + +// CBS_ASN1_TAG_NUMBER_MASK may be ANDed with a tag to query its number. +#define CBS_ASN1_TAG_NUMBER_MASK ((1u << (5 + CBS_ASN1_TAG_SHIFT)) - 1) + +// The following values are constants for UNIVERSAL tags. Note these constants +// include the constructed bit. +#define CBS_ASN1_BOOLEAN 0x1u +#define CBS_ASN1_INTEGER 0x2u +#define CBS_ASN1_BITSTRING 0x3u +#define CBS_ASN1_OCTETSTRING 0x4u +#define CBS_ASN1_NULL 0x5u +#define CBS_ASN1_OBJECT 0x6u +#define CBS_ASN1_ENUMERATED 0xau +#define CBS_ASN1_UTF8STRING 0xcu +#define CBS_ASN1_SEQUENCE (0x10u | CBS_ASN1_CONSTRUCTED) +#define CBS_ASN1_SET (0x11u | CBS_ASN1_CONSTRUCTED) +#define CBS_ASN1_NUMERICSTRING 0x12u +#define CBS_ASN1_PRINTABLESTRING 0x13u +#define CBS_ASN1_T61STRING 0x14u +#define CBS_ASN1_VIDEOTEXSTRING 0x15u +#define CBS_ASN1_IA5STRING 0x16u +#define CBS_ASN1_UTCTIME 0x17u +#define CBS_ASN1_GENERALIZEDTIME 0x18u +#define CBS_ASN1_GRAPHICSTRING 0x19u +#define CBS_ASN1_VISIBLESTRING 0x1au +#define CBS_ASN1_GENERALSTRING 0x1bu +#define CBS_ASN1_UNIVERSALSTRING 0x1cu +#define CBS_ASN1_BMPSTRING 0x1eu + +// CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not +// including tag and length bytes) and advances |cbs| over it. The ASN.1 +// element must match |tag_value|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int CBS_get_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value); + +// CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the +// ASN.1 header bytes too. +OPENSSL_EXPORT int CBS_get_asn1_element(CBS *cbs, CBS *out, + CBS_ASN1_TAG tag_value); + +// CBS_peek_asn1_tag looks ahead at the next ASN.1 tag and returns one +// if the next ASN.1 element on |cbs| would have tag |tag_value|. If +// |cbs| is empty or the tag does not match, it returns zero. Note: if +// it returns one, CBS_get_asn1 may still fail if the rest of the +// element is malformed. +OPENSSL_EXPORT int CBS_peek_asn1_tag(const CBS *cbs, CBS_ASN1_TAG tag_value); + +// CBS_get_any_asn1 sets |*out| to contain the next ASN.1 element from |*cbs| +// (not including tag and length bytes), sets |*out_tag| to the tag number, and +// advances |*cbs|. It returns one on success and zero on error. Either of |out| +// and |out_tag| may be NULL to ignore the value. +OPENSSL_EXPORT int CBS_get_any_asn1(CBS *cbs, CBS *out, + CBS_ASN1_TAG *out_tag); + +// CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from +// |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to +// the tag number and |*out_header_len| to the length of the ASN.1 header. Each +// of |out|, |out_tag|, and |out_header_len| may be NULL to ignore the value. +OPENSSL_EXPORT int CBS_get_any_asn1_element(CBS *cbs, CBS *out, + CBS_ASN1_TAG *out_tag, + size_t *out_header_len); + +// CBS_get_any_ber_asn1_element acts the same as |CBS_get_any_asn1_element| but +// also allows indefinite-length elements to be returned and does not enforce +// that lengths are minimal. It sets |*out_indefinite| to one if the length was +// indefinite and zero otherwise. If indefinite, |*out_header_len| and +// |CBS_len(out)| will be equal as only the header is returned (although this is +// also true for empty elements so |*out_indefinite| should be checked). If +// |out_ber_found| is not NULL then it is set to one if any case of invalid DER +// but valid BER is found, and to zero otherwise. +// +// This function will not successfully parse an end-of-contents (EOC) as an +// element. Callers parsing indefinite-length encoding must check for EOC +// separately. +OPENSSL_EXPORT int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, + CBS_ASN1_TAG *out_tag, + size_t *out_header_len, + int *out_ber_found, + int *out_indefinite); + +// CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1| +// and sets |*out| to its value. It returns one on success and zero on error, +// where error includes the integer being negative, or too large to represent +// in 64 bits. +OPENSSL_EXPORT int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out); + +// CBS_get_asn1_int64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1| +// and sets |*out| to its value. It returns one on success and zero on error, +// where error includes the integer being too large to represent in 64 bits. +OPENSSL_EXPORT int CBS_get_asn1_int64(CBS *cbs, int64_t *out); + +// CBS_get_asn1_bool gets an ASN.1 BOOLEAN from |cbs| and sets |*out| to zero +// or one based on its value. It returns one on success or zero on error. +OPENSSL_EXPORT int CBS_get_asn1_bool(CBS *cbs, int *out); + +// CBS_get_optional_asn1 gets an optional explicitly-tagged element from |cbs| +// tagged with |tag| and sets |*out| to its contents, or ignores it if |out| is +// NULL. If present and if |out_present| is not NULL, it sets |*out_present| to +// one, otherwise zero. It returns one on success, whether or not the element +// was present, and zero on decode failure. +OPENSSL_EXPORT int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, + CBS_ASN1_TAG tag); + +// CBS_get_optional_asn1_octet_string gets an optional +// explicitly-tagged OCTET STRING from |cbs|. If present, it sets +// |*out| to the string and |*out_present| to one. Otherwise, it sets +// |*out| to empty and |*out_present| to zero. |out_present| may be +// NULL. It returns one on success, whether or not the element was +// present, and zero on decode failure. +OPENSSL_EXPORT int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, + int *out_present, + CBS_ASN1_TAG tag); + +// CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged +// INTEGER from |cbs|. If present, it sets |*out| to the +// value. Otherwise, it sets |*out| to |default_value|. It returns one +// on success, whether or not the element was present, and zero on +// decode failure. +OPENSSL_EXPORT int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, + CBS_ASN1_TAG tag, + uint64_t default_value); + +// CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from +// |cbs|. If present, it sets |*out| to either zero or one, based on the +// boolean. Otherwise, it sets |*out| to |default_value|. It returns one on +// success, whether or not the element was present, and zero on decode +// failure. +OPENSSL_EXPORT int CBS_get_optional_asn1_bool(CBS *cbs, int *out, + CBS_ASN1_TAG tag, + int default_value); + +// CBS_is_valid_asn1_bitstring returns one if |cbs| is a valid ASN.1 BIT STRING +// body and zero otherwise. +OPENSSL_EXPORT int CBS_is_valid_asn1_bitstring(const CBS *cbs); + +// CBS_asn1_bitstring_has_bit returns one if |cbs| is a valid ASN.1 BIT STRING +// body and the specified bit is present and set. Otherwise, it returns zero. +// |bit| is indexed starting from zero. +OPENSSL_EXPORT int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit); + +// CBS_is_valid_asn1_integer returns one if |cbs| is a valid ASN.1 INTEGER, +// body and zero otherwise. On success, if |out_is_negative| is non-NULL, +// |*out_is_negative| will be set to one if |cbs| is negative and zero +// otherwise. +OPENSSL_EXPORT int CBS_is_valid_asn1_integer(const CBS *cbs, + int *out_is_negative); + +// CBS_is_unsigned_asn1_integer returns one if |cbs| is a valid non-negative +// ASN.1 INTEGER body and zero otherwise. +OPENSSL_EXPORT int CBS_is_unsigned_asn1_integer(const CBS *cbs); + +// CBS_is_valid_asn1_oid returns one if |cbs| is a valid DER-encoded ASN.1 +// OBJECT IDENTIFIER contents (not including the element framing) and zero +// otherwise. This function tolerates arbitrarily large OID components. +OPENSSL_EXPORT int CBS_is_valid_asn1_oid(const CBS *cbs); + +// CBS_asn1_oid_to_text interprets |cbs| as DER-encoded ASN.1 OBJECT IDENTIFIER +// contents (not including the element framing) and returns the ASCII +// representation (e.g., "1.2.840.113554.4.1.72585") in a newly-allocated +// string, or NULL on failure. The caller must release the result with +// |OPENSSL_free|. +// +// This function may fail if |cbs| is an invalid OBJECT IDENTIFIER, or if any +// OID components are too large. +OPENSSL_EXPORT char *CBS_asn1_oid_to_text(const CBS *cbs); + + +// CBS_parse_generalized_time returns one if |cbs| is a valid DER-encoded, ASN.1 +// GeneralizedTime body within the limitations imposed by RFC 5280, or zero +// otherwise. If |allow_timezone_offset| is non-zero, four-digit timezone +// offsets, which would not be allowed by DER, are permitted. On success, if +// |out_tm| is non-NULL, |*out_tm| will be zeroed, and then set to the +// corresponding time in UTC. This function does not compute |out_tm->tm_wday| +// or |out_tm->tm_yday|. +OPENSSL_EXPORT int CBS_parse_generalized_time(const CBS *cbs, struct tm *out_tm, + int allow_timezone_offset); + +// CBS_parse_utc_time returns one if |cbs| is a valid DER-encoded, ASN.1 +// UTCTime body within the limitations imposed by RFC 5280, or zero otherwise. +// If |allow_timezone_offset| is non-zero, four-digit timezone offsets, which +// would not be allowed by DER, are permitted. On success, if |out_tm| is +// non-NULL, |*out_tm| will be zeroed, and then set to the corresponding time +// in UTC. This function does not compute |out_tm->tm_wday| or +// |out_tm->tm_yday|. +OPENSSL_EXPORT int CBS_parse_utc_time(const CBS *cbs, struct tm *out_tm, + int allow_timezone_offset); + +// CRYPTO ByteBuilder. +// +// |CBB| objects allow one to build length-prefixed serialisations. A |CBB| +// object is associated with a buffer and new buffers are created with +// |CBB_init|. Several |CBB| objects can point at the same buffer when a +// length-prefix is pending, however only a single |CBB| can be 'current' at +// any one time. For example, if one calls |CBB_add_u8_length_prefixed| then +// the new |CBB| points at the same buffer as the original. But if the original +// |CBB| is used then the length prefix is written out and the new |CBB| must +// not be used again. +// +// If one needs to force a length prefix to be written out because a |CBB| is +// going out of scope, use |CBB_flush|. If an operation on a |CBB| fails, it is +// in an undefined state and must not be used except to call |CBB_cleanup|. + +struct cbb_buffer_st { + uint8_t *buf; + // len is the number of valid bytes in |buf|. + size_t len; + // cap is the size of |buf|. + size_t cap; + // can_resize is one iff |buf| is owned by this object. If not then |buf| + // cannot be resized. + unsigned can_resize : 1; + // error is one if there was an error writing to this CBB. All future + // operations will fail. + unsigned error : 1; +}; + +struct cbb_child_st { + // base is a pointer to the buffer this |CBB| writes to. + struct cbb_buffer_st *base; + // offset is the number of bytes from the start of |base->buf| to this |CBB|'s + // pending length prefix. + size_t offset; + // pending_len_len contains the number of bytes in this |CBB|'s pending + // length-prefix, or zero if no length-prefix is pending. + uint8_t pending_len_len; + unsigned pending_is_asn1 : 1; +}; + +struct cbb_st { + // child points to a child CBB if a length-prefix is pending. + CBB *child; + // is_child is one if this is a child |CBB| and zero if it is a top-level + // |CBB|. This determines which arm of the union is valid. + char is_child; + union { + struct cbb_buffer_st base; + struct cbb_child_st child; + } u; +}; + +// CBB_zero sets an uninitialised |cbb| to the zero state. It must be +// initialised with |CBB_init| or |CBB_init_fixed| before use, but it is safe to +// call |CBB_cleanup| without a successful |CBB_init|. This may be used for more +// uniform cleanup of a |CBB|. +OPENSSL_EXPORT void CBB_zero(CBB *cbb); + +// CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as +// needed, the |initial_capacity| is just a hint. It returns one on success or +// zero on allocation failure. +OPENSSL_EXPORT int CBB_init(CBB *cbb, size_t initial_capacity); + +// CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since +// |buf| cannot grow, trying to write more than |len| bytes will cause CBB +// functions to fail. This function is infallible and always returns one. It is +// safe, but not necessary, to call |CBB_cleanup| on |cbb|. +OPENSSL_EXPORT int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len); + +// CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects +// writing to the same buffer. This should be used in an error case where a +// serialisation is abandoned. +// +// This function can only be called on a "top level" |CBB|, i.e. one initialised +// with |CBB_init| or |CBB_init_fixed|, or a |CBB| set to the zero state with +// |CBB_zero|. +OPENSSL_EXPORT void CBB_cleanup(CBB *cbb); + +// CBB_finish completes any pending length prefix and sets |*out_data| to a +// malloced buffer and |*out_len| to the length of that buffer. The caller +// takes ownership of the buffer and, unless the buffer was fixed with +// |CBB_init_fixed|, must call |OPENSSL_free| when done. +// +// It can only be called on a "top level" |CBB|, i.e. one initialised with +// |CBB_init| or |CBB_init_fixed|. It returns one on success and zero on +// error. +OPENSSL_EXPORT int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len); + +// CBB_flush causes any pending length prefixes to be written out and any child +// |CBB| objects of |cbb| to be invalidated. This allows |cbb| to continue to be +// used after the children go out of scope, e.g. when local |CBB| objects are +// added as children to a |CBB| that persists after a function returns. This +// function returns one on success or zero on error. +OPENSSL_EXPORT int CBB_flush(CBB *cbb); + +// CBB_data returns a pointer to the bytes written to |cbb|. It does not flush +// |cbb|. The pointer is valid until the next operation to |cbb|. +// +// To avoid unfinalized length prefixes, it is a fatal error to call this on a +// CBB with any active children. +OPENSSL_EXPORT const uint8_t *CBB_data(const CBB *cbb); + +// CBB_len returns the number of bytes written to |cbb|. It does not flush +// |cbb|. +// +// To avoid unfinalized length prefixes, it is a fatal error to call this on a +// CBB with any active children. +OPENSSL_EXPORT size_t CBB_len(const CBB *cbb); + +// CBB_add_u8_length_prefixed sets |*out_contents| to a new child of |cbb|. The +// data written to |*out_contents| will be prefixed in |cbb| with an 8-bit +// length. It returns one on success or zero on error. +OPENSSL_EXPORT int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents); + +// CBB_add_u16_length_prefixed sets |*out_contents| to a new child of |cbb|. +// The data written to |*out_contents| will be prefixed in |cbb| with a 16-bit, +// big-endian length. It returns one on success or zero on error. +OPENSSL_EXPORT int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents); + +// CBB_add_u24_length_prefixed sets |*out_contents| to a new child of |cbb|. +// The data written to |*out_contents| will be prefixed in |cbb| with a 24-bit, +// big-endian length. It returns one on success or zero on error. +OPENSSL_EXPORT int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents); + +// CBB_add_asn1 sets |*out_contents| to a |CBB| into which the contents of an +// ASN.1 object can be written. The |tag| argument will be used as the tag for +// the object. It returns one on success or zero on error. +OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, CBS_ASN1_TAG tag); + +// CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on +// success and zero otherwise. +OPENSSL_EXPORT int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len); + +// CBB_add_zeros append |len| bytes with value zero to |cbb|. It returns one on +// success and zero otherwise. +OPENSSL_EXPORT int CBB_add_zeros(CBB *cbb, size_t len); + +// CBB_add_space appends |len| bytes to |cbb| and sets |*out_data| to point to +// the beginning of that space. The caller must then write |len| bytes of +// actual contents to |*out_data|. It returns one on success and zero +// otherwise. +OPENSSL_EXPORT int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len); + +// CBB_reserve ensures |cbb| has room for |len| additional bytes and sets +// |*out_data| to point to the beginning of that space. It returns one on +// success and zero otherwise. The caller may write up to |len| bytes to +// |*out_data| and call |CBB_did_write| to complete the write. |*out_data| is +// valid until the next operation on |cbb| or an ancestor |CBB|. +OPENSSL_EXPORT int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len); + +// CBB_did_write advances |cbb| by |len| bytes, assuming the space has been +// written to by the caller. It returns one on success and zero on error. +OPENSSL_EXPORT int CBB_did_write(CBB *cbb, size_t len); + +// CBB_add_u8 appends an 8-bit number from |value| to |cbb|. It returns one on +// success and zero otherwise. +OPENSSL_EXPORT int CBB_add_u8(CBB *cbb, uint8_t value); + +// CBB_add_u16 appends a 16-bit, big-endian number from |value| to |cbb|. It +// returns one on success and zero otherwise. +OPENSSL_EXPORT int CBB_add_u16(CBB *cbb, uint16_t value); + +// CBB_add_u16le appends a 16-bit, little-endian number from |value| to |cbb|. +// It returns one on success and zero otherwise. +OPENSSL_EXPORT int CBB_add_u16le(CBB *cbb, uint16_t value); + +// CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It +// returns one on success and zero otherwise. +OPENSSL_EXPORT int CBB_add_u24(CBB *cbb, uint32_t value); + +// CBB_add_u32 appends a 32-bit, big-endian number from |value| to |cbb|. It +// returns one on success and zero otherwise. +OPENSSL_EXPORT int CBB_add_u32(CBB *cbb, uint32_t value); + +// CBB_add_u32le appends a 32-bit, little-endian number from |value| to |cbb|. +// It returns one on success and zero otherwise. +OPENSSL_EXPORT int CBB_add_u32le(CBB *cbb, uint32_t value); + +// CBB_add_u64 appends a 64-bit, big-endian number from |value| to |cbb|. It +// returns one on success and zero otherwise. +OPENSSL_EXPORT int CBB_add_u64(CBB *cbb, uint64_t value); + +// CBB_add_u64le appends a 64-bit, little-endian number from |value| to |cbb|. +// It returns one on success and zero otherwise. +OPENSSL_EXPORT int CBB_add_u64le(CBB *cbb, uint64_t value); + +// CBB_discard_child discards the current unflushed child of |cbb|. Neither the +// child's contents nor the length prefix will be included in the output. +OPENSSL_EXPORT void CBB_discard_child(CBB *cbb); + +// CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1| +// and writes |value| in its contents. It returns one on success and zero on +// error. +OPENSSL_EXPORT int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); + +// CBB_add_asn1_uint64_with_tag behaves like |CBB_add_asn1_uint64| but uses +// |tag| as the tag instead of INTEGER. This is useful if the INTEGER type uses +// implicit tagging. +OPENSSL_EXPORT int CBB_add_asn1_uint64_with_tag(CBB *cbb, uint64_t value, + CBS_ASN1_TAG tag); + +// CBB_add_asn1_int64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1| +// and writes |value| in its contents. It returns one on success and zero on +// error. +OPENSSL_EXPORT int CBB_add_asn1_int64(CBB *cbb, int64_t value); + +// CBB_add_asn1_int64_with_tag behaves like |CBB_add_asn1_int64| but uses |tag| +// as the tag instead of INTEGER. This is useful if the INTEGER type uses +// implicit tagging. +OPENSSL_EXPORT int CBB_add_asn1_int64_with_tag(CBB *cbb, int64_t value, + CBS_ASN1_TAG tag); + +// CBB_add_asn1_octet_string writes an ASN.1 OCTET STRING into |cbb| with the +// given contents. It returns one on success and zero on error. +OPENSSL_EXPORT int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, + size_t data_len); + +// CBB_add_asn1_bool writes an ASN.1 BOOLEAN into |cbb| which is true iff +// |value| is non-zero. It returns one on success and zero on error. +OPENSSL_EXPORT int CBB_add_asn1_bool(CBB *cbb, int value); + +// CBB_add_asn1_oid_from_text decodes |len| bytes from |text| as an ASCII OID +// representation, e.g. "1.2.840.113554.4.1.72585", and writes the DER-encoded +// contents to |cbb|. It returns one on success and zero on malloc failure or if +// |text| was invalid. It does not include the OBJECT IDENTIFER framing, only +// the element's contents. +// +// This function considers OID strings with components which do not fit in a +// |uint64_t| to be invalid. +OPENSSL_EXPORT int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, + size_t len); + +// CBB_flush_asn1_set_of calls |CBB_flush| on |cbb| and then reorders the +// contents for a DER-encoded ASN.1 SET OF type. It returns one on success and +// zero on failure. DER canonicalizes SET OF contents by sorting +// lexicographically by encoding. Call this function when encoding a SET OF +// type in an order that is not already known to be canonical. +// +// Note a SET type has a slightly different ordering than a SET OF. +OPENSSL_EXPORT int CBB_flush_asn1_set_of(CBB *cbb); + + +#if defined(__cplusplus) +} // extern C + + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +using ScopedCBB = internal::StackAllocated; + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#endif + +#endif // OPENSSL_HEADER_BYTESTRING_H diff --git a/lib/boringssl/include/openssl/cast.h b/lib/boringssl/include/openssl/cast.h new file mode 100644 index 00000000..1a0f82dd --- /dev/null +++ b/lib/boringssl/include/openssl/cast.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_CAST_H +#define OPENSSL_HEADER_CAST_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define CAST_ENCRYPT 1 +#define CAST_DECRYPT 0 + +#define CAST_BLOCK 8 +#define CAST_KEY_LENGTH 16 + +typedef struct cast_key_st { + uint32_t data[32]; + int short_key; // Use reduced rounds for short key +} CAST_KEY; + +OPENSSL_EXPORT void CAST_set_key(CAST_KEY *key, size_t len, + const uint8_t *data); +OPENSSL_EXPORT void CAST_ecb_encrypt(const uint8_t *in, uint8_t *out, + const CAST_KEY *key, int enc); +OPENSSL_EXPORT void CAST_encrypt(uint32_t *data, const CAST_KEY *key); +OPENSSL_EXPORT void CAST_decrypt(uint32_t *data, const CAST_KEY *key); +OPENSSL_EXPORT void CAST_cbc_encrypt(const uint8_t *in, uint8_t *out, + size_t length, const CAST_KEY *ks, + uint8_t *iv, int enc); + +OPENSSL_EXPORT void CAST_cfb64_encrypt(const uint8_t *in, uint8_t *out, + size_t length, const CAST_KEY *schedule, + uint8_t *ivec, int *num, int enc); + +#ifdef __cplusplus +} +#endif + +#endif // OPENSSL_HEADER_CAST_H diff --git a/lib/boringssl/include/openssl/chacha.h b/lib/boringssl/include/openssl/chacha.h new file mode 100644 index 00000000..cfbaa756 --- /dev/null +++ b/lib/boringssl/include/openssl/chacha.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CHACHA_H +#define OPENSSL_HEADER_CHACHA_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +// ChaCha20. +// +// ChaCha20 is a stream cipher. See https://tools.ietf.org/html/rfc8439. + + +// CRYPTO_chacha_20 encrypts |in_len| bytes from |in| with the given key and +// nonce and writes the result to |out|. If |in| and |out| alias, they must be +// equal. The initial block counter is specified by |counter|. +OPENSSL_EXPORT void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, + size_t in_len, const uint8_t key[32], + const uint8_t nonce[12], uint32_t counter); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_CHACHA_H diff --git a/lib/boringssl/include/openssl/cipher.h b/lib/boringssl/include/openssl/cipher.h new file mode 100644 index 00000000..310d7c23 --- /dev/null +++ b/lib/boringssl/include/openssl/cipher.h @@ -0,0 +1,662 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_CIPHER_H +#define OPENSSL_HEADER_CIPHER_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Ciphers. + + +// Cipher primitives. +// +// The following functions return |EVP_CIPHER| objects that implement the named +// cipher algorithm. + +OPENSSL_EXPORT const EVP_CIPHER *EVP_rc4(void); + +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ecb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_cbc(void); + +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ecb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ctr(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ofb(void); + +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ecb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ctr(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ofb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_xts(void); + +// EVP_enc_null returns a 'cipher' that passes plaintext through as +// ciphertext. +OPENSSL_EXPORT const EVP_CIPHER *EVP_enc_null(void); + +// EVP_rc2_cbc returns a cipher that implements 128-bit RC2 in CBC mode. +OPENSSL_EXPORT const EVP_CIPHER *EVP_rc2_cbc(void); + +// EVP_rc2_40_cbc returns a cipher that implements 40-bit RC2 in CBC mode. This +// is obviously very, very weak and is included only in order to read PKCS#12 +// files, which often encrypt the certificate chain using this cipher. It is +// deliberately not exported. +const EVP_CIPHER *EVP_rc2_40_cbc(void); + +// EVP_get_cipherbynid returns the cipher corresponding to the given NID, or +// NULL if no such cipher is known. Note using this function links almost every +// cipher implemented by BoringSSL into the binary, whether the caller uses them +// or not. Size-conscious callers, such as client software, should not use this +// function. +OPENSSL_EXPORT const EVP_CIPHER *EVP_get_cipherbynid(int nid); + + +// Cipher context allocation. +// +// An |EVP_CIPHER_CTX| represents the state of an encryption or decryption in +// progress. + +// EVP_CIPHER_CTX_init initialises an, already allocated, |EVP_CIPHER_CTX|. +OPENSSL_EXPORT void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_new allocates a fresh |EVP_CIPHER_CTX|, calls +// |EVP_CIPHER_CTX_init| and returns it, or NULL on allocation failure. +OPENSSL_EXPORT EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); + +// EVP_CIPHER_CTX_cleanup frees any memory referenced by |ctx|. It returns +// one. +OPENSSL_EXPORT int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_free calls |EVP_CIPHER_CTX_cleanup| on |ctx| and then frees +// |ctx| itself. +OPENSSL_EXPORT void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_copy sets |out| to be a duplicate of the current state of +// |in|. The |out| argument must have been previously initialised. +OPENSSL_EXPORT int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, + const EVP_CIPHER_CTX *in); + +// EVP_CIPHER_CTX_reset calls |EVP_CIPHER_CTX_cleanup| followed by +// |EVP_CIPHER_CTX_init| and returns one. +OPENSSL_EXPORT int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx); + + +// Cipher context configuration. + +// EVP_CipherInit_ex configures |ctx| for a fresh encryption (or decryption, if +// |enc| is zero) operation using |cipher|. If |ctx| has been previously +// configured with a cipher then |cipher|, |key| and |iv| may be |NULL| and +// |enc| may be -1 to reuse the previous values. The operation will use |key| +// as the key and |iv| as the IV (if any). These should have the correct +// lengths given by |EVP_CIPHER_key_length| and |EVP_CIPHER_iv_length|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *engine, + const uint8_t *key, const uint8_t *iv, + int enc); + +// EVP_EncryptInit_ex calls |EVP_CipherInit_ex| with |enc| equal to one. +OPENSSL_EXPORT int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const uint8_t *key, const uint8_t *iv); + +// EVP_DecryptInit_ex calls |EVP_CipherInit_ex| with |enc| equal to zero. +OPENSSL_EXPORT int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const uint8_t *key, const uint8_t *iv); + + +// Cipher operations. + +// EVP_EncryptUpdate encrypts |in_len| bytes from |in| to |out|. The number +// of output bytes may be up to |in_len| plus the block length minus one and +// |out| must have sufficient space. The number of bytes actually output is +// written to |*out_len|. It returns one on success and zero otherwise. +// +// If |ctx| is an AEAD cipher, e.g. |EVP_aes_128_gcm|, and |out| is NULL, this +// function instead adds |in_len| bytes from |in| to the AAD and sets |*out_len| +// to |in_len|. The AAD must be fully specified in this way before this function +// is used to encrypt plaintext. +OPENSSL_EXPORT int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + int in_len); + +// EVP_EncryptFinal_ex writes at most a block of ciphertext to |out| and sets +// |*out_len| to the number of bytes written. If padding is enabled (the +// default) then standard padding is applied to create the final block. If +// padding is disabled (with |EVP_CIPHER_CTX_set_padding|) then any partial +// block remaining will cause an error. The function returns one on success and +// zero otherwise. +OPENSSL_EXPORT int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len); + +// EVP_DecryptUpdate decrypts |in_len| bytes from |in| to |out|. The number of +// output bytes may be up to |in_len| plus the block length minus one and |out| +// must have sufficient space. The number of bytes actually output is written +// to |*out_len|. It returns one on success and zero otherwise. +// +// If |ctx| is an AEAD cipher, e.g. |EVP_aes_128_gcm|, and |out| is NULL, this +// function instead adds |in_len| bytes from |in| to the AAD and sets |*out_len| +// to |in_len|. The AAD must be fully specified in this way before this function +// is used to decrypt ciphertext. +OPENSSL_EXPORT int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + int in_len); + +// EVP_DecryptFinal_ex writes at most a block of ciphertext to |out| and sets +// |*out_len| to the number of bytes written. If padding is enabled (the +// default) then padding is removed from the final block. +// +// WARNING: it is unsafe to call this function with unauthenticated +// ciphertext if padding is enabled. +OPENSSL_EXPORT int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len); + +// EVP_CipherUpdate calls either |EVP_EncryptUpdate| or |EVP_DecryptUpdate| +// depending on how |ctx| has been setup. +OPENSSL_EXPORT int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + int in_len); + +// EVP_CipherFinal_ex calls either |EVP_EncryptFinal_ex| or +// |EVP_DecryptFinal_ex| depending on how |ctx| has been setup. +OPENSSL_EXPORT int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len); + + +// Cipher context accessors. + +// EVP_CIPHER_CTX_cipher returns the |EVP_CIPHER| underlying |ctx|, or NULL if +// none has been set. +OPENSSL_EXPORT const EVP_CIPHER *EVP_CIPHER_CTX_cipher( + const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_nid returns a NID identifying the |EVP_CIPHER| underlying +// |ctx| (e.g. |NID_aes_128_gcm|). It will crash if no cipher has been +// configured. +OPENSSL_EXPORT int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_encrypting returns one if |ctx| is configured for encryption +// and zero otherwise. +OPENSSL_EXPORT int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_block_size returns the block size, in bytes, of the cipher +// underlying |ctx|, or one if the cipher is a stream cipher. It will crash if +// no cipher has been configured. +OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_key_length returns the key size, in bytes, of the cipher +// underlying |ctx| or zero if no cipher has been configured. +OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_iv_length returns the IV size, in bytes, of the cipher +// underlying |ctx|. It will crash if no cipher has been configured. +OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_get_app_data returns the opaque, application data pointer for +// |ctx|, or NULL if none has been set. +OPENSSL_EXPORT void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_set_app_data sets the opaque, application data pointer for +// |ctx| to |data|. +OPENSSL_EXPORT void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, + void *data); + +// EVP_CIPHER_CTX_flags returns a value which is the OR of zero or more +// |EVP_CIPH_*| flags. It will crash if no cipher has been configured. +OPENSSL_EXPORT uint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_mode returns one of the |EVP_CIPH_*| cipher mode values +// enumerated below. It will crash if no cipher has been configured. +OPENSSL_EXPORT uint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx); + +// EVP_CIPHER_CTX_ctrl is an |ioctl| like function. The |command| argument +// should be one of the |EVP_CTRL_*| values. The |arg| and |ptr| arguments are +// specific to the command in question. +OPENSSL_EXPORT int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command, + int arg, void *ptr); + +// EVP_CIPHER_CTX_set_padding sets whether padding is enabled for |ctx| and +// returns one. Pass a non-zero |pad| to enable padding (the default) or zero +// to disable. +OPENSSL_EXPORT int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad); + +// EVP_CIPHER_CTX_set_key_length sets the key length for |ctx|. This is only +// valid for ciphers that can take a variable length key. It returns one on +// success and zero on error. +OPENSSL_EXPORT int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *ctx, + unsigned key_len); + + +// Cipher accessors. + +// EVP_CIPHER_nid returns a NID identifying |cipher|. (For example, +// |NID_aes_128_gcm|.) +OPENSSL_EXPORT int EVP_CIPHER_nid(const EVP_CIPHER *cipher); + +// EVP_CIPHER_block_size returns the block size, in bytes, for |cipher|, or one +// if |cipher| is a stream cipher. +OPENSSL_EXPORT unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher); + +// EVP_CIPHER_key_length returns the key size, in bytes, for |cipher|. If +// |cipher| can take a variable key length then this function returns the +// default key length and |EVP_CIPHER_flags| will return a value with +// |EVP_CIPH_VARIABLE_LENGTH| set. +OPENSSL_EXPORT unsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher); + +// EVP_CIPHER_iv_length returns the IV size, in bytes, of |cipher|, or zero if +// |cipher| doesn't take an IV. +OPENSSL_EXPORT unsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher); + +// EVP_CIPHER_flags returns a value which is the OR of zero or more +// |EVP_CIPH_*| flags. +OPENSSL_EXPORT uint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher); + +// EVP_CIPHER_mode returns one of the cipher mode values enumerated below. +OPENSSL_EXPORT uint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher); + + +// Key derivation. + +// EVP_BytesToKey generates a key and IV for the cipher |type| by iterating +// |md| |count| times using |data| and |salt|. On entry, the |key| and |iv| +// buffers must have enough space to hold a key and IV for |type|. It returns +// the length of the key on success or zero on error. +OPENSSL_EXPORT int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const uint8_t *salt, const uint8_t *data, + size_t data_len, unsigned count, uint8_t *key, + uint8_t *iv); + + +// Cipher modes (for |EVP_CIPHER_mode|). + +#define EVP_CIPH_STREAM_CIPHER 0x0 +#define EVP_CIPH_ECB_MODE 0x1 +#define EVP_CIPH_CBC_MODE 0x2 +#define EVP_CIPH_CFB_MODE 0x3 +#define EVP_CIPH_OFB_MODE 0x4 +#define EVP_CIPH_CTR_MODE 0x5 +#define EVP_CIPH_GCM_MODE 0x6 +#define EVP_CIPH_XTS_MODE 0x7 + +// The following values are never returned from |EVP_CIPHER_mode| and are +// included only to make it easier to compile code with BoringSSL. +#define EVP_CIPH_CCM_MODE 0x8 +#define EVP_CIPH_OCB_MODE 0x9 +#define EVP_CIPH_WRAP_MODE 0xa + + +// Cipher flags (for |EVP_CIPHER_flags|). + +// EVP_CIPH_VARIABLE_LENGTH indicates that the cipher takes a variable length +// key. +#define EVP_CIPH_VARIABLE_LENGTH 0x40 + +// EVP_CIPH_ALWAYS_CALL_INIT indicates that the |init| function for the cipher +// should always be called when initialising a new operation, even if the key +// is NULL to indicate that the same key is being used. +#define EVP_CIPH_ALWAYS_CALL_INIT 0x80 + +// EVP_CIPH_CUSTOM_IV indicates that the cipher manages the IV itself rather +// than keeping it in the |iv| member of |EVP_CIPHER_CTX|. +#define EVP_CIPH_CUSTOM_IV 0x100 + +// EVP_CIPH_CTRL_INIT indicates that EVP_CTRL_INIT should be used when +// initialising an |EVP_CIPHER_CTX|. +#define EVP_CIPH_CTRL_INIT 0x200 + +// EVP_CIPH_FLAG_CUSTOM_CIPHER indicates that the cipher manages blocking +// itself. This causes EVP_(En|De)crypt_ex to be simple wrapper functions. +#define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x400 + +// EVP_CIPH_FLAG_AEAD_CIPHER specifies that the cipher is an AEAD. This is an +// older version of the proper AEAD interface. See aead.h for the current +// one. +#define EVP_CIPH_FLAG_AEAD_CIPHER 0x800 + +// EVP_CIPH_CUSTOM_COPY indicates that the |ctrl| callback should be called +// with |EVP_CTRL_COPY| at the end of normal |EVP_CIPHER_CTX_copy| +// processing. +#define EVP_CIPH_CUSTOM_COPY 0x1000 + +// EVP_CIPH_FLAG_NON_FIPS_ALLOW is meaningless. In OpenSSL it permits non-FIPS +// algorithms in FIPS mode. But BoringSSL FIPS mode doesn't prohibit algorithms +// (it's up the the caller to use the FIPS module in a fashion compliant with +// their needs). Thus this exists only to allow code to compile. +#define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0 + + +// Deprecated functions + +// EVP_CipherInit acts like EVP_CipherInit_ex except that |EVP_CIPHER_CTX_init| +// is called on |cipher| first, if |cipher| is not NULL. +OPENSSL_EXPORT int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const uint8_t *key, const uint8_t *iv, + int enc); + +// EVP_EncryptInit calls |EVP_CipherInit| with |enc| equal to one. +OPENSSL_EXPORT int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, const uint8_t *key, + const uint8_t *iv); + +// EVP_DecryptInit calls |EVP_CipherInit| with |enc| equal to zero. +OPENSSL_EXPORT int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, const uint8_t *key, + const uint8_t *iv); + +// EVP_CipherFinal calls |EVP_CipherFinal_ex|. +OPENSSL_EXPORT int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len); + +// EVP_EncryptFinal calls |EVP_EncryptFinal_ex|. +OPENSSL_EXPORT int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len); + +// EVP_DecryptFinal calls |EVP_DecryptFinal_ex|. +OPENSSL_EXPORT int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len); + +// EVP_Cipher historically exposed an internal implementation detail of |ctx| +// and should not be used. Use |EVP_CipherUpdate| and |EVP_CipherFinal_ex| +// instead. +// +// If |ctx|'s cipher does not have the |EVP_CIPH_FLAG_CUSTOM_CIPHER| flag, it +// encrypts or decrypts |in_len| bytes from |in| and writes the resulting +// |in_len| bytes to |out|. It returns one on success and zero on error. +// |in_len| must be a multiple of the cipher's block size, or the behavior is +// undefined. +// +// TODO(davidben): Rather than being undefined (it'll often round the length up +// and likely read past the buffer), just fail the operation. +// +// If |ctx|'s cipher has the |EVP_CIPH_FLAG_CUSTOM_CIPHER| flag, it runs in one +// of two modes: If |in| is non-NULL, it behaves like |EVP_CipherUpdate|. If +// |in| is NULL, it behaves like |EVP_CipherFinal_ex|. In both cases, it returns +// |*out_len| on success and -1 on error. +// +// WARNING: The two possible calling conventions of this function signal errors +// incompatibly. In the first, zero indicates an error. In the second, zero +// indicates success with zero bytes of output. +OPENSSL_EXPORT int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t in_len); + +// EVP_add_cipher_alias does nothing and returns one. +OPENSSL_EXPORT int EVP_add_cipher_alias(const char *a, const char *b); + +// EVP_get_cipherbyname returns an |EVP_CIPHER| given a human readable name in +// |name|, or NULL if the name is unknown. Note using this function links almost +// every cipher implemented by BoringSSL into the binary, not just the ones the +// caller requests. Size-conscious callers, such as client software, should not +// use this function. +OPENSSL_EXPORT const EVP_CIPHER *EVP_get_cipherbyname(const char *name); + +// These AEADs are deprecated AES-GCM implementations that set +// |EVP_CIPH_FLAG_CUSTOM_CIPHER|. Use |EVP_aead_aes_128_gcm| and +// |EVP_aead_aes_256_gcm| instead. +// +// WARNING: Although these APIs allow streaming an individual AES-GCM operation, +// this is not secure. Until calling |EVP_DecryptFinal_ex|, the tag has not yet +// been checked and output released by |EVP_DecryptUpdate| is unauthenticated +// and easily manipulated by attackers. Callers must buffer the output and may +// not act on it until the entire operation is complete. +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_gcm(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_gcm(void); + +// These are deprecated, 192-bit version of AES. +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_ecb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_ctr(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_gcm(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_ofb(void); + +// EVP_des_ede3_ecb is an alias for |EVP_des_ede3|. Use the former instead. +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void); + +// EVP_aes_128_cfb128 is only available in decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cfb128(void); + +// EVP_aes_128_cfb is an alias for |EVP_aes_128_cfb128| and is only available in +// decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cfb(void); + +// EVP_aes_192_cfb128 is only available in decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_cfb128(void); + +// EVP_aes_192_cfb is an alias for |EVP_aes_192_cfb128| and is only available in +// decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_cfb(void); + +// EVP_aes_256_cfb128 is only available in decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_cfb128(void); + +// EVP_aes_256_cfb is an alias for |EVP_aes_256_cfb128| and is only available in +// decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_cfb(void); + +// EVP_bf_ecb is Blowfish in ECB mode and is only available in decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_bf_ecb(void); + +// EVP_bf_cbc is Blowfish in CBC mode and is only available in decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_bf_cbc(void); + +// EVP_bf_cfb is Blowfish in 64-bit CFB mode and is only available in decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_bf_cfb(void); + +// EVP_cast5_ecb is CAST5 in ECB mode and is only available in decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_cast5_ecb(void); + +// EVP_cast5_cbc is CAST5 in CBC mode and is only available in decrepit. +OPENSSL_EXPORT const EVP_CIPHER *EVP_cast5_cbc(void); + +// The following flags do nothing and are included only to make it easier to +// compile code with BoringSSL. +#define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0 + +// EVP_CIPHER_CTX_set_flags does nothing. +OPENSSL_EXPORT void EVP_CIPHER_CTX_set_flags(const EVP_CIPHER_CTX *ctx, + uint32_t flags); + + +// Private functions. + +// EVP_CIPH_NO_PADDING disables padding in block ciphers. +#define EVP_CIPH_NO_PADDING 0x800 + +// The following are |EVP_CIPHER_CTX_ctrl| commands. +#define EVP_CTRL_INIT 0x0 +#define EVP_CTRL_SET_KEY_LENGTH 0x1 +#define EVP_CTRL_GET_RC2_KEY_BITS 0x2 +#define EVP_CTRL_SET_RC2_KEY_BITS 0x3 +#define EVP_CTRL_GET_RC5_ROUNDS 0x4 +#define EVP_CTRL_SET_RC5_ROUNDS 0x5 +#define EVP_CTRL_RAND_KEY 0x6 +#define EVP_CTRL_PBE_PRF_NID 0x7 +#define EVP_CTRL_COPY 0x8 +#define EVP_CTRL_AEAD_SET_IVLEN 0x9 +#define EVP_CTRL_AEAD_GET_TAG 0x10 +#define EVP_CTRL_AEAD_SET_TAG 0x11 +#define EVP_CTRL_AEAD_SET_IV_FIXED 0x12 +#define EVP_CTRL_GCM_IV_GEN 0x13 +#define EVP_CTRL_AEAD_SET_MAC_KEY 0x17 +// EVP_CTRL_GCM_SET_IV_INV sets the GCM invocation field, decrypt only +#define EVP_CTRL_GCM_SET_IV_INV 0x18 + +// The following constants are unused. +#define EVP_GCM_TLS_FIXED_IV_LEN 4 +#define EVP_GCM_TLS_EXPLICIT_IV_LEN 8 +#define EVP_GCM_TLS_TAG_LEN 16 + +// The following are legacy aliases for AEAD |EVP_CIPHER_CTX_ctrl| values. +#define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +#define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +#define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG +#define EVP_CTRL_GCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED + +#define EVP_MAX_KEY_LENGTH 64 +#define EVP_MAX_IV_LENGTH 16 +#define EVP_MAX_BLOCK_LENGTH 32 + +struct evp_cipher_ctx_st { + // cipher contains the underlying cipher for this context. + const EVP_CIPHER *cipher; + + // app_data is a pointer to opaque, user data. + void *app_data; // application stuff + + // cipher_data points to the |cipher| specific state. + void *cipher_data; + + // key_len contains the length of the key, which may differ from + // |cipher->key_len| if the cipher can take a variable key length. + unsigned key_len; + + // encrypt is one if encrypting and zero if decrypting. + int encrypt; + + // flags contains the OR of zero or more |EVP_CIPH_*| flags, above. + uint32_t flags; + + // oiv contains the original IV value. + uint8_t oiv[EVP_MAX_IV_LENGTH]; + + // iv contains the current IV value, which may have been updated. + uint8_t iv[EVP_MAX_IV_LENGTH]; + + // buf contains a partial block which is used by, for example, CTR mode to + // store unused keystream bytes. + uint8_t buf[EVP_MAX_BLOCK_LENGTH]; + + // buf_len contains the number of bytes of a partial block contained in + // |buf|. + int buf_len; + + // num contains the number of bytes of |iv| which are valid for modes that + // manage partial blocks themselves. + unsigned num; + + // final_used is non-zero if the |final| buffer contains plaintext. + int final_used; + + uint8_t final[EVP_MAX_BLOCK_LENGTH]; // possible final block + + // Has this structure been rendered unusable by a failure. + int poisoned; +} /* EVP_CIPHER_CTX */; + +typedef struct evp_cipher_info_st { + const EVP_CIPHER *cipher; + unsigned char iv[EVP_MAX_IV_LENGTH]; +} EVP_CIPHER_INFO; + + +#if defined(__cplusplus) +} // extern C + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(EVP_CIPHER_CTX, EVP_CIPHER_CTX_free) + +using ScopedEVP_CIPHER_CTX = + internal::StackAllocated; + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#endif + +#define CIPHER_R_AES_KEY_SETUP_FAILED 100 +#define CIPHER_R_BAD_DECRYPT 101 +#define CIPHER_R_BAD_KEY_LENGTH 102 +#define CIPHER_R_BUFFER_TOO_SMALL 103 +#define CIPHER_R_CTRL_NOT_IMPLEMENTED 104 +#define CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED 105 +#define CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 106 +#define CIPHER_R_INITIALIZATION_ERROR 107 +#define CIPHER_R_INPUT_NOT_INITIALIZED 108 +#define CIPHER_R_INVALID_AD_SIZE 109 +#define CIPHER_R_INVALID_KEY_LENGTH 110 +#define CIPHER_R_INVALID_NONCE_SIZE 111 +#define CIPHER_R_INVALID_OPERATION 112 +#define CIPHER_R_IV_TOO_LARGE 113 +#define CIPHER_R_NO_CIPHER_SET 114 +#define CIPHER_R_OUTPUT_ALIASES_INPUT 115 +#define CIPHER_R_TAG_TOO_LARGE 116 +#define CIPHER_R_TOO_LARGE 117 +#define CIPHER_R_UNSUPPORTED_AD_SIZE 118 +#define CIPHER_R_UNSUPPORTED_INPUT_SIZE 119 +#define CIPHER_R_UNSUPPORTED_KEY_SIZE 120 +#define CIPHER_R_UNSUPPORTED_NONCE_SIZE 121 +#define CIPHER_R_UNSUPPORTED_TAG_SIZE 122 +#define CIPHER_R_WRONG_FINAL_BLOCK_LENGTH 123 +#define CIPHER_R_NO_DIRECTION_SET 124 +#define CIPHER_R_INVALID_NONCE 125 + +#endif // OPENSSL_HEADER_CIPHER_H diff --git a/lib/boringssl/include/openssl/cmac.h b/lib/boringssl/include/openssl/cmac.h new file mode 100644 index 00000000..3e8cf929 --- /dev/null +++ b/lib/boringssl/include/openssl/cmac.h @@ -0,0 +1,91 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CMAC_H +#define OPENSSL_HEADER_CMAC_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// CMAC. +// +// CMAC is a MAC based on AES-CBC and defined in +// https://tools.ietf.org/html/rfc4493#section-2.3. + + +// One-shot functions. + +// AES_CMAC calculates the 16-byte, CMAC authenticator of |in_len| bytes of +// |in| and writes it to |out|. The |key_len| may be 16 or 32 bytes to select +// between AES-128 and AES-256. It returns one on success or zero on error. +OPENSSL_EXPORT int AES_CMAC(uint8_t out[16], const uint8_t *key, size_t key_len, + const uint8_t *in, size_t in_len); + + +// Incremental interface. + +// CMAC_CTX_new allocates a fresh |CMAC_CTX| and returns it, or NULL on +// error. +OPENSSL_EXPORT CMAC_CTX *CMAC_CTX_new(void); + +// CMAC_CTX_free frees a |CMAC_CTX|. +OPENSSL_EXPORT void CMAC_CTX_free(CMAC_CTX *ctx); + +// CMAC_CTX_copy sets |out| to be a duplicate of the current state |in|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in); + +// CMAC_Init configures |ctx| to use the given |key| and |cipher|. The CMAC RFC +// only specifies the use of AES-128 thus |key_len| should be 16 and |cipher| +// should be |EVP_aes_128_cbc()|. However, this implementation also supports +// AES-256 by setting |key_len| to 32 and |cipher| to |EVP_aes_256_cbc()|. The +// |engine| argument is ignored. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t key_len, + const EVP_CIPHER *cipher, ENGINE *engine); + + +// CMAC_Reset resets |ctx| so that a fresh message can be authenticated. +OPENSSL_EXPORT int CMAC_Reset(CMAC_CTX *ctx); + +// CMAC_Update processes |in_len| bytes of message from |in|. It returns one on +// success or zero on error. +OPENSSL_EXPORT int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len); + +// CMAC_Final sets |*out_len| to 16 and, if |out| is not NULL, writes 16 bytes +// of authenticator to it. It returns one on success or zero on error. +OPENSSL_EXPORT int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(CMAC_CTX, CMAC_CTX_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#endif // OPENSSL_HEADER_CMAC_H diff --git a/lib/boringssl/include/openssl/conf.h b/lib/boringssl/include/openssl/conf.h new file mode 100644 index 00000000..908c16ea --- /dev/null +++ b/lib/boringssl/include/openssl/conf.h @@ -0,0 +1,170 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_CONF_H +#define OPENSSL_HEADER_CONF_H + +#include + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Config files look like: +// +// # Comment +// +// # This key is in the default section. +// key=value +// +// [section_name] +// key2=value2 +// +// Config files are represented by a |CONF|. + +struct conf_value_st { + char *section; + char *name; + char *value; +}; + +DEFINE_STACK_OF(CONF_VALUE) +DECLARE_LHASH_OF(CONF_VALUE) + + +// NCONF_new returns a fresh, empty |CONF|, or NULL on error. The |method| +// argument must be NULL. +OPENSSL_EXPORT CONF *NCONF_new(void *method); + +// NCONF_free frees all the data owned by |conf| and then |conf| itself. +OPENSSL_EXPORT void NCONF_free(CONF *conf); + +// NCONF_load parses the file named |filename| and adds the values found to +// |conf|. It returns one on success and zero on error. In the event of an +// error, if |out_error_line| is not NULL, |*out_error_line| is set to the +// number of the line that contained the error. +OPENSSL_EXPORT int NCONF_load(CONF *conf, const char *filename, + long *out_error_line); + +// NCONF_load_bio acts like |NCONF_load| but reads from |bio| rather than from +// a named file. +OPENSSL_EXPORT int NCONF_load_bio(CONF *conf, BIO *bio, long *out_error_line); + +// NCONF_get_section returns a stack of values for a given section in |conf|. +// If |section| is NULL, the default section is returned. It returns NULL on +// error. +OPENSSL_EXPORT const STACK_OF(CONF_VALUE) *NCONF_get_section( + const CONF *conf, const char *section); + +// NCONF_get_string returns the value of the key |name|, in section |section|. +// The |section| argument may be NULL to indicate the default section. It +// returns the value or NULL on error. +OPENSSL_EXPORT const char *NCONF_get_string(const CONF *conf, + const char *section, + const char *name); + + +// Deprecated functions + +// These defines do nothing but are provided to make old code easier to +// compile. +#define CONF_MFLAGS_DEFAULT_SECTION 0 +#define CONF_MFLAGS_IGNORE_MISSING_FILE 0 + +// CONF_modules_load_file returns one. BoringSSL is defined to have no config +// file options, thus loading from |filename| always succeeds by doing nothing. +OPENSSL_EXPORT int CONF_modules_load_file(const char *filename, + const char *appname, + unsigned long flags); + +// CONF_modules_free does nothing. +OPENSSL_EXPORT void CONF_modules_free(void); + +// OPENSSL_config does nothing. +OPENSSL_EXPORT void OPENSSL_config(const char *config_name); + +// OPENSSL_no_config does nothing. +OPENSSL_EXPORT void OPENSSL_no_config(void); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(CONF, NCONF_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define CONF_R_LIST_CANNOT_BE_NULL 100 +#define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 101 +#define CONF_R_MISSING_EQUAL_SIGN 102 +#define CONF_R_NO_CLOSE_BRACE 103 +#define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 104 +#define CONF_R_VARIABLE_HAS_NO_VALUE 105 +#define CONF_R_VARIABLE_EXPANSION_TOO_LONG 106 + +#endif // OPENSSL_HEADER_THREAD_H diff --git a/lib/boringssl/include/openssl/cpu.h b/lib/boringssl/include/openssl/cpu.h new file mode 100644 index 00000000..d865020c --- /dev/null +++ b/lib/boringssl/include/openssl/cpu.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +// This header is provided for compatibility with older revisions of BoringSSL. +// TODO(davidben): Remove this header. + +#include "crypto.h" diff --git a/lib/boringssl/include/openssl/crypto.h b/lib/boringssl/include/openssl/crypto.h new file mode 100644 index 00000000..171ac43f --- /dev/null +++ b/lib/boringssl/include/openssl/crypto.h @@ -0,0 +1,203 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_H +#define OPENSSL_HEADER_CRYPTO_H + +#include +#include + +// Upstream OpenSSL defines |OPENSSL_malloc|, etc., in crypto.h rather than +// mem.h. +#include + +// Upstream OpenSSL defines |CRYPTO_LOCK|, etc., in crypto.h rather than +// thread.h. +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +// crypto.h contains functions for initializing the crypto library. + + +// CRYPTO_library_init initializes the crypto library. It must be called if the +// library is built with BORINGSSL_NO_STATIC_INITIALIZER. Otherwise, it does +// nothing and a static initializer is used instead. It is safe to call this +// function multiple times and concurrently from multiple threads. +// +// On some ARM configurations, this function may require filesystem access and +// should be called before entering a sandbox. +OPENSSL_EXPORT void CRYPTO_library_init(void); + +// CRYPTO_is_confidential_build returns one if the linked version of BoringSSL +// has been built with the BORINGSSL_CONFIDENTIAL define and zero otherwise. +// +// This is used by some consumers to identify whether they are using an +// internal version of BoringSSL. +OPENSSL_EXPORT int CRYPTO_is_confidential_build(void); + +// CRYPTO_has_asm returns one unless BoringSSL was built with OPENSSL_NO_ASM, +// in which case it returns zero. +OPENSSL_EXPORT int CRYPTO_has_asm(void); + +// BORINGSSL_self_test triggers the FIPS KAT-based self tests. It returns one on +// success and zero on error. +OPENSSL_EXPORT int BORINGSSL_self_test(void); + +// BORINGSSL_integrity_test triggers the module's integrity test where the code +// and data of the module is matched against a hash injected at build time. It +// returns one on success or zero if there's a mismatch. This function only +// exists if the module was built in FIPS mode without ASAN. +OPENSSL_EXPORT int BORINGSSL_integrity_test(void); + +// CRYPTO_pre_sandbox_init initializes the crypto library, pre-acquiring some +// unusual resources to aid running in sandboxed environments. It is safe to +// call this function multiple times and concurrently from multiple threads. +// +// For more details on using BoringSSL in a sandboxed environment, see +// SANDBOXING.md in the source tree. +OPENSSL_EXPORT void CRYPTO_pre_sandbox_init(void); + +#if defined(OPENSSL_ARM) && defined(OPENSSL_LINUX) && \ + !defined(OPENSSL_STATIC_ARMCAP) +// CRYPTO_needs_hwcap2_workaround returns one if the ARMv8 AArch32 AT_HWCAP2 +// workaround was needed. See https://crbug.com/boringssl/46. +OPENSSL_EXPORT int CRYPTO_needs_hwcap2_workaround(void); +#endif // OPENSSL_ARM && OPENSSL_LINUX && !OPENSSL_STATIC_ARMCAP + + +// FIPS monitoring + +// FIPS_mode returns zero unless BoringSSL is built with BORINGSSL_FIPS, in +// which case it returns one. +OPENSSL_EXPORT int FIPS_mode(void); + +// fips_counter_t denotes specific APIs/algorithms. A counter is maintained for +// each in FIPS mode so that tests can be written to assert that the expected, +// FIPS functions are being called by a certain peice of code. +enum fips_counter_t { + fips_counter_evp_aes_128_gcm = 0, + fips_counter_evp_aes_256_gcm = 1, + fips_counter_evp_aes_128_ctr = 2, + fips_counter_evp_aes_256_ctr = 3, + + fips_counter_max = 3, +}; + +// FIPS_read_counter returns a counter of the number of times the specific +// function denoted by |counter| has been used. This always returns zero unless +// BoringSSL was built with BORINGSSL_FIPS_COUNTERS defined. +OPENSSL_EXPORT size_t FIPS_read_counter(enum fips_counter_t counter); + + +// Deprecated functions. + +// OPENSSL_VERSION_TEXT contains a string the identifies the version of +// “OpenSSL”. node.js requires a version number in this text. +#define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1 (compatible; BoringSSL)" + +#define OPENSSL_VERSION 0 +#define OPENSSL_CFLAGS 1 +#define OPENSSL_BUILT_ON 2 +#define OPENSSL_PLATFORM 3 +#define OPENSSL_DIR 4 + +// OpenSSL_version is a compatibility function that returns the string +// "BoringSSL" if |which| is |OPENSSL_VERSION| and placeholder strings +// otherwise. +OPENSSL_EXPORT const char *OpenSSL_version(int which); + +#define SSLEAY_VERSION OPENSSL_VERSION +#define SSLEAY_CFLAGS OPENSSL_CFLAGS +#define SSLEAY_BUILT_ON OPENSSL_BUILT_ON +#define SSLEAY_PLATFORM OPENSSL_PLATFORM +#define SSLEAY_DIR OPENSSL_DIR + +// SSLeay_version calls |OpenSSL_version|. +OPENSSL_EXPORT const char *SSLeay_version(int which); + +// SSLeay is a compatibility function that returns OPENSSL_VERSION_NUMBER from +// base.h. +OPENSSL_EXPORT unsigned long SSLeay(void); + +// OpenSSL_version_num is a compatibility function that returns +// OPENSSL_VERSION_NUMBER from base.h. +OPENSSL_EXPORT unsigned long OpenSSL_version_num(void); + +// CRYPTO_malloc_init returns one. +OPENSSL_EXPORT int CRYPTO_malloc_init(void); + +// OPENSSL_malloc_init returns one. +OPENSSL_EXPORT int OPENSSL_malloc_init(void); + +// ENGINE_load_builtin_engines does nothing. +OPENSSL_EXPORT void ENGINE_load_builtin_engines(void); + +// ENGINE_register_all_complete returns one. +OPENSSL_EXPORT int ENGINE_register_all_complete(void); + +// OPENSSL_load_builtin_modules does nothing. +OPENSSL_EXPORT void OPENSSL_load_builtin_modules(void); + +#define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS 0 +#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0 +#define OPENSSL_INIT_ADD_ALL_CIPHERS 0 +#define OPENSSL_INIT_ADD_ALL_DIGESTS 0 +#define OPENSSL_INIT_NO_ADD_ALL_CIPHERS 0 +#define OPENSSL_INIT_NO_ADD_ALL_DIGESTS 0 +#define OPENSSL_INIT_LOAD_CONFIG 0 +#define OPENSSL_INIT_NO_LOAD_CONFIG 0 + +// OPENSSL_init_crypto calls |CRYPTO_library_init| and returns one. +OPENSSL_EXPORT int OPENSSL_init_crypto(uint64_t opts, + const OPENSSL_INIT_SETTINGS *settings); + +// OPENSSL_cleanup does nothing. +OPENSSL_EXPORT void OPENSSL_cleanup(void); + +// FIPS_mode_set returns one if |on| matches whether BoringSSL was built with +// |BORINGSSL_FIPS| and zero otherwise. +OPENSSL_EXPORT int FIPS_mode_set(int on); + +// FIPS_module_name returns the name of the FIPS module. +OPENSSL_EXPORT const char *FIPS_module_name(void); + +// FIPS_version returns the version of the FIPS module, or zero if the build +// isn't exactly at a verified version. The version, expressed in base 10, will +// be a date in the form yyyymmddXX where XX is often "00", but can be +// incremented if multiple versions are defined on a single day. +// +// (This format exceeds a |uint32_t| in the year 4294.) +OPENSSL_EXPORT uint32_t FIPS_version(void); + +// FIPS_query_algorithm_status returns one if |algorithm| is FIPS validated in +// the current BoringSSL and zero otherwise. +OPENSSL_EXPORT int FIPS_query_algorithm_status(const char *algorithm); + +#if defined(OPENSSL_ARM) && defined(OPENSSL_LINUX) && \ + !defined(OPENSSL_STATIC_ARMCAP) +// CRYPTO_has_broken_NEON returns zero. +OPENSSL_EXPORT int CRYPTO_has_broken_NEON(void); +#endif + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_CRYPTO_H diff --git a/lib/boringssl/include/openssl/ctrdrbg.h b/lib/boringssl/include/openssl/ctrdrbg.h new file mode 100644 index 00000000..5440fb4d --- /dev/null +++ b/lib/boringssl/include/openssl/ctrdrbg.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2022, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CTRDRBG_H +#define OPENSSL_HEADER_CTRDRBG_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// FIPS pseudo-random number generator. + + +// CTR-DRBG state objects. +// +// CTR_DRBG_STATE contains the state of a FIPS AES-CTR-based pseudo-random +// number generator. If BoringSSL was built in FIPS mode then this is a FIPS +// Approved algorithm. + +// CTR_DRBG_ENTROPY_LEN is the number of bytes of input entropy. See SP +// 800-90Ar1, table 3. +#define CTR_DRBG_ENTROPY_LEN 48 + +// CTR_DRBG_MAX_GENERATE_LENGTH is the maximum number of bytes that can be +// generated in a single call to |CTR_DRBG_generate|. +#define CTR_DRBG_MAX_GENERATE_LENGTH 65536 + +// CTR_DRBG_new returns an initialized |CTR_DRBG_STATE|, or NULL if either +// allocation failed or if |personalization_len| is invalid. +OPENSSL_EXPORT CTR_DRBG_STATE *CTR_DRBG_new( + const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], const uint8_t *personalization, + size_t personalization_len); + +// CTR_DRBG_free frees |state| if non-NULL, or else does nothing. +OPENSSL_EXPORT void CTR_DRBG_free(CTR_DRBG_STATE* state); + +// CTR_DRBG_reseed reseeds |drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of entropy +// in |entropy| and, optionally, up to |CTR_DRBG_ENTROPY_LEN| bytes of +// additional data. It returns one on success or zero on error. +OPENSSL_EXPORT int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg, + const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], + const uint8_t *additional_data, + size_t additional_data_len); + +// CTR_DRBG_generate processes to up |CTR_DRBG_ENTROPY_LEN| bytes of additional +// data (if any) and then writes |out_len| random bytes to |out|, where +// |out_len| <= |CTR_DRBG_MAX_GENERATE_LENGTH|. It returns one on success or +// zero on error. +OPENSSL_EXPORT int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out, + size_t out_len, + const uint8_t *additional_data, + size_t additional_data_len); + +// CTR_DRBG_clear zeroises the state of |drbg|. +OPENSSL_EXPORT void CTR_DRBG_clear(CTR_DRBG_STATE *drbg); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { +BSSL_NAMESPACE_BEGIN +BORINGSSL_MAKE_DELETER(CTR_DRBG_STATE, CTR_DRBG_free) +BSSL_NAMESPACE_END +} // extern C++ +#endif + +#endif // OPENSSL_HEADER_CTRDRBG_H diff --git a/lib/boringssl/include/openssl/curve25519.h b/lib/boringssl/include/openssl/curve25519.h new file mode 100644 index 00000000..a455389c --- /dev/null +++ b/lib/boringssl/include/openssl/curve25519.h @@ -0,0 +1,201 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CURVE25519_H +#define OPENSSL_HEADER_CURVE25519_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Curve25519. +// +// Curve25519 is an elliptic curve. See https://tools.ietf.org/html/rfc7748. + + +// X25519. +// +// X25519 is the Diffie-Hellman primitive built from curve25519. It is +// sometimes referred to as “curve25519”, but “X25519” is a more precise name. +// See http://cr.yp.to/ecdh.html and https://tools.ietf.org/html/rfc7748. + +#define X25519_PRIVATE_KEY_LEN 32 +#define X25519_PUBLIC_VALUE_LEN 32 +#define X25519_SHARED_KEY_LEN 32 + +// X25519_keypair sets |out_public_value| and |out_private_key| to a freshly +// generated, public–private key pair. +OPENSSL_EXPORT void X25519_keypair(uint8_t out_public_value[32], + uint8_t out_private_key[32]); + +// X25519 writes a shared key to |out_shared_key| that is calculated from the +// given private key and the peer's public value. It returns one on success and +// zero on error. +// +// Don't use the shared key directly, rather use a KDF and also include the two +// public values as inputs. +OPENSSL_EXPORT int X25519(uint8_t out_shared_key[32], + const uint8_t private_key[32], + const uint8_t peer_public_value[32]); + +// X25519_public_from_private calculates a Diffie-Hellman public value from the +// given private key and writes it to |out_public_value|. +OPENSSL_EXPORT void X25519_public_from_private(uint8_t out_public_value[32], + const uint8_t private_key[32]); + + +// Ed25519. +// +// Ed25519 is a signature scheme using a twisted-Edwards curve that is +// birationally equivalent to curve25519. +// +// Note that, unlike RFC 8032's formulation, our private key representation +// includes a public key suffix to make multiple key signing operations with the +// same key more efficient. The RFC 8032 private key is referred to in this +// implementation as the "seed" and is the first 32 bytes of our private key. + +#define ED25519_PRIVATE_KEY_LEN 64 +#define ED25519_PUBLIC_KEY_LEN 32 +#define ED25519_SIGNATURE_LEN 64 + +// ED25519_keypair sets |out_public_key| and |out_private_key| to a freshly +// generated, public–private key pair. +OPENSSL_EXPORT void ED25519_keypair(uint8_t out_public_key[32], + uint8_t out_private_key[64]); + +// ED25519_sign sets |out_sig| to be a signature of |message_len| bytes from +// |message| using |private_key|. It returns one on success or zero on +// allocation failure. +OPENSSL_EXPORT int ED25519_sign(uint8_t out_sig[64], const uint8_t *message, + size_t message_len, + const uint8_t private_key[64]); + +// ED25519_verify returns one iff |signature| is a valid signature, by +// |public_key| of |message_len| bytes from |message|. It returns zero +// otherwise. +OPENSSL_EXPORT int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[64], + const uint8_t public_key[32]); + +// ED25519_keypair_from_seed calculates a public and private key from an +// Ed25519 “seed”. Seed values are not exposed by this API (although they +// happen to be the first 32 bytes of a private key) so this function is for +// interoperating with systems that may store just a seed instead of a full +// private key. +OPENSSL_EXPORT void ED25519_keypair_from_seed(uint8_t out_public_key[32], + uint8_t out_private_key[64], + const uint8_t seed[32]); + + +// SPAKE2. +// +// SPAKE2 is a password-authenticated key-exchange. It allows two parties, +// who share a low-entropy secret (i.e. password), to agree on a shared key. +// An attacker can only make one guess of the password per execution of the +// protocol. +// +// See https://tools.ietf.org/html/draft-irtf-cfrg-spake2-02. + +// spake2_role_t enumerates the different “roles” in SPAKE2. The protocol +// requires that the symmetry of the two parties be broken so one participant +// must be “Alice” and the other be “Bob”. +enum spake2_role_t { + spake2_role_alice, + spake2_role_bob, +}; + +// SPAKE2_CTX_new creates a new |SPAKE2_CTX| (which can only be used for a +// single execution of the protocol). SPAKE2 requires the symmetry of the two +// parties to be broken which is indicated via |my_role| – each party must pass +// a different value for this argument. +// +// The |my_name| and |their_name| arguments allow optional, opaque names to be +// bound into the protocol. For example MAC addresses, hostnames, usernames +// etc. These values are not exposed and can avoid context-confusion attacks +// when a password is shared between several devices. +OPENSSL_EXPORT SPAKE2_CTX *SPAKE2_CTX_new( + enum spake2_role_t my_role, + const uint8_t *my_name, size_t my_name_len, + const uint8_t *their_name, size_t their_name_len); + +// SPAKE2_CTX_free frees |ctx| and all the resources that it has allocated. +OPENSSL_EXPORT void SPAKE2_CTX_free(SPAKE2_CTX *ctx); + +// SPAKE2_MAX_MSG_SIZE is the maximum size of a SPAKE2 message. +#define SPAKE2_MAX_MSG_SIZE 32 + +// SPAKE2_generate_msg generates a SPAKE2 message given |password|, writes +// it to |out| and sets |*out_len| to the number of bytes written. +// +// At most |max_out_len| bytes are written to |out| and, in order to ensure +// success, |max_out_len| should be at least |SPAKE2_MAX_MSG_SIZE| bytes. +// +// This function can only be called once for a given |SPAKE2_CTX|. +// +// It returns one on success and zero on error. +OPENSSL_EXPORT int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *password, + size_t password_len); + +// SPAKE2_MAX_KEY_SIZE is the maximum amount of key material that SPAKE2 will +// produce. +#define SPAKE2_MAX_KEY_SIZE 64 + +// SPAKE2_process_msg completes the SPAKE2 exchange given the peer's message in +// |their_msg|, writes at most |max_out_key_len| bytes to |out_key| and sets +// |*out_key_len| to the number of bytes written. +// +// The resulting keying material is suitable for: +// a) Using directly in a key-confirmation step: i.e. each side could +// transmit a hash of their role, a channel-binding value and the key +// material to prove to the other side that they know the shared key. +// b) Using as input keying material to HKDF to generate a variety of subkeys +// for encryption etc. +// +// If |max_out_key_key| is smaller than the amount of key material generated +// then the key is silently truncated. If you want to ensure that no truncation +// occurs then |max_out_key| should be at least |SPAKE2_MAX_KEY_SIZE|. +// +// You must call |SPAKE2_generate_msg| on a given |SPAKE2_CTX| before calling +// this function. On successful return, |ctx| is complete and calling +// |SPAKE2_CTX_free| is the only acceptable operation on it. +// +// Returns one on success or zero on error. +OPENSSL_EXPORT int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, + size_t *out_key_len, + size_t max_out_key_len, + const uint8_t *their_msg, + size_t their_msg_len); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(SPAKE2_CTX, SPAKE2_CTX_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#endif // OPENSSL_HEADER_CURVE25519_H diff --git a/lib/boringssl/include/openssl/des.h b/lib/boringssl/include/openssl/des.h new file mode 100644 index 00000000..539b2c52 --- /dev/null +++ b/lib/boringssl/include/openssl/des.h @@ -0,0 +1,183 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DES_H +#define OPENSSL_HEADER_DES_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// DES. +// +// This module is deprecated and retained for legacy reasons only. It is slow +// and may leak key material with timing or cache side channels. Moreover, +// single-keyed DES is broken and can be brute-forced in under a day. +// +// Use a modern cipher, such as AES-GCM or ChaCha20-Poly1305, instead. + + +typedef struct DES_cblock_st { + uint8_t bytes[8]; +} DES_cblock; + +typedef struct DES_ks { + uint32_t subkeys[16][2]; +} DES_key_schedule; + + +#define DES_KEY_SZ (sizeof(DES_cblock)) +#define DES_SCHEDULE_SZ (sizeof(DES_key_schedule)) + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define DES_CBC_MODE 0 +#define DES_PCBC_MODE 1 + +// DES_set_key performs a key schedule and initialises |schedule| with |key|. +OPENSSL_EXPORT void DES_set_key(const DES_cblock *key, + DES_key_schedule *schedule); + +// DES_set_odd_parity sets the parity bits (the least-significant bits in each +// byte) of |key| given the other bits in each byte. +OPENSSL_EXPORT void DES_set_odd_parity(DES_cblock *key); + +// DES_ecb_encrypt encrypts (or decrypts, if |is_encrypt| is |DES_DECRYPT|) a +// single DES block (8 bytes) from in to out, using the key configured in +// |schedule|. +OPENSSL_EXPORT void DES_ecb_encrypt(const DES_cblock *in, DES_cblock *out, + const DES_key_schedule *schedule, + int is_encrypt); + +// DES_ncbc_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) |len| +// bytes from |in| to |out| with DES in CBC mode. +OPENSSL_EXPORT void DES_ncbc_encrypt(const uint8_t *in, uint8_t *out, + size_t len, + const DES_key_schedule *schedule, + DES_cblock *ivec, int enc); + +// DES_ecb3_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) a single +// block (8 bytes) of data from |input| to |output| using 3DES. +OPENSSL_EXPORT void DES_ecb3_encrypt(const DES_cblock *input, + DES_cblock *output, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3, + int enc); + +// DES_ede3_cbc_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) |len| +// bytes from |in| to |out| with 3DES in CBC mode. 3DES uses three keys, thus +// the function takes three different |DES_key_schedule|s. +OPENSSL_EXPORT void DES_ede3_cbc_encrypt(const uint8_t *in, uint8_t *out, + size_t len, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3, + DES_cblock *ivec, int enc); + +// DES_ede2_cbc_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) |len| +// bytes from |in| to |out| with 3DES in CBC mode. With this keying option, the +// first and third 3DES keys are identical. Thus, this function takes only two +// different |DES_key_schedule|s. +OPENSSL_EXPORT void DES_ede2_cbc_encrypt(const uint8_t *in, uint8_t *out, + size_t len, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + DES_cblock *ivec, int enc); + + +// Deprecated functions. + +// DES_set_key_unchecked calls |DES_set_key|. +OPENSSL_EXPORT void DES_set_key_unchecked(const DES_cblock *key, + DES_key_schedule *schedule); + +OPENSSL_EXPORT void DES_ede3_cfb64_encrypt(const uint8_t *in, uint8_t *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, + DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc); + +OPENSSL_EXPORT void DES_ede3_cfb_encrypt(const uint8_t *in, uint8_t *out, + int numbits, long length, + DES_key_schedule *ks1, + DES_key_schedule *ks2, + DES_key_schedule *ks3, + DES_cblock *ivec, int enc); + + +// Private functions. +// +// These functions are only exported for use in |decrepit|. + +OPENSSL_EXPORT void DES_decrypt3(uint32_t *data, const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3); + +OPENSSL_EXPORT void DES_encrypt3(uint32_t *data, const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_DES_H diff --git a/lib/boringssl/include/openssl/dh.h b/lib/boringssl/include/openssl/dh.h new file mode 100644 index 00000000..660627db --- /dev/null +++ b/lib/boringssl/include/openssl/dh.h @@ -0,0 +1,355 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DH_H +#define OPENSSL_HEADER_DH_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// DH contains functions for performing Diffie-Hellman key agreement in +// multiplicative groups. +// +// This module is deprecated and retained for legacy reasons only. It is not +// considered a priority for performance or hardening work. Do not use it in +// new code. Use X25519 or ECDH with P-256 instead. + + +// Allocation and destruction. + +// DH_new returns a new, empty DH object or NULL on error. +OPENSSL_EXPORT DH *DH_new(void); + +// DH_free decrements the reference count of |dh| and frees it if the reference +// count drops to zero. +OPENSSL_EXPORT void DH_free(DH *dh); + +// DH_up_ref increments the reference count of |dh| and returns one. +OPENSSL_EXPORT int DH_up_ref(DH *dh); + + +// Properties. + +// DH_bits returns the size of |dh|'s group modulus, in bits. +OPENSSL_EXPORT unsigned DH_bits(const DH *dh); + +// DH_get0_pub_key returns |dh|'s public key. +OPENSSL_EXPORT const BIGNUM *DH_get0_pub_key(const DH *dh); + +// DH_get0_priv_key returns |dh|'s private key, or NULL if |dh| is a public key. +OPENSSL_EXPORT const BIGNUM *DH_get0_priv_key(const DH *dh); + +// DH_get0_p returns |dh|'s group modulus. +OPENSSL_EXPORT const BIGNUM *DH_get0_p(const DH *dh); + +// DH_get0_q returns the size of |dh|'s subgroup, or NULL if it is unset. +OPENSSL_EXPORT const BIGNUM *DH_get0_q(const DH *dh); + +// DH_get0_g returns |dh|'s group generator. +OPENSSL_EXPORT const BIGNUM *DH_get0_g(const DH *dh); + +// DH_get0_key sets |*out_pub_key| and |*out_priv_key|, if non-NULL, to |dh|'s +// public and private key, respectively. If |dh| is a public key, the private +// key will be set to NULL. +OPENSSL_EXPORT void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key, + const BIGNUM **out_priv_key); + +// DH_set0_key sets |dh|'s public and private key to the specified values. If +// NULL, the field is left unchanged. On success, it takes ownership of each +// argument and returns one. Otherwise, it returns zero. +OPENSSL_EXPORT int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); + +// DH_get0_pqg sets |*out_p|, |*out_q|, and |*out_g|, if non-NULL, to |dh|'s p, +// q, and g parameters, respectively. +OPENSSL_EXPORT void DH_get0_pqg(const DH *dh, const BIGNUM **out_p, + const BIGNUM **out_q, const BIGNUM **out_g); + +// DH_set0_pqg sets |dh|'s p, q, and g parameters to the specified values. If +// NULL, the field is left unchanged. On success, it takes ownership of each +// argument and returns one. Otherwise, it returns zero. |q| may be NULL, but +// |p| and |g| must either be specified or already configured on |dh|. +OPENSSL_EXPORT int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); + +// DH_set_length sets the number of bits to use for the secret exponent when +// calling |DH_generate_key| on |dh| and returns one. If unset, +// |DH_generate_key| will use the bit length of p. +OPENSSL_EXPORT int DH_set_length(DH *dh, unsigned priv_length); + + +// Standard parameters. + +// DH_get_rfc7919_2048 returns the group `ffdhe2048` from +// https://tools.ietf.org/html/rfc7919#appendix-A.1. It returns NULL if out +// of memory. +OPENSSL_EXPORT DH *DH_get_rfc7919_2048(void); + +// BN_get_rfc3526_prime_1536 sets |*ret| to the 1536-bit MODP group from RFC +// 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated +// and returned. It returns NULL on allocation failure. +OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *ret); + +// BN_get_rfc3526_prime_2048 sets |*ret| to the 2048-bit MODP group from RFC +// 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated +// and returned. It returns NULL on allocation failure. +OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *ret); + +// BN_get_rfc3526_prime_3072 sets |*ret| to the 3072-bit MODP group from RFC +// 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated +// and returned. It returns NULL on allocation failure. +OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *ret); + +// BN_get_rfc3526_prime_4096 sets |*ret| to the 4096-bit MODP group from RFC +// 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated +// and returned. It returns NULL on allocation failure. +OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *ret); + +// BN_get_rfc3526_prime_6144 sets |*ret| to the 6144-bit MODP group from RFC +// 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated +// and returned. It returns NULL on allocation failure. +OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *ret); + +// BN_get_rfc3526_prime_8192 sets |*ret| to the 8192-bit MODP group from RFC +// 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated +// and returned. It returns NULL on allocation failure. +OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *ret); + + +// Parameter generation. + +#define DH_GENERATOR_2 2 +#define DH_GENERATOR_5 5 + +// DH_generate_parameters_ex generates a suitable Diffie-Hellman group with a +// prime that is |prime_bits| long and stores it in |dh|. The generator of the +// group will be |generator|, which should be |DH_GENERATOR_2| unless there's a +// good reason to use a different value. The |cb| argument contains a callback +// function that will be called during the generation. See the documentation in +// |bn.h| about this. In addition to the callback invocations from |BN|, |cb| +// will also be called with |event| equal to three when the generation is +// complete. +OPENSSL_EXPORT int DH_generate_parameters_ex(DH *dh, int prime_bits, + int generator, BN_GENCB *cb); + + +// Diffie-Hellman operations. + +// DH_generate_key generates a new, random, private key and stores it in +// |dh|. It returns one on success and zero on error. +OPENSSL_EXPORT int DH_generate_key(DH *dh); + +// DH_compute_key_padded calculates the shared key between |dh| and |peers_key| +// and writes it as a big-endian integer into |out|, padded up to |DH_size| +// bytes. It returns the number of bytes written, which is always |DH_size|, or +// a negative number on error. |out| must have |DH_size| bytes of space. +// +// WARNING: this differs from the usual BoringSSL return-value convention. +// +// Note this function differs from |DH_compute_key| in that it preserves leading +// zeros in the secret. This function is the preferred variant. It matches PKCS +// #3 and avoids some side channel attacks. However, the two functions are not +// drop-in replacements for each other. Using a different variant than the +// application expects will result in sporadic key mismatches. +// +// Callers that expect a fixed-width secret should use this function over +// |DH_compute_key|. Callers that use either function should migrate to a modern +// primitive such as X25519 or ECDH with P-256 instead. +OPENSSL_EXPORT int DH_compute_key_padded(uint8_t *out, const BIGNUM *peers_key, + DH *dh); + +// DH_compute_key_hashed calculates the shared key between |dh| and |peers_key| +// and hashes it with the given |digest|. If the hash output is less than +// |max_out_len| bytes then it writes the hash output to |out| and sets +// |*out_len| to the number of bytes written. Otherwise it signals an error. It +// returns one on success or zero on error. +// +// NOTE: this follows the usual BoringSSL return-value convention, but that's +// different from |DH_compute_key| and |DH_compute_key_padded|. +OPENSSL_EXPORT int DH_compute_key_hashed(DH *dh, uint8_t *out, size_t *out_len, + size_t max_out_len, + const BIGNUM *peers_key, + const EVP_MD *digest); + + +// Utility functions. + +// DH_size returns the number of bytes in the DH group's prime. +OPENSSL_EXPORT int DH_size(const DH *dh); + +// DH_num_bits returns the minimum number of bits needed to represent the +// absolute value of the DH group's prime. +OPENSSL_EXPORT unsigned DH_num_bits(const DH *dh); + +#define DH_CHECK_P_NOT_PRIME 0x01 +#define DH_CHECK_P_NOT_SAFE_PRIME 0x02 +#define DH_CHECK_UNABLE_TO_CHECK_GENERATOR 0x04 +#define DH_CHECK_NOT_SUITABLE_GENERATOR 0x08 +#define DH_CHECK_Q_NOT_PRIME 0x10 +#define DH_CHECK_INVALID_Q_VALUE 0x20 + +// These are compatibility defines. +#define DH_NOT_SUITABLE_GENERATOR DH_CHECK_NOT_SUITABLE_GENERATOR +#define DH_UNABLE_TO_CHECK_GENERATOR DH_CHECK_UNABLE_TO_CHECK_GENERATOR + +// DH_check checks the suitability of |dh| as a Diffie-Hellman group. and sets +// |DH_CHECK_*| flags in |*out_flags| if it finds any errors. It returns one if +// |*out_flags| was successfully set and zero on error. +// +// Note: these checks may be quite computationally expensive. +OPENSSL_EXPORT int DH_check(const DH *dh, int *out_flags); + +#define DH_CHECK_PUBKEY_TOO_SMALL 0x1 +#define DH_CHECK_PUBKEY_TOO_LARGE 0x2 +#define DH_CHECK_PUBKEY_INVALID 0x4 + +// DH_check_pub_key checks the suitability of |pub_key| as a public key for the +// DH group in |dh| and sets |DH_CHECK_PUBKEY_*| flags in |*out_flags| if it +// finds any errors. It returns one if |*out_flags| was successfully set and +// zero on error. +OPENSSL_EXPORT int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, + int *out_flags); + +// DHparams_dup allocates a fresh |DH| and copies the parameters from |dh| into +// it. It returns the new |DH| or NULL on error. +OPENSSL_EXPORT DH *DHparams_dup(const DH *dh); + + +// ASN.1 functions. + +// DH_parse_parameters decodes a DER-encoded DHParameter structure (PKCS #3) +// from |cbs| and advances |cbs|. It returns a newly-allocated |DH| or NULL on +// error. +OPENSSL_EXPORT DH *DH_parse_parameters(CBS *cbs); + +// DH_marshal_parameters marshals |dh| as a DER-encoded DHParameter structure +// (PKCS #3) and appends the result to |cbb|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int DH_marshal_parameters(CBB *cbb, const DH *dh); + + +// Deprecated functions. + +// DH_generate_parameters behaves like |DH_generate_parameters_ex|, which is +// what you should use instead. It returns NULL on error, or a newly-allocated +// |DH| on success. This function is provided for compatibility only. +OPENSSL_EXPORT DH *DH_generate_parameters(int prime_len, int generator, + void (*callback)(int, int, void *), + void *cb_arg); + +// d2i_DHparams parses a DER-encoded DHParameter structure (PKCS #3) from |len| +// bytes at |*inp|, as in |d2i_SAMPLE|. +// +// Use |DH_parse_parameters| instead. +OPENSSL_EXPORT DH *d2i_DHparams(DH **ret, const unsigned char **inp, long len); + +// i2d_DHparams marshals |in| to a DER-encoded DHParameter structure (PKCS #3), +// as described in |i2d_SAMPLE|. +// +// Use |DH_marshal_parameters| instead. +OPENSSL_EXPORT int i2d_DHparams(const DH *in, unsigned char **outp); + +// DH_compute_key behaves like |DH_compute_key_padded| but, contrary to PKCS #3, +// returns a variable-length shared key with leading zeros. It returns the +// number of bytes written, or a negative number on error. |out| must have +// |DH_size| bytes of space. +// +// WARNING: this differs from the usual BoringSSL return-value convention. +// +// Note this function's running time and memory access pattern leaks information +// about the shared secret. Particularly if |dh| is reused, this may result in +// side channel attacks such as https://raccoon-attack.com/. +// +// |DH_compute_key_padded| is the preferred variant and avoids the above +// attacks. However, the two functions are not drop-in replacements for each +// other. Using a different variant than the application expects will result in +// sporadic key mismatches. +// +// Callers that expect a fixed-width secret should use |DH_compute_key_padded| +// instead. Callers that use either function should migrate to a modern +// primitive such as X25519 or ECDH with P-256 instead. +OPENSSL_EXPORT int DH_compute_key(uint8_t *out, const BIGNUM *peers_key, + DH *dh); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(DH, DH_free) +BORINGSSL_MAKE_UP_REF(DH, DH_up_ref) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define DH_R_BAD_GENERATOR 100 +#define DH_R_INVALID_PUBKEY 101 +#define DH_R_MODULUS_TOO_LARGE 102 +#define DH_R_NO_PRIVATE_VALUE 103 +#define DH_R_DECODE_ERROR 104 +#define DH_R_ENCODE_ERROR 105 + +#endif // OPENSSL_HEADER_DH_H diff --git a/lib/boringssl/include/openssl/digest.h b/lib/boringssl/include/openssl/digest.h new file mode 100644 index 00000000..6e889993 --- /dev/null +++ b/lib/boringssl/include/openssl/digest.h @@ -0,0 +1,355 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DIGEST_H +#define OPENSSL_HEADER_DIGEST_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Digest functions. +// +// An EVP_MD abstracts the details of a specific hash function allowing code to +// deal with the concept of a "hash function" without needing to know exactly +// which hash function it is. + + +// Hash algorithms. +// +// The following functions return |EVP_MD| objects that implement the named hash +// function. + +OPENSSL_EXPORT const EVP_MD *EVP_md4(void); +OPENSSL_EXPORT const EVP_MD *EVP_md5(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha1(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha224(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha256(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha384(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha512(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha512_256(void); +OPENSSL_EXPORT const EVP_MD *EVP_blake2b256(void); + +// EVP_md5_sha1 is a TLS-specific |EVP_MD| which computes the concatenation of +// MD5 and SHA-1, as used in TLS 1.1 and below. +OPENSSL_EXPORT const EVP_MD *EVP_md5_sha1(void); + +// EVP_get_digestbynid returns an |EVP_MD| for the given NID, or NULL if no +// such digest is known. +OPENSSL_EXPORT const EVP_MD *EVP_get_digestbynid(int nid); + +// EVP_get_digestbyobj returns an |EVP_MD| for the given |ASN1_OBJECT|, or NULL +// if no such digest is known. +OPENSSL_EXPORT const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj); + + +// Digest contexts. +// +// An EVP_MD_CTX represents the state of a specific digest operation in +// progress. + +// EVP_MD_CTX_init initialises an, already allocated, |EVP_MD_CTX|. This is the +// same as setting the structure to zero. +OPENSSL_EXPORT void EVP_MD_CTX_init(EVP_MD_CTX *ctx); + +// EVP_MD_CTX_new allocates and initialises a fresh |EVP_MD_CTX| and returns +// it, or NULL on allocation failure. The caller must use |EVP_MD_CTX_free| to +// release the resulting object. +OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_new(void); + +// EVP_MD_CTX_cleanup frees any resources owned by |ctx| and resets it to a +// freshly initialised state. It does not free |ctx| itself. It returns one. +OPENSSL_EXPORT int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); + +// EVP_MD_CTX_cleanse zeros the digest state in |ctx| and then performs the +// actions of |EVP_MD_CTX_cleanup|. Note that some |EVP_MD_CTX| objects contain +// more than just a digest (e.g. those resulting from |EVP_DigestSignInit|) but +// this function does not zero out more than just the digest state even in that +// case. +OPENSSL_EXPORT void EVP_MD_CTX_cleanse(EVP_MD_CTX *ctx); + +// EVP_MD_CTX_free calls |EVP_MD_CTX_cleanup| and then frees |ctx| itself. +OPENSSL_EXPORT void EVP_MD_CTX_free(EVP_MD_CTX *ctx); + +// EVP_MD_CTX_copy_ex sets |out|, which must already be initialised, to be a +// copy of |in|. It returns one on success and zero on allocation failure. +OPENSSL_EXPORT int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); + +// EVP_MD_CTX_move sets |out|, which must already be initialised, to the hash +// state in |in|. |in| is mutated and left in an empty state. +OPENSSL_EXPORT void EVP_MD_CTX_move(EVP_MD_CTX *out, EVP_MD_CTX *in); + +// EVP_MD_CTX_reset calls |EVP_MD_CTX_cleanup| followed by |EVP_MD_CTX_init|. It +// returns one. +OPENSSL_EXPORT int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); + + +// Digest operations. + +// EVP_DigestInit_ex configures |ctx|, which must already have been +// initialised, for a fresh hashing operation using |type|. It returns one on +// success and zero on allocation failure. +OPENSSL_EXPORT int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *engine); + +// EVP_DigestInit acts like |EVP_DigestInit_ex| except that |ctx| is +// initialised before use. +OPENSSL_EXPORT int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); + +// EVP_DigestUpdate hashes |len| bytes from |data| into the hashing operation +// in |ctx|. It returns one. +OPENSSL_EXPORT int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +// EVP_MAX_MD_SIZE is the largest digest size supported, in bytes. +// Functions that output a digest generally require the buffer have +// at least this much space. +#define EVP_MAX_MD_SIZE 64 // SHA-512 is the longest so far. + +// EVP_MAX_MD_BLOCK_SIZE is the largest digest block size supported, in +// bytes. +#define EVP_MAX_MD_BLOCK_SIZE 128 // SHA-512 is the longest so far. + +// EVP_DigestFinal_ex finishes the digest in |ctx| and writes the output to +// |md_out|. |EVP_MD_CTX_size| bytes are written, which is at most +// |EVP_MAX_MD_SIZE|. If |out_size| is not NULL then |*out_size| is set to the +// number of bytes written. It returns one. After this call, the hash cannot be +// updated or finished again until |EVP_DigestInit_ex| is called to start +// another hashing operation. +OPENSSL_EXPORT int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, + unsigned int *out_size); + +// EVP_DigestFinal acts like |EVP_DigestFinal_ex| except that +// |EVP_MD_CTX_cleanup| is called on |ctx| before returning. +OPENSSL_EXPORT int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md_out, + unsigned int *out_size); + +// EVP_Digest performs a complete hashing operation in one call. It hashes |len| +// bytes from |data| and writes the digest to |md_out|. |EVP_MD_CTX_size| bytes +// are written, which is at most |EVP_MAX_MD_SIZE|. If |out_size| is not NULL +// then |*out_size| is set to the number of bytes written. It returns one on +// success and zero otherwise. +OPENSSL_EXPORT int EVP_Digest(const void *data, size_t len, uint8_t *md_out, + unsigned int *md_out_size, const EVP_MD *type, + ENGINE *impl); + + +// Digest function accessors. +// +// These functions allow code to learn details about an abstract hash +// function. + +// EVP_MD_type returns a NID identifying |md|. (For example, |NID_sha256|.) +OPENSSL_EXPORT int EVP_MD_type(const EVP_MD *md); + +// EVP_MD_flags returns the flags for |md|, which is a set of |EVP_MD_FLAG_*| +// values, ORed together. +OPENSSL_EXPORT uint32_t EVP_MD_flags(const EVP_MD *md); + +// EVP_MD_size returns the digest size of |md|, in bytes. +OPENSSL_EXPORT size_t EVP_MD_size(const EVP_MD *md); + +// EVP_MD_block_size returns the native block-size of |md|, in bytes. +OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md); + +// EVP_MD_FLAG_PKEY_DIGEST indicates that the digest function is used with a +// specific public key in order to verify signatures. (For example, +// EVP_dss1.) +#define EVP_MD_FLAG_PKEY_DIGEST 1 + +// EVP_MD_FLAG_DIGALGID_ABSENT indicates that the parameter type in an X.509 +// DigestAlgorithmIdentifier representing this digest function should be +// undefined rather than NULL. +#define EVP_MD_FLAG_DIGALGID_ABSENT 2 + +// EVP_MD_FLAG_XOF indicates that the digest is an extensible-output function +// (XOF). This flag is defined for compatibility and will never be set in any +// |EVP_MD| in BoringSSL. +#define EVP_MD_FLAG_XOF 4 + + +// Digest operation accessors. + +// EVP_MD_CTX_md returns the underlying digest function, or NULL if one has not +// been set. +OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); + +// EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It +// will crash if a digest hasn't been set on |ctx|. +OPENSSL_EXPORT size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx); + +// EVP_MD_CTX_block_size returns the block size of the digest function used by +// |ctx|, in bytes. It will crash if a digest hasn't been set on |ctx|. +OPENSSL_EXPORT size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx); + +// EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|. +// (For example, |NID_sha256|.) It will crash if a digest hasn't been set on +// |ctx|. +OPENSSL_EXPORT int EVP_MD_CTX_type(const EVP_MD_CTX *ctx); + + +// ASN.1 functions. +// +// These functions allow code to parse and serialize AlgorithmIdentifiers for +// hash functions. + +// EVP_parse_digest_algorithm parses an AlgorithmIdentifier structure containing +// a hash function OID (for example, 2.16.840.1.101.3.4.2.1 is SHA-256) and +// advances |cbs|. The parameters field may either be omitted or a NULL. It +// returns the digest function or NULL on error. +OPENSSL_EXPORT const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs); + +// EVP_marshal_digest_algorithm marshals |md| as an AlgorithmIdentifier +// structure and appends the result to |cbb|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md); + + +// Deprecated functions. + +// EVP_MD_CTX_copy sets |out|, which must /not/ be initialised, to be a copy of +// |in|. It returns one on success and zero on error. +OPENSSL_EXPORT int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in); + +// EVP_add_digest does nothing and returns one. It exists only for +// compatibility with OpenSSL. +OPENSSL_EXPORT int EVP_add_digest(const EVP_MD *digest); + +// EVP_get_digestbyname returns an |EVP_MD| given a human readable name in +// |name|, or NULL if the name is unknown. +OPENSSL_EXPORT const EVP_MD *EVP_get_digestbyname(const char *); + +// EVP_dss1 returns the value of EVP_sha1(). This was provided by OpenSSL to +// specifiy the original DSA signatures, which were fixed to use SHA-1. Note, +// however, that attempting to sign or verify DSA signatures with the EVP +// interface will always fail. +OPENSSL_EXPORT const EVP_MD *EVP_dss1(void); + +// EVP_MD_CTX_create calls |EVP_MD_CTX_new|. +OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_create(void); + +// EVP_MD_CTX_destroy calls |EVP_MD_CTX_free|. +OPENSSL_EXPORT void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); + +// EVP_DigestFinalXOF returns zero and adds an error to the error queue. +// BoringSSL does not support any XOF digests. +OPENSSL_EXPORT int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, uint8_t *out, + size_t len); + +// EVP_MD_meth_get_flags calls |EVP_MD_flags|. +OPENSSL_EXPORT uint32_t EVP_MD_meth_get_flags(const EVP_MD *md); + +// EVP_MD_CTX_set_flags does nothing. +OPENSSL_EXPORT void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags); + +// EVP_MD_CTX_FLAG_NON_FIPS_ALLOW is meaningless. In OpenSSL it permits non-FIPS +// algorithms in FIPS mode. But BoringSSL FIPS mode doesn't prohibit algorithms +// (it's up the the caller to use the FIPS module in a fashion compliant with +// their needs). Thus this exists only to allow code to compile. +#define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0 + +// EVP_MD_nid calls |EVP_MD_type|. +OPENSSL_EXPORT int EVP_MD_nid(const EVP_MD *md); + + +struct evp_md_pctx_ops; + +struct env_md_ctx_st { + // digest is the underlying digest function, or NULL if not set. + const EVP_MD *digest; + // md_data points to a block of memory that contains the hash-specific + // context. + void *md_data; + + // pctx is an opaque (at this layer) pointer to additional context that + // EVP_PKEY functions may store in this object. + EVP_PKEY_CTX *pctx; + + // pctx_ops, if not NULL, points to a vtable that contains functions to + // manipulate |pctx|. + const struct evp_md_pctx_ops *pctx_ops; +} /* EVP_MD_CTX */; + + +#if defined(__cplusplus) +} // extern C + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(EVP_MD_CTX, EVP_MD_CTX_free) + +using ScopedEVP_MD_CTX = + internal::StackAllocatedMovable; + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#endif + +#define DIGEST_R_INPUT_NOT_INITIALIZED 100 +#define DIGEST_R_DECODE_ERROR 101 +#define DIGEST_R_UNKNOWN_HASH 102 + +#endif // OPENSSL_HEADER_DIGEST_H diff --git a/lib/boringssl/include/openssl/dsa.h b/lib/boringssl/include/openssl/dsa.h new file mode 100644 index 00000000..30afd438 --- /dev/null +++ b/lib/boringssl/include/openssl/dsa.h @@ -0,0 +1,447 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + * + * The DSS routines are based on patches supplied by + * Steven Schoch . */ + +#ifndef OPENSSL_HEADER_DSA_H +#define OPENSSL_HEADER_DSA_H + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// DSA contains functions for signing and verifying with the Digital Signature +// Algorithm. +// +// This module is deprecated and retained for legacy reasons only. It is not +// considered a priority for performance or hardening work. Do not use it in +// new code. Use Ed25519, ECDSA with P-256, or RSA instead. + + +// Allocation and destruction. + +// DSA_new returns a new, empty DSA object or NULL on error. +OPENSSL_EXPORT DSA *DSA_new(void); + +// DSA_free decrements the reference count of |dsa| and frees it if the +// reference count drops to zero. +OPENSSL_EXPORT void DSA_free(DSA *dsa); + +// DSA_up_ref increments the reference count of |dsa| and returns one. +OPENSSL_EXPORT int DSA_up_ref(DSA *dsa); + + +// Properties. + +// DSA_bits returns the size of |dsa|'s group modulus, in bits. +OPENSSL_EXPORT unsigned DSA_bits(const DSA *dsa); + +// DSA_get0_pub_key returns |dsa|'s public key. +OPENSSL_EXPORT const BIGNUM *DSA_get0_pub_key(const DSA *dsa); + +// DSA_get0_priv_key returns |dsa|'s private key, or NULL if |dsa| is a public +// key. +OPENSSL_EXPORT const BIGNUM *DSA_get0_priv_key(const DSA *dsa); + +// DSA_get0_p returns |dsa|'s group modulus. +OPENSSL_EXPORT const BIGNUM *DSA_get0_p(const DSA *dsa); + +// DSA_get0_q returns the size of |dsa|'s subgroup. +OPENSSL_EXPORT const BIGNUM *DSA_get0_q(const DSA *dsa); + +// DSA_get0_g returns |dsa|'s group generator. +OPENSSL_EXPORT const BIGNUM *DSA_get0_g(const DSA *dsa); + +// DSA_get0_key sets |*out_pub_key| and |*out_priv_key|, if non-NULL, to |dsa|'s +// public and private key, respectively. If |dsa| is a public key, the private +// key will be set to NULL. +OPENSSL_EXPORT void DSA_get0_key(const DSA *dsa, const BIGNUM **out_pub_key, + const BIGNUM **out_priv_key); + +// DSA_get0_pqg sets |*out_p|, |*out_q|, and |*out_g|, if non-NULL, to |dsa|'s +// p, q, and g parameters, respectively. +OPENSSL_EXPORT void DSA_get0_pqg(const DSA *dsa, const BIGNUM **out_p, + const BIGNUM **out_q, const BIGNUM **out_g); + +// DSA_set0_key sets |dsa|'s public and private key to |pub_key| and |priv_key|, +// respectively, if non-NULL. On success, it takes ownership of each argument +// and returns one. Otherwise, it returns zero. +// +// |priv_key| may be NULL, but |pub_key| must either be non-NULL or already +// configured on |dsa|. +OPENSSL_EXPORT int DSA_set0_key(DSA *dsa, BIGNUM *pub_key, BIGNUM *priv_key); + +// DSA_set0_pqg sets |dsa|'s parameters to |p|, |q|, and |g|, if non-NULL, and +// takes ownership of them. On success, it takes ownership of each argument and +// returns one. Otherwise, it returns zero. +// +// Each argument must either be non-NULL or already configured on |dsa|. +OPENSSL_EXPORT int DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g); + + +// Parameter generation. + +// DSA_generate_parameters_ex generates a set of DSA parameters by following +// the procedure given in FIPS 186-4, appendix A. +// (http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf) +// +// The larger prime will have a length of |bits| (e.g. 2048). The |seed| value +// allows others to generate and verify the same parameters and should be +// random input which is kept for reference. If |out_counter| or |out_h| are +// not NULL then the counter and h value used in the generation are written to +// them. +// +// The |cb| argument is passed to |BN_generate_prime_ex| and is thus called +// during the generation process in order to indicate progress. See the +// comments for that function for details. In addition to the calls made by +// |BN_generate_prime_ex|, |DSA_generate_parameters_ex| will call it with +// |event| equal to 2 and 3 at different stages of the process. +// +// It returns one on success and zero otherwise. +OPENSSL_EXPORT int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, + const uint8_t *seed, + size_t seed_len, int *out_counter, + unsigned long *out_h, + BN_GENCB *cb); + +// DSAparams_dup returns a freshly allocated |DSA| that contains a copy of the +// parameters from |dsa|. It returns NULL on error. +OPENSSL_EXPORT DSA *DSAparams_dup(const DSA *dsa); + + +// Key generation. + +// DSA_generate_key generates a public/private key pair in |dsa|, which must +// already have parameters setup. It returns one on success and zero on +// error. +OPENSSL_EXPORT int DSA_generate_key(DSA *dsa); + + +// Signatures. + +// DSA_SIG_st (aka |DSA_SIG|) contains a DSA signature as a pair of integers. +struct DSA_SIG_st { + BIGNUM *r, *s; +}; + +// DSA_SIG_new returns a freshly allocated, DIG_SIG structure or NULL on error. +// Both |r| and |s| in the signature will be NULL. +OPENSSL_EXPORT DSA_SIG *DSA_SIG_new(void); + +// DSA_SIG_free frees the contents of |sig| and then frees |sig| itself. +OPENSSL_EXPORT void DSA_SIG_free(DSA_SIG *sig); + +// DSA_SIG_get0 sets |*out_r| and |*out_s|, if non-NULL, to the two components +// of |sig|. +OPENSSL_EXPORT void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **out_r, + const BIGNUM **out_s); + +// DSA_SIG_set0 sets |sig|'s components to |r| and |s|, neither of which may be +// NULL. On success, it takes ownership of each argument and returns one. +// Otherwise, it returns zero. +OPENSSL_EXPORT int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +// DSA_do_sign returns a signature of the hash in |digest| by the key in |dsa| +// and returns an allocated, DSA_SIG structure, or NULL on error. +OPENSSL_EXPORT DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, + const DSA *dsa); + +// DSA_do_verify verifies that |sig| is a valid signature, by the public key in +// |dsa|, of the hash in |digest|. It returns one if so, zero if invalid and -1 +// on error. +// +// WARNING: do not use. This function returns -1 for error, 0 for invalid and 1 +// for valid. However, this is dangerously different to the usual OpenSSL +// convention and could be a disaster if a user did |if (DSA_do_verify(...))|. +// Because of this, |DSA_check_signature| is a safer version of this. +// +// TODO(fork): deprecate. +OPENSSL_EXPORT int DSA_do_verify(const uint8_t *digest, size_t digest_len, + DSA_SIG *sig, const DSA *dsa); + +// DSA_do_check_signature sets |*out_valid| to zero. Then it verifies that |sig| +// is a valid signature, by the public key in |dsa| of the hash in |digest| +// and, if so, it sets |*out_valid| to one. +// +// It returns one if it was able to verify the signature as valid or invalid, +// and zero on error. +OPENSSL_EXPORT int DSA_do_check_signature(int *out_valid, const uint8_t *digest, + size_t digest_len, DSA_SIG *sig, + const DSA *dsa); + + +// ASN.1 signatures. +// +// These functions also perform DSA signature operations, but deal with ASN.1 +// encoded signatures as opposed to raw |BIGNUM|s. If you don't know what +// encoding a DSA signature is in, it's probably ASN.1. + +// DSA_sign signs |digest| with the key in |dsa| and writes the resulting +// signature, in ASN.1 form, to |out_sig| and the length of the signature to +// |*out_siglen|. There must be, at least, |DSA_size(dsa)| bytes of space in +// |out_sig|. It returns one on success and zero otherwise. +// +// (The |type| argument is ignored.) +OPENSSL_EXPORT int DSA_sign(int type, const uint8_t *digest, size_t digest_len, + uint8_t *out_sig, unsigned int *out_siglen, + const DSA *dsa); + +// DSA_verify verifies that |sig| is a valid, ASN.1 signature, by the public +// key in |dsa|, of the hash in |digest|. It returns one if so, zero if invalid +// and -1 on error. +// +// (The |type| argument is ignored.) +// +// WARNING: do not use. This function returns -1 for error, 0 for invalid and 1 +// for valid. However, this is dangerously different to the usual OpenSSL +// convention and could be a disaster if a user did |if (DSA_do_verify(...))|. +// Because of this, |DSA_check_signature| is a safer version of this. +// +// TODO(fork): deprecate. +OPENSSL_EXPORT int DSA_verify(int type, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, + size_t sig_len, const DSA *dsa); + +// DSA_check_signature sets |*out_valid| to zero. Then it verifies that |sig| +// is a valid, ASN.1 signature, by the public key in |dsa|, of the hash in +// |digest|. If so, it sets |*out_valid| to one. +// +// It returns one if it was able to verify the signature as valid or invalid, +// and zero on error. +OPENSSL_EXPORT int DSA_check_signature(int *out_valid, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, + size_t sig_len, const DSA *dsa); + +// DSA_size returns the size, in bytes, of an ASN.1 encoded, DSA signature +// generated by |dsa|. Parameters must already have been setup in |dsa|. +OPENSSL_EXPORT int DSA_size(const DSA *dsa); + + +// ASN.1 encoding. + +// DSA_SIG_parse parses a DER-encoded DSA-Sig-Value structure from |cbs| and +// advances |cbs|. It returns a newly-allocated |DSA_SIG| or NULL on error. +OPENSSL_EXPORT DSA_SIG *DSA_SIG_parse(CBS *cbs); + +// DSA_SIG_marshal marshals |sig| as a DER-encoded DSA-Sig-Value and appends the +// result to |cbb|. It returns one on success and zero on error. +OPENSSL_EXPORT int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig); + +// DSA_parse_public_key parses a DER-encoded DSA public key from |cbs| and +// advances |cbs|. It returns a newly-allocated |DSA| or NULL on error. +OPENSSL_EXPORT DSA *DSA_parse_public_key(CBS *cbs); + +// DSA_marshal_public_key marshals |dsa| as a DER-encoded DSA public key and +// appends the result to |cbb|. It returns one on success and zero on +// failure. +OPENSSL_EXPORT int DSA_marshal_public_key(CBB *cbb, const DSA *dsa); + +// DSA_parse_private_key parses a DER-encoded DSA private key from |cbs| and +// advances |cbs|. It returns a newly-allocated |DSA| or NULL on error. +OPENSSL_EXPORT DSA *DSA_parse_private_key(CBS *cbs); + +// DSA_marshal_private_key marshals |dsa| as a DER-encoded DSA private key and +// appends the result to |cbb|. It returns one on success and zero on +// failure. +OPENSSL_EXPORT int DSA_marshal_private_key(CBB *cbb, const DSA *dsa); + +// DSA_parse_parameters parses a DER-encoded Dss-Parms structure (RFC 3279) +// from |cbs| and advances |cbs|. It returns a newly-allocated |DSA| or NULL on +// error. +OPENSSL_EXPORT DSA *DSA_parse_parameters(CBS *cbs); + +// DSA_marshal_parameters marshals |dsa| as a DER-encoded Dss-Parms structure +// (RFC 3279) and appends the result to |cbb|. It returns one on success and +// zero on failure. +OPENSSL_EXPORT int DSA_marshal_parameters(CBB *cbb, const DSA *dsa); + + +// Conversion. + +// DSA_dup_DH returns a |DH| constructed from the parameters of |dsa|. This is +// sometimes needed when Diffie-Hellman parameters are stored in the form of +// DSA parameters. It returns an allocated |DH| on success or NULL on error. +OPENSSL_EXPORT DH *DSA_dup_DH(const DSA *dsa); + + +// ex_data functions. +// +// See |ex_data.h| for details. + +OPENSSL_EXPORT int DSA_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int DSA_set_ex_data(DSA *dsa, int idx, void *arg); +OPENSSL_EXPORT void *DSA_get_ex_data(const DSA *dsa, int idx); + + +// Deprecated functions. + +// d2i_DSA_SIG parses a DER-encoded DSA-Sig-Value structure from |len| bytes at +// |*inp|, as described in |d2i_SAMPLE|. +// +// Use |DSA_SIG_parse| instead. +OPENSSL_EXPORT DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, + long len); + +// i2d_DSA_SIG marshals |in| to a DER-encoded DSA-Sig-Value structure, as +// described in |i2d_SAMPLE|. +// +// Use |DSA_SIG_marshal| instead. +OPENSSL_EXPORT int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp); + +// d2i_DSAPublicKey parses a DER-encoded DSA public key from |len| bytes at +// |*inp|, as described in |d2i_SAMPLE|. +// +// Use |DSA_parse_public_key| instead. +OPENSSL_EXPORT DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len); + +// i2d_DSAPublicKey marshals |in| as a DER-encoded DSA public key, as described +// in |i2d_SAMPLE|. +// +// Use |DSA_marshal_public_key| instead. +OPENSSL_EXPORT int i2d_DSAPublicKey(const DSA *in, uint8_t **outp); + +// d2i_DSAPrivateKey parses a DER-encoded DSA private key from |len| bytes at +// |*inp|, as described in |d2i_SAMPLE|. +// +// Use |DSA_parse_private_key| instead. +OPENSSL_EXPORT DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len); + +// i2d_DSAPrivateKey marshals |in| as a DER-encoded DSA private key, as +// described in |i2d_SAMPLE|. +// +// Use |DSA_marshal_private_key| instead. +OPENSSL_EXPORT int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp); + +// d2i_DSAparams parses a DER-encoded Dss-Parms structure (RFC 3279) from |len| +// bytes at |*inp|, as described in |d2i_SAMPLE|. +// +// Use |DSA_parse_parameters| instead. +OPENSSL_EXPORT DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len); + +// i2d_DSAparams marshals |in|'s parameters as a DER-encoded Dss-Parms structure +// (RFC 3279), as described in |i2d_SAMPLE|. +// +// Use |DSA_marshal_parameters| instead. +OPENSSL_EXPORT int i2d_DSAparams(const DSA *in, uint8_t **outp); + +// DSA_generate_parameters is a deprecated version of +// |DSA_generate_parameters_ex| that creates and returns a |DSA*|. Don't use +// it. +OPENSSL_EXPORT DSA *DSA_generate_parameters(int bits, unsigned char *seed, + int seed_len, int *counter_ret, + unsigned long *h_ret, + void (*callback)(int, int, void *), + void *cb_arg); + + +struct dsa_st { + long version; + BIGNUM *p; + BIGNUM *q; // == 20 + BIGNUM *g; + + BIGNUM *pub_key; // y public key + BIGNUM *priv_key; // x private key + + int flags; + // Normally used to cache montgomery values + CRYPTO_MUTEX method_mont_lock; + BN_MONT_CTX *method_mont_p; + BN_MONT_CTX *method_mont_q; + CRYPTO_refcount_t references; + CRYPTO_EX_DATA ex_data; +}; + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(DSA, DSA_free) +BORINGSSL_MAKE_UP_REF(DSA, DSA_up_ref) +BORINGSSL_MAKE_DELETER(DSA_SIG, DSA_SIG_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define DSA_R_BAD_Q_VALUE 100 +#define DSA_R_MISSING_PARAMETERS 101 +#define DSA_R_MODULUS_TOO_LARGE 102 +#define DSA_R_NEED_NEW_SETUP_VALUES 103 +#define DSA_R_BAD_VERSION 104 +#define DSA_R_DECODE_ERROR 105 +#define DSA_R_ENCODE_ERROR 106 +#define DSA_R_INVALID_PARAMETERS 107 +#define DSA_R_TOO_MANY_ITERATIONS 108 + +#endif // OPENSSL_HEADER_DSA_H diff --git a/lib/boringssl/include/openssl/dtls1.h b/lib/boringssl/include/openssl/dtls1.h new file mode 100644 index 00000000..38ca801c --- /dev/null +++ b/lib/boringssl/include/openssl/dtls1.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ diff --git a/lib/boringssl/include/openssl/e_os2.h b/lib/boringssl/include/openssl/e_os2.h new file mode 100644 index 00000000..f2d8bac8 --- /dev/null +++ b/lib/boringssl/include/openssl/e_os2.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include diff --git a/lib/boringssl/include/openssl/ec.h b/lib/boringssl/include/openssl/ec.h new file mode 100644 index 00000000..dd5259bb --- /dev/null +++ b/lib/boringssl/include/openssl/ec.h @@ -0,0 +1,485 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#ifndef OPENSSL_HEADER_EC_H +#define OPENSSL_HEADER_EC_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Low-level operations on elliptic curves. + + +// point_conversion_form_t enumerates forms, as defined in X9.62 (ECDSA), for +// the encoding of a elliptic curve point (x,y) +typedef enum { + // POINT_CONVERSION_COMPRESSED indicates that the point is encoded as z||x, + // where the octet z specifies which solution of the quadratic equation y + // is. + POINT_CONVERSION_COMPRESSED = 2, + + // POINT_CONVERSION_UNCOMPRESSED indicates that the point is encoded as + // z||x||y, where z is the octet 0x04. + POINT_CONVERSION_UNCOMPRESSED = 4, + + // POINT_CONVERSION_HYBRID indicates that the point is encoded as z||x||y, + // where z specifies which solution of the quadratic equation y is. This is + // not supported by the code and has never been observed in use. + // + // TODO(agl): remove once node.js no longer references this. + POINT_CONVERSION_HYBRID = 6, +} point_conversion_form_t; + + +// Elliptic curve groups. + +// EC_GROUP_new_by_curve_name returns a fresh EC_GROUP object for the elliptic +// curve specified by |nid|, or NULL on unsupported NID or allocation failure. +// +// The supported NIDs are: +// NID_secp224r1 (P-224), +// NID_X9_62_prime256v1 (P-256), +// NID_secp384r1 (P-384), +// NID_secp521r1 (P-521) +// +// If in doubt, use |NID_X9_62_prime256v1|, or see the curve25519.h header for +// more modern primitives. +OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_by_curve_name(int nid); + +// EC_GROUP_free releases a reference to |group|. +OPENSSL_EXPORT void EC_GROUP_free(EC_GROUP *group); + +// EC_GROUP_dup takes a reference to |a| and returns it. +OPENSSL_EXPORT EC_GROUP *EC_GROUP_dup(const EC_GROUP *a); + +// EC_GROUP_cmp returns zero if |a| and |b| are the same group and non-zero +// otherwise. +OPENSSL_EXPORT int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, + BN_CTX *ignored); + +// EC_GROUP_get0_generator returns a pointer to the internal |EC_POINT| object +// in |group| that specifies the generator for the group. +OPENSSL_EXPORT const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group); + +// EC_GROUP_get0_order returns a pointer to the internal |BIGNUM| object in +// |group| that specifies the order of the group. +OPENSSL_EXPORT const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group); + +// EC_GROUP_order_bits returns the number of bits of the order of |group|. +OPENSSL_EXPORT int EC_GROUP_order_bits(const EC_GROUP *group); + +// EC_GROUP_get_cofactor sets |*cofactor| to the cofactor of |group| using +// |ctx|, if it's not NULL. It returns one on success and zero otherwise. +OPENSSL_EXPORT int EC_GROUP_get_cofactor(const EC_GROUP *group, + BIGNUM *cofactor, BN_CTX *ctx); + +// EC_GROUP_get_curve_GFp gets various parameters about a group. It sets +// |*out_p| to the order of the coordinate field and |*out_a| and |*out_b| to +// the parameters of the curve when expressed as y² = x³ + ax + b. Any of the +// output parameters can be NULL. It returns one on success and zero on +// error. +OPENSSL_EXPORT int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, + BIGNUM *out_a, BIGNUM *out_b, + BN_CTX *ctx); + +// EC_GROUP_get_curve_name returns a NID that identifies |group|. +OPENSSL_EXPORT int EC_GROUP_get_curve_name(const EC_GROUP *group); + +// EC_GROUP_get_degree returns the number of bits needed to represent an +// element of the field underlying |group|. +OPENSSL_EXPORT unsigned EC_GROUP_get_degree(const EC_GROUP *group); + +// EC_curve_nid2nist returns the NIST name of the elliptic curve specified by +// |nid|, or NULL if |nid| is not a NIST curve. For example, it returns "P-256" +// for |NID_X9_62_prime256v1|. +OPENSSL_EXPORT const char *EC_curve_nid2nist(int nid); + +// EC_curve_nist2nid returns the NID of the elliptic curve specified by the NIST +// name |name|, or |NID_undef| if |name| is not a recognized name. For example, +// it returns |NID_X9_62_prime256v1| for "P-256". +OPENSSL_EXPORT int EC_curve_nist2nid(const char *name); + + +// Points on elliptic curves. + +// EC_POINT_new returns a fresh |EC_POINT| object in the given group, or NULL +// on error. +OPENSSL_EXPORT EC_POINT *EC_POINT_new(const EC_GROUP *group); + +// EC_POINT_free frees |point| and the data that it points to. +OPENSSL_EXPORT void EC_POINT_free(EC_POINT *point); + +// EC_POINT_copy sets |*dest| equal to |*src|. It returns one on success and +// zero otherwise. +OPENSSL_EXPORT int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src); + +// EC_POINT_dup returns a fresh |EC_POINT| that contains the same values as +// |src|, or NULL on error. +OPENSSL_EXPORT EC_POINT *EC_POINT_dup(const EC_POINT *src, + const EC_GROUP *group); + +// EC_POINT_set_to_infinity sets |point| to be the "point at infinity" for the +// given group. +OPENSSL_EXPORT int EC_POINT_set_to_infinity(const EC_GROUP *group, + EC_POINT *point); + +// EC_POINT_is_at_infinity returns one iff |point| is the point at infinity and +// zero otherwise. +OPENSSL_EXPORT int EC_POINT_is_at_infinity(const EC_GROUP *group, + const EC_POINT *point); + +// EC_POINT_is_on_curve returns one if |point| is an element of |group| and +// and zero otherwise or when an error occurs. This is different from OpenSSL, +// which returns -1 on error. If |ctx| is non-NULL, it may be used. +OPENSSL_EXPORT int EC_POINT_is_on_curve(const EC_GROUP *group, + const EC_POINT *point, BN_CTX *ctx); + +// EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero if +// not equal and -1 on error. If |ctx| is not NULL, it may be used. +OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx); + + +// Point conversion. + +// EC_POINT_get_affine_coordinates_GFp sets |x| and |y| to the affine value of +// |point| using |ctx|, if it's not NULL. It returns one on success and zero +// otherwise. +// +// Either |x| or |y| may be NULL to skip computing that coordinate. This is +// slightly faster in the common case where only the x-coordinate is needed. +OPENSSL_EXPORT int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); + +// EC_POINT_get_affine_coordinates is an alias of +// |EC_POINT_get_affine_coordinates_GFp|. +OPENSSL_EXPORT int EC_POINT_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); + +// EC_POINT_set_affine_coordinates_GFp sets the value of |point| to be +// (|x|, |y|). The |ctx| argument may be used if not NULL. It returns one +// on success or zero on error. It's considered an error if the point is not on +// the curve. +// +// Note that the corresponding function in OpenSSL versions prior to 1.0.2s does +// not check if the point is on the curve. This is a security-critical check, so +// code additionally supporting OpenSSL should repeat the check with +// |EC_POINT_is_on_curve| or check for older OpenSSL versions with +// |OPENSSL_VERSION_NUMBER|. +OPENSSL_EXPORT int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, + BN_CTX *ctx); + +// EC_POINT_set_affine_coordinates is an alias of +// |EC_POINT_set_affine_coordinates_GFp|. +OPENSSL_EXPORT int EC_POINT_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, + BN_CTX *ctx); + +// EC_POINT_point2oct serialises |point| into the X9.62 form given by |form| +// into, at most, |max_out| bytes at |buf|. It returns the number of bytes +// written or zero on error if |buf| is non-NULL, else the number of bytes +// needed. The |ctx| argument may be used if not NULL. +OPENSSL_EXPORT size_t EC_POINT_point2oct(const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + uint8_t *buf, size_t max_out, + BN_CTX *ctx); + +// EC_POINT_point2buf serialises |point| into the X9.62 form given by |form| to +// a newly-allocated buffer and sets |*out_buf| to point to it. It returns the +// length of the result on success or zero on error. The caller must release +// |*out_buf| with |OPENSSL_free| when done. +OPENSSL_EXPORT size_t EC_POINT_point2buf(const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + uint8_t **out_buf, BN_CTX *ctx); + +// EC_POINT_point2cbb behaves like |EC_POINT_point2oct| but appends the +// serialised point to |cbb|. It returns one on success and zero on error. +OPENSSL_EXPORT int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + BN_CTX *ctx); + +// EC_POINT_oct2point sets |point| from |len| bytes of X9.62 format +// serialisation in |buf|. It returns one on success and zero on error. The +// |ctx| argument may be used if not NULL. It's considered an error if |buf| +// does not represent a point on the curve. +OPENSSL_EXPORT int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, + const uint8_t *buf, size_t len, + BN_CTX *ctx); + +// EC_POINT_set_compressed_coordinates_GFp sets |point| to equal the point with +// the given |x| coordinate and the y coordinate specified by |y_bit| (see +// X9.62). It returns one on success and zero otherwise. +OPENSSL_EXPORT int EC_POINT_set_compressed_coordinates_GFp( + const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, int y_bit, + BN_CTX *ctx); + + +// Group operations. + +// EC_POINT_add sets |r| equal to |a| plus |b|. It returns one on success and +// zero otherwise. If |ctx| is not NULL, it may be used. +OPENSSL_EXPORT int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, + const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx); + +// EC_POINT_dbl sets |r| equal to |a| plus |a|. It returns one on success and +// zero otherwise. If |ctx| is not NULL, it may be used. +OPENSSL_EXPORT int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, + const EC_POINT *a, BN_CTX *ctx); + +// EC_POINT_invert sets |a| equal to minus |a|. It returns one on success and +// zero otherwise. If |ctx| is not NULL, it may be used. +OPENSSL_EXPORT int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, + BN_CTX *ctx); + +// EC_POINT_mul sets r = generator*n + q*m. It returns one on success and zero +// otherwise. If |ctx| is not NULL, it may be used. +OPENSSL_EXPORT int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *n, const EC_POINT *q, + const BIGNUM *m, BN_CTX *ctx); + + +// Hash-to-curve. +// +// The following functions implement primitives from +// draft-irtf-cfrg-hash-to-curve-16. The |dst| parameter in each function is the +// domain separation tag and must be unique for each protocol and between the +// |hash_to_curve| and |hash_to_scalar| variants. See section 3.1 of the spec +// for additional guidance on this parameter. + +// EC_hash_to_curve_p256_xmd_sha256_sswu hashes |msg| to a point on |group| and +// writes the result to |out|, implementing the P256_XMD:SHA-256_SSWU_RO_ suite +// from draft-irtf-cfrg-hash-to-curve-16. It returns one on success and zero on +// error. +OPENSSL_EXPORT int EC_hash_to_curve_p256_xmd_sha256_sswu( + const EC_GROUP *group, EC_POINT *out, const uint8_t *dst, size_t dst_len, + const uint8_t *msg, size_t msg_len); + +// EC_hash_to_curve_p384_xmd_sha384_sswu hashes |msg| to a point on |group| and +// writes the result to |out|, implementing the P384_XMD:SHA-384_SSWU_RO_ suite +// from draft-irtf-cfrg-hash-to-curve-16. It returns one on success and zero on +// error. +OPENSSL_EXPORT int EC_hash_to_curve_p384_xmd_sha384_sswu( + const EC_GROUP *group, EC_POINT *out, const uint8_t *dst, size_t dst_len, + const uint8_t *msg, size_t msg_len); + + +// Deprecated functions. + +// EC_GROUP_new_curve_GFp creates a new, arbitrary elliptic curve group based +// on the equation y² = x³ + a·x + b. It returns the new group or NULL on +// error. +// +// This new group has no generator. It is an error to use a generator-less group +// with any functions except for |EC_GROUP_free|, |EC_POINT_new|, +// |EC_POINT_set_affine_coordinates_GFp|, and |EC_GROUP_set_generator|. +// +// |EC_GROUP|s returned by this function will always compare as unequal via +// |EC_GROUP_cmp| (even to themselves). |EC_GROUP_get_curve_name| will always +// return |NID_undef|. +// +// This function is provided for compatibility with some legacy applications +// only. Avoid using arbitrary curves and use |EC_GROUP_new_by_curve_name| +// instead. This ensures the result meets preconditions necessary for +// elliptic curve algorithms to function correctly and securely. +// +// Given invalid parameters, this function may fail or it may return an +// |EC_GROUP| which breaks these preconditions. Subsequent operations may then +// return arbitrary, incorrect values. Callers should not pass +// attacker-controlled values to this function. +OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, + const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); + +// EC_GROUP_set_generator sets the generator for |group| to |generator|, which +// must have the given order and cofactor. It may only be used with |EC_GROUP| +// objects returned by |EC_GROUP_new_curve_GFp| and may only be used once on +// each group. |generator| must have been created using |group|. +OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group, + const EC_POINT *generator, + const BIGNUM *order, + const BIGNUM *cofactor); + +// EC_GROUP_get_order sets |*order| to the order of |group|, if it's not +// NULL. It returns one on success and zero otherwise. |ctx| is ignored. Use +// |EC_GROUP_get0_order| instead. +OPENSSL_EXPORT int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, + BN_CTX *ctx); + +#define OPENSSL_EC_EXPLICIT_CURVE 0 +#define OPENSSL_EC_NAMED_CURVE 1 + +// EC_GROUP_set_asn1_flag does nothing. +OPENSSL_EXPORT void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); + +// EC_GROUP_get_asn1_flag returns |OPENSSL_EC_NAMED_CURVE|. +OPENSSL_EXPORT int EC_GROUP_get_asn1_flag(const EC_GROUP *group); + +typedef struct ec_method_st EC_METHOD; + +// EC_GROUP_method_of returns a dummy non-NULL pointer. +OPENSSL_EXPORT const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group); + +// EC_METHOD_get_field_type returns NID_X9_62_prime_field. +OPENSSL_EXPORT int EC_METHOD_get_field_type(const EC_METHOD *meth); + +// EC_GROUP_set_point_conversion_form aborts the process if |form| is not +// |POINT_CONVERSION_UNCOMPRESSED| and otherwise does nothing. +OPENSSL_EXPORT void EC_GROUP_set_point_conversion_form( + EC_GROUP *group, point_conversion_form_t form); + +// EC_builtin_curve describes a supported elliptic curve. +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; + +// EC_get_builtin_curves writes at most |max_num_curves| elements to +// |out_curves| and returns the total number that it would have written, had +// |max_num_curves| been large enough. +// +// The |EC_builtin_curve| items describe the supported elliptic curves. +OPENSSL_EXPORT size_t EC_get_builtin_curves(EC_builtin_curve *out_curves, + size_t max_num_curves); + +// EC_POINT_clear_free calls |EC_POINT_free|. +OPENSSL_EXPORT void EC_POINT_clear_free(EC_POINT *point); + + +#if defined(__cplusplus) +} // extern C +#endif + +// Old code expects to get EC_KEY from ec.h. +#include + +#if defined(__cplusplus) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(EC_POINT, EC_POINT_free) +BORINGSSL_MAKE_DELETER(EC_GROUP, EC_GROUP_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define EC_R_BUFFER_TOO_SMALL 100 +#define EC_R_COORDINATES_OUT_OF_RANGE 101 +#define EC_R_D2I_ECPKPARAMETERS_FAILURE 102 +#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 103 +#define EC_R_GROUP2PKPARAMETERS_FAILURE 104 +#define EC_R_I2D_ECPKPARAMETERS_FAILURE 105 +#define EC_R_INCOMPATIBLE_OBJECTS 106 +#define EC_R_INVALID_COMPRESSED_POINT 107 +#define EC_R_INVALID_COMPRESSION_BIT 108 +#define EC_R_INVALID_ENCODING 109 +#define EC_R_INVALID_FIELD 110 +#define EC_R_INVALID_FORM 111 +#define EC_R_INVALID_GROUP_ORDER 112 +#define EC_R_INVALID_PRIVATE_KEY 113 +#define EC_R_MISSING_PARAMETERS 114 +#define EC_R_MISSING_PRIVATE_KEY 115 +#define EC_R_NON_NAMED_CURVE 116 +#define EC_R_NOT_INITIALIZED 117 +#define EC_R_PKPARAMETERS2GROUP_FAILURE 118 +#define EC_R_POINT_AT_INFINITY 119 +#define EC_R_POINT_IS_NOT_ON_CURVE 120 +#define EC_R_SLOT_FULL 121 +#define EC_R_UNDEFINED_GENERATOR 122 +#define EC_R_UNKNOWN_GROUP 123 +#define EC_R_UNKNOWN_ORDER 124 +#define EC_R_WRONG_ORDER 125 +#define EC_R_BIGNUM_OUT_OF_RANGE 126 +#define EC_R_WRONG_CURVE_PARAMETERS 127 +#define EC_R_DECODE_ERROR 128 +#define EC_R_ENCODE_ERROR 129 +#define EC_R_GROUP_MISMATCH 130 +#define EC_R_INVALID_COFACTOR 131 +#define EC_R_PUBLIC_KEY_VALIDATION_FAILED 132 +#define EC_R_INVALID_SCALAR 133 + +#endif // OPENSSL_HEADER_EC_H diff --git a/lib/boringssl/include/openssl/ec_key.h b/lib/boringssl/include/openssl/ec_key.h new file mode 100644 index 00000000..00986cf4 --- /dev/null +++ b/lib/boringssl/include/openssl/ec_key.h @@ -0,0 +1,386 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#ifndef OPENSSL_HEADER_EC_KEY_H +#define OPENSSL_HEADER_EC_KEY_H + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// ec_key.h contains functions that handle elliptic-curve points that are +// public/private keys. + + +// EC key objects. +// +// An |EC_KEY| object represents a public or private EC key. A given object may +// be used concurrently on multiple threads by non-mutating functions, provided +// no other thread is concurrently calling a mutating function. Unless otherwise +// documented, functions which take a |const| pointer are non-mutating and +// functions which take a non-|const| pointer are mutating. + +// EC_KEY_new returns a fresh |EC_KEY| object or NULL on error. +OPENSSL_EXPORT EC_KEY *EC_KEY_new(void); + +// EC_KEY_new_method acts the same as |EC_KEY_new|, but takes an explicit +// |ENGINE|. +OPENSSL_EXPORT EC_KEY *EC_KEY_new_method(const ENGINE *engine); + +// EC_KEY_new_by_curve_name returns a fresh EC_KEY for group specified by |nid| +// or NULL on error. +OPENSSL_EXPORT EC_KEY *EC_KEY_new_by_curve_name(int nid); + +// EC_KEY_free frees all the data owned by |key| and |key| itself. +OPENSSL_EXPORT void EC_KEY_free(EC_KEY *key); + +// EC_KEY_dup returns a fresh copy of |src| or NULL on error. +OPENSSL_EXPORT EC_KEY *EC_KEY_dup(const EC_KEY *src); + +// EC_KEY_up_ref increases the reference count of |key| and returns one. It does +// not mutate |key| for thread-safety purposes and may be used concurrently. +OPENSSL_EXPORT int EC_KEY_up_ref(EC_KEY *key); + +// EC_KEY_is_opaque returns one if |key| is opaque and doesn't expose its key +// material. Otherwise it return zero. +OPENSSL_EXPORT int EC_KEY_is_opaque(const EC_KEY *key); + +// EC_KEY_get0_group returns a pointer to the |EC_GROUP| object inside |key|. +OPENSSL_EXPORT const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); + +// EC_KEY_set_group sets the |EC_GROUP| object that |key| will use to |group|. +// It returns one on success and zero if |key| is already configured with a +// different group. +OPENSSL_EXPORT int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group); + +// EC_KEY_get0_private_key returns a pointer to the private key inside |key|. +OPENSSL_EXPORT const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key); + +// EC_KEY_set_private_key sets the private key of |key| to |priv|. It returns +// one on success and zero otherwise. |key| must already have had a group +// configured (see |EC_KEY_set_group| and |EC_KEY_new_by_curve_name|). +OPENSSL_EXPORT int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv); + +// EC_KEY_get0_public_key returns a pointer to the public key point inside +// |key|. +OPENSSL_EXPORT const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); + +// EC_KEY_set_public_key sets the public key of |key| to |pub|, by copying it. +// It returns one on success and zero otherwise. |key| must already have had a +// group configured (see |EC_KEY_set_group| and |EC_KEY_new_by_curve_name|), and +// |pub| must also belong to that group. +OPENSSL_EXPORT int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); + +#define EC_PKEY_NO_PARAMETERS 0x001 +#define EC_PKEY_NO_PUBKEY 0x002 + +// EC_KEY_get_enc_flags returns the encoding flags for |key|, which is a +// bitwise-OR of |EC_PKEY_*| values. +OPENSSL_EXPORT unsigned EC_KEY_get_enc_flags(const EC_KEY *key); + +// EC_KEY_set_enc_flags sets the encoding flags for |key|, which is a +// bitwise-OR of |EC_PKEY_*| values. +OPENSSL_EXPORT void EC_KEY_set_enc_flags(EC_KEY *key, unsigned flags); + +// EC_KEY_get_conv_form returns the conversation form that will be used by +// |key|. +OPENSSL_EXPORT point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); + +// EC_KEY_set_conv_form sets the conversion form to be used by |key|. +OPENSSL_EXPORT void EC_KEY_set_conv_form(EC_KEY *key, + point_conversion_form_t cform); + +// EC_KEY_check_key performs several checks on |key| (possibly including an +// expensive check that the public key is in the primary subgroup). It returns +// one if all checks pass and zero otherwise. If it returns zero then detail +// about the problem can be found on the error stack. +OPENSSL_EXPORT int EC_KEY_check_key(const EC_KEY *key); + +// EC_KEY_check_fips performs both a signing pairwise consistency test +// (FIPS 140-2 4.9.2) and the consistency test from SP 800-56Ar3 section +// 5.6.2.1.4. It returns one if it passes and zero otherwise. +OPENSSL_EXPORT int EC_KEY_check_fips(const EC_KEY *key); + +// EC_KEY_set_public_key_affine_coordinates sets the public key in |key| to +// (|x|, |y|). It returns one on success and zero on error. It's considered an +// error if |x| and |y| do not represent a point on |key|'s curve. +OPENSSL_EXPORT int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, + const BIGNUM *x, + const BIGNUM *y); + +// EC_KEY_oct2key decodes |len| bytes from |in| as an EC public key in X9.62 +// form. |key| must already have a group configured. On success, it sets the +// public key in |key| to the result and returns one. Otherwise, it returns +// zero. +OPENSSL_EXPORT int EC_KEY_oct2key(EC_KEY *key, const uint8_t *in, size_t len, + BN_CTX *ctx); + +// EC_KEY_key2buf behaves like |EC_POINT_point2buf|, except it encodes the +// public key in |key|. +OPENSSL_EXPORT size_t EC_KEY_key2buf(const EC_KEY *key, + point_conversion_form_t form, + uint8_t **out_buf, BN_CTX *ctx); + +// EC_KEY_oct2priv decodes a big-endian, zero-padded integer from |len| bytes +// from |in| and sets |key|'s private key to the result. It returns one on +// success and zero on error. The input must be padded to the size of |key|'s +// group order. +OPENSSL_EXPORT int EC_KEY_oct2priv(EC_KEY *key, const uint8_t *in, size_t len); + +// EC_KEY_priv2oct serializes |key|'s private key as a big-endian integer, +// zero-padded to the size of |key|'s group order and writes the result to at +// most |max_out| bytes of |out|. It returns the number of bytes written on +// success and zero on error. If |out| is NULL, it returns the number of bytes +// needed without writing anything. +OPENSSL_EXPORT size_t EC_KEY_priv2oct(const EC_KEY *key, uint8_t *out, + size_t max_out); + +// EC_KEY_priv2buf behaves like |EC_KEY_priv2oct| but sets |*out_buf| to a +// newly-allocated buffer containing the result. It returns the size of the +// result on success and zero on error. The caller must release |*out_buf| with +// |OPENSSL_free| when done. +OPENSSL_EXPORT size_t EC_KEY_priv2buf(const EC_KEY *key, uint8_t **out_buf); + + +// Key generation. + +// EC_KEY_generate_key generates a random, private key, calculates the +// corresponding public key and stores both in |key|. It returns one on success +// or zero otherwise. +OPENSSL_EXPORT int EC_KEY_generate_key(EC_KEY *key); + +// EC_KEY_generate_key_fips behaves like |EC_KEY_generate_key| but performs +// additional checks for FIPS compliance. This function is applicable when +// generating keys for either signing/verification or key agreement because +// both types of consistency check (PCT) are performed. +OPENSSL_EXPORT int EC_KEY_generate_key_fips(EC_KEY *key); + +// EC_KEY_derive_from_secret deterministically derives a private key for |group| +// from an input secret using HKDF-SHA256. It returns a newly-allocated |EC_KEY| +// on success or NULL on error. |secret| must not be used in any other +// algorithm. If using a base secret for multiple operations, derive separate +// values with a KDF such as HKDF first. +// +// Note this function implements an arbitrary derivation scheme, rather than any +// particular standard one. New protocols are recommended to use X25519 and +// Ed25519, which have standard byte import functions. See +// |X25519_public_from_private| and |ED25519_keypair_from_seed|. +OPENSSL_EXPORT EC_KEY *EC_KEY_derive_from_secret(const EC_GROUP *group, + const uint8_t *secret, + size_t secret_len); + + +// Serialisation. + +// EC_KEY_parse_private_key parses a DER-encoded ECPrivateKey structure (RFC +// 5915) from |cbs| and advances |cbs|. It returns a newly-allocated |EC_KEY| or +// NULL on error. If |group| is non-null, the parameters field of the +// ECPrivateKey may be omitted (but must match |group| if present). Otherwise, +// the parameters field is required. +OPENSSL_EXPORT EC_KEY *EC_KEY_parse_private_key(CBS *cbs, + const EC_GROUP *group); + +// EC_KEY_marshal_private_key marshals |key| as a DER-encoded ECPrivateKey +// structure (RFC 5915) and appends the result to |cbb|. It returns one on +// success and zero on failure. |enc_flags| is a combination of |EC_PKEY_*| +// values and controls whether corresponding fields are omitted. +OPENSSL_EXPORT int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key, + unsigned enc_flags); + +// EC_KEY_parse_curve_name parses a DER-encoded OBJECT IDENTIFIER as a curve +// name from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP| +// or NULL on error. +OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs); + +// EC_KEY_marshal_curve_name marshals |group| as a DER-encoded OBJECT IDENTIFIER +// and appends the result to |cbb|. It returns one on success and zero on +// failure. +OPENSSL_EXPORT int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group); + +// EC_KEY_parse_parameters parses a DER-encoded ECParameters structure (RFC +// 5480) from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP| +// or NULL on error. It supports the namedCurve and specifiedCurve options, but +// use of specifiedCurve is deprecated. Use |EC_KEY_parse_curve_name| +// instead. +OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_parameters(CBS *cbs); + + +// ex_data functions. +// +// These functions are wrappers. See |ex_data.h| for details. + +OPENSSL_EXPORT int EC_KEY_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int EC_KEY_set_ex_data(EC_KEY *r, int idx, void *arg); +OPENSSL_EXPORT void *EC_KEY_get_ex_data(const EC_KEY *r, int idx); + + +// ECDSA method. + +// ECDSA_FLAG_OPAQUE specifies that this ECDSA_METHOD does not expose its key +// material. This may be set if, for instance, it is wrapping some other crypto +// API, like a platform key store. +#define ECDSA_FLAG_OPAQUE 1 + +// ecdsa_method_st is a structure of function pointers for implementing ECDSA. +// See engine.h. +struct ecdsa_method_st { + struct openssl_method_common_st common; + + void *app_data; + + int (*init)(EC_KEY *key); + int (*finish)(EC_KEY *key); + + // group_order_size returns the number of bytes needed to represent the order + // of the group. This is used to calculate the maximum size of an ECDSA + // signature in |ECDSA_size|. + size_t (*group_order_size)(const EC_KEY *key); + + // sign matches the arguments and behaviour of |ECDSA_sign|. + int (*sign)(const uint8_t *digest, size_t digest_len, uint8_t *sig, + unsigned int *sig_len, EC_KEY *eckey); + + int flags; +}; + + +// Deprecated functions. + +// EC_KEY_set_asn1_flag does nothing. +OPENSSL_EXPORT void EC_KEY_set_asn1_flag(EC_KEY *key, int flag); + +// d2i_ECPrivateKey parses a DER-encoded ECPrivateKey structure (RFC 5915) from +// |len| bytes at |*inp|, as described in |d2i_SAMPLE|. On input, if |*out_key| +// is non-NULL and has a group configured, the parameters field may be omitted +// but must match that group if present. +// +// Use |EC_KEY_parse_private_key| instead. +OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey(EC_KEY **out_key, const uint8_t **inp, + long len); + +// i2d_ECPrivateKey marshals |key| as a DER-encoded ECPrivateKey structure (RFC +// 5915), as described in |i2d_SAMPLE|. +// +// Use |EC_KEY_marshal_private_key| instead. +OPENSSL_EXPORT int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp); + +// d2i_ECParameters parses a DER-encoded ECParameters structure (RFC 5480) from +// |len| bytes at |*inp|, as described in |d2i_SAMPLE|. +// +// Use |EC_KEY_parse_parameters| or |EC_KEY_parse_curve_name| instead. +OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, + long len); + +// i2d_ECParameters marshals |key|'s parameters as a DER-encoded OBJECT +// IDENTIFIER, as described in |i2d_SAMPLE|. +// +// Use |EC_KEY_marshal_curve_name| instead. +OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp); + +// o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into +// |*out_key|. Note that this differs from the d2i format in that |*out_key| +// must be non-NULL with a group set. On successful exit, |*inp| is advanced by +// |len| bytes. It returns |*out_key| or NULL on error. +// +// Use |EC_POINT_oct2point| instead. +OPENSSL_EXPORT EC_KEY *o2i_ECPublicKey(EC_KEY **out_key, const uint8_t **inp, + long len); + +// i2o_ECPublicKey marshals an EC point from |key|, as described in +// |i2d_SAMPLE|, except it returns zero on error instead of a negative value. +// +// Use |EC_POINT_point2cbb| instead. +OPENSSL_EXPORT int i2o_ECPublicKey(const EC_KEY *key, unsigned char **outp); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(EC_KEY, EC_KEY_free) +BORINGSSL_MAKE_UP_REF(EC_KEY, EC_KEY_up_ref) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#endif // OPENSSL_HEADER_EC_KEY_H diff --git a/lib/boringssl/include/openssl/ecdh.h b/lib/boringssl/include/openssl/ecdh.h new file mode 100644 index 00000000..0130ccc2 --- /dev/null +++ b/lib/boringssl/include/openssl/ecdh.h @@ -0,0 +1,118 @@ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * The Elliptic Curve Public-Key Crypto Library (ECC Code) included + * herein is developed by SUN MICROSYSTEMS, INC., and is contributed + * to the OpenSSL project. + * + * The ECC Code is licensed pursuant to the OpenSSL open source + * license provided below. + * + * The ECDH software is originally written by Douglas Stebila of + * Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_ECDH_H +#define OPENSSL_HEADER_ECDH_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Elliptic curve Diffie-Hellman. + + +// ECDH_compute_key calculates the shared key between |pub_key| and |priv_key|. +// If |kdf| is not NULL, then it is called with the bytes of the shared key and +// the parameter |out|. When |kdf| returns, the value of |*outlen| becomes the +// return value. Otherwise, as many bytes of the shared key as will fit are +// copied directly to, at most, |outlen| bytes at |out|. It returns the number +// of bytes written to |out|, or -1 on error. +OPENSSL_EXPORT int ECDH_compute_key( + void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *priv_key, + void *(*kdf)(const void *in, size_t inlen, void *out, size_t *outlen)); + +// ECDH_compute_key_fips calculates the shared key between |pub_key| and +// |priv_key| and hashes it with the appropriate SHA function for |out_len|. The +// only value values for |out_len| are thus 24 (SHA-224), 32 (SHA-256), 48 +// (SHA-384), and 64 (SHA-512). It returns one on success and zero on error. +// +// Note that the return value is different to |ECDH_compute_key|: it returns an +// error flag (as is common for BoringSSL) rather than the number of bytes +// written. +// +// This function allows the FIPS module to compute an ECDH and KDF within the +// module boundary without taking an arbitrary function pointer for the KDF, +// which isn't very FIPSy. +OPENSSL_EXPORT int ECDH_compute_key_fips(uint8_t *out, size_t out_len, + const EC_POINT *pub_key, + const EC_KEY *priv_key); + + +#if defined(__cplusplus) +} // extern C +#endif + +#define ECDH_R_KDF_FAILED 100 +#define ECDH_R_NO_PRIVATE_VALUE 101 +#define ECDH_R_POINT_ARITHMETIC_FAILURE 102 +#define ECDH_R_UNKNOWN_DIGEST_LENGTH 103 + +#endif // OPENSSL_HEADER_ECDH_H diff --git a/lib/boringssl/include/openssl/ecdsa.h b/lib/boringssl/include/openssl/ecdsa.h new file mode 100644 index 00000000..56be1547 --- /dev/null +++ b/lib/boringssl/include/openssl/ecdsa.h @@ -0,0 +1,237 @@ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_ECDSA_H +#define OPENSSL_HEADER_ECDSA_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// ECDSA contains functions for signing and verifying with the Digital Signature +// Algorithm over elliptic curves. + + +// Signing and verifying. + +// ECDSA_sign signs |digest_len| bytes from |digest| with |key| and writes the +// resulting signature to |sig|, which must have |ECDSA_size(key)| bytes of +// space. On successful exit, |*sig_len| is set to the actual number of bytes +// written. The |type| argument should be zero. It returns one on success and +// zero otherwise. +// +// WARNING: |digest| must be the output of some hash function on the data to be +// signed. Passing unhashed inputs will not result in a secure signature scheme. +OPENSSL_EXPORT int ECDSA_sign(int type, const uint8_t *digest, + size_t digest_len, uint8_t *sig, + unsigned int *sig_len, const EC_KEY *key); + +// ECDSA_verify verifies that |sig_len| bytes from |sig| constitute a valid +// signature by |key| of |digest|. (The |type| argument should be zero.) It +// returns one on success or zero if the signature is invalid or an error +// occurred. +// +// WARNING: |digest| must be the output of some hash function on the data to be +// verified. Passing unhashed inputs will not result in a secure signature +// scheme. +OPENSSL_EXPORT int ECDSA_verify(int type, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, + size_t sig_len, const EC_KEY *key); + +// ECDSA_size returns the maximum size of an ECDSA signature using |key|. It +// returns zero if |key| is NULL or if it doesn't have a group set. +OPENSSL_EXPORT size_t ECDSA_size(const EC_KEY *key); + + +// Low-level signing and verification. +// +// Low-level functions handle signatures as |ECDSA_SIG| structures which allow +// the two values in an ECDSA signature to be handled separately. + +struct ecdsa_sig_st { + BIGNUM *r; + BIGNUM *s; +}; + +// ECDSA_SIG_new returns a fresh |ECDSA_SIG| structure or NULL on error. +OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_new(void); + +// ECDSA_SIG_free frees |sig| its member |BIGNUM|s. +OPENSSL_EXPORT void ECDSA_SIG_free(ECDSA_SIG *sig); + +// ECDSA_SIG_get0_r returns the r component of |sig|. +OPENSSL_EXPORT const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig); + +// ECDSA_SIG_get0_s returns the s component of |sig|. +OPENSSL_EXPORT const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig); + +// ECDSA_SIG_get0 sets |*out_r| and |*out_s|, if non-NULL, to the two +// components of |sig|. +OPENSSL_EXPORT void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **out_r, + const BIGNUM **out_s); + +// ECDSA_SIG_set0 sets |sig|'s components to |r| and |s|, neither of which may +// be NULL. On success, it takes ownership of each argument and returns one. +// Otherwise, it returns zero. +OPENSSL_EXPORT int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +// ECDSA_do_sign signs |digest_len| bytes from |digest| with |key| and returns +// the resulting signature structure, or NULL on error. +// +// WARNING: |digest| must be the output of some hash function on the data to be +// signed. Passing unhashed inputs will not result in a secure signature scheme. +OPENSSL_EXPORT ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, + size_t digest_len, const EC_KEY *key); + +// ECDSA_do_verify verifies that |sig| constitutes a valid signature by |key| +// of |digest|. It returns one on success or zero if the signature is invalid +// or on error. +// +// WARNING: |digest| must be the output of some hash function on the data to be +// verified. Passing unhashed inputs will not result in a secure signature +// scheme. +OPENSSL_EXPORT int ECDSA_do_verify(const uint8_t *digest, size_t digest_len, + const ECDSA_SIG *sig, const EC_KEY *key); + + +// ASN.1 functions. + +// ECDSA_SIG_parse parses a DER-encoded ECDSA-Sig-Value structure from |cbs| and +// advances |cbs|. It returns a newly-allocated |ECDSA_SIG| or NULL on error. +OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs); + +// ECDSA_SIG_from_bytes parses |in| as a DER-encoded ECDSA-Sig-Value structure. +// It returns a newly-allocated |ECDSA_SIG| structure or NULL on error. +OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_from_bytes(const uint8_t *in, + size_t in_len); + +// ECDSA_SIG_marshal marshals |sig| as a DER-encoded ECDSA-Sig-Value and appends +// the result to |cbb|. It returns one on success and zero on error. +OPENSSL_EXPORT int ECDSA_SIG_marshal(CBB *cbb, const ECDSA_SIG *sig); + +// ECDSA_SIG_to_bytes marshals |sig| as a DER-encoded ECDSA-Sig-Value and, on +// success, sets |*out_bytes| to a newly allocated buffer containing the result +// and returns one. Otherwise, it returns zero. The result should be freed with +// |OPENSSL_free|. +OPENSSL_EXPORT int ECDSA_SIG_to_bytes(uint8_t **out_bytes, size_t *out_len, + const ECDSA_SIG *sig); + +// ECDSA_SIG_max_len returns the maximum length of a DER-encoded ECDSA-Sig-Value +// structure for a group whose order is represented in |order_len| bytes, or +// zero on overflow. +OPENSSL_EXPORT size_t ECDSA_SIG_max_len(size_t order_len); + + +// Testing-only functions. + +// ECDSA_sign_with_nonce_and_leak_private_key_for_testing behaves like +// |ECDSA_do_sign| but uses |nonce| for the ECDSA nonce 'k', instead of a random +// value. |nonce| is interpreted as a big-endian integer. It must be reduced +// modulo the group order and padded with zeros up to |BN_num_bytes(order)| +// bytes. +// +// WARNING: This function is only exported for testing purposes, when using test +// vectors or fuzzing strategies. It must not be used outside tests and may leak +// any private keys it is used with. +OPENSSL_EXPORT ECDSA_SIG * +ECDSA_sign_with_nonce_and_leak_private_key_for_testing(const uint8_t *digest, + size_t digest_len, + const EC_KEY *eckey, + const uint8_t *nonce, + size_t nonce_len); + + +// Deprecated functions. + +// d2i_ECDSA_SIG parses aa DER-encoded ECDSA-Sig-Value structure from |len| +// bytes at |*inp|, as described in |d2i_SAMPLE|. +// +// Use |ECDSA_SIG_parse| instead. +OPENSSL_EXPORT ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp, + long len); + +// i2d_ECDSA_SIG marshals |sig| as a DER-encoded ECDSA-Sig-Value, as described +// in |i2d_SAMPLE|. +// +// Use |ECDSA_SIG_marshal| instead. +OPENSSL_EXPORT int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(ECDSA_SIG, ECDSA_SIG_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define ECDSA_R_BAD_SIGNATURE 100 +#define ECDSA_R_MISSING_PARAMETERS 101 +#define ECDSA_R_NEED_NEW_SETUP_VALUES 102 +#define ECDSA_R_NOT_IMPLEMENTED 103 +#define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED 104 +#define ECDSA_R_ENCODE_ERROR 105 +#define ECDSA_R_TOO_MANY_ITERATIONS 106 + +#endif // OPENSSL_HEADER_ECDSA_H diff --git a/lib/boringssl/include/openssl/engine.h b/lib/boringssl/include/openssl/engine.h new file mode 100644 index 00000000..ce60de46 --- /dev/null +++ b/lib/boringssl/include/openssl/engine.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_ENGINE_H +#define OPENSSL_HEADER_ENGINE_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Engines are collections of methods. Methods are tables of function pointers, +// defined for certain algorithms, that allow operations on those algorithms to +// be overridden via a callback. This can be used, for example, to implement an +// RSA* that forwards operations to a hardware module. +// +// Methods are reference counted but |ENGINE|s are not. When creating a method, +// you should zero the whole structure and fill in the function pointers that +// you wish before setting it on an |ENGINE|. Any functions pointers that +// are NULL indicate that the default behaviour should be used. + + +// Allocation and destruction. + +// ENGINE_new returns an empty ENGINE that uses the default method for all +// algorithms. +OPENSSL_EXPORT ENGINE *ENGINE_new(void); + +// ENGINE_free decrements the reference counts for all methods linked from +// |engine| and frees |engine| itself. It returns one. +OPENSSL_EXPORT int ENGINE_free(ENGINE *engine); + + +// Method accessors. +// +// Method accessors take a method pointer and the size of the structure. The +// size allows for ABI compatibility in the case that the method structure is +// extended with extra elements at the end. Methods are always copied by the +// set functions. +// +// Set functions return one on success and zero on allocation failure. + +OPENSSL_EXPORT int ENGINE_set_RSA_method(ENGINE *engine, + const RSA_METHOD *method, + size_t method_size); +OPENSSL_EXPORT RSA_METHOD *ENGINE_get_RSA_method(const ENGINE *engine); + +OPENSSL_EXPORT int ENGINE_set_ECDSA_method(ENGINE *engine, + const ECDSA_METHOD *method, + size_t method_size); +OPENSSL_EXPORT ECDSA_METHOD *ENGINE_get_ECDSA_method(const ENGINE *engine); + + +// Generic method functions. +// +// These functions take a void* type but actually operate on all method +// structures. + +// METHOD_ref increments the reference count of |method|. This is a no-op for +// now because all methods are currently static. +void METHOD_ref(void *method); + +// METHOD_unref decrements the reference count of |method| and frees it if the +// reference count drops to zero. This is a no-op for now because all methods +// are currently static. +void METHOD_unref(void *method); + + +// Private functions. + +// openssl_method_common_st contains the common part of all method structures. +// This must be the first member of all method structures. +struct openssl_method_common_st { + int references; // dummy – not used. + char is_static; +}; + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(ENGINE, ENGINE_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define ENGINE_R_OPERATION_NOT_SUPPORTED 100 + +#endif // OPENSSL_HEADER_ENGINE_H diff --git a/lib/boringssl/include/openssl/err.h b/lib/boringssl/include/openssl/err.h new file mode 100644 index 00000000..0ec71b17 --- /dev/null +++ b/lib/boringssl/include/openssl/err.h @@ -0,0 +1,494 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_ERR_H +#define OPENSSL_HEADER_ERR_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Error queue handling functions. +// +// Errors in OpenSSL are generally signaled by the return value of a function. +// When a function fails it may add an entry to a per-thread error queue, +// which is managed by the functions in this header. +// +// Each error contains: +// 1) The library (i.e. ec, pem, rsa) which created it. +// 2) The file and line number of the call that added the error. +// 3) A pointer to some error specific data, which may be NULL. +// +// The library identifier and reason code are packed in a uint32_t and there +// exist various functions for unpacking it. +// +// The typical behaviour is that an error will occur deep in a call queue and +// that code will push an error onto the error queue. As the error queue +// unwinds, other functions will push their own errors. Thus, the "least +// recent" error is the most specific and the other errors will provide a +// backtrace of sorts. + + +// Startup and shutdown. + +// ERR_load_BIO_strings does nothing. +// +// TODO(fork): remove. libjingle calls this. +OPENSSL_EXPORT void ERR_load_BIO_strings(void); + +// ERR_load_ERR_strings does nothing. +OPENSSL_EXPORT void ERR_load_ERR_strings(void); + +// ERR_load_crypto_strings does nothing. +OPENSSL_EXPORT void ERR_load_crypto_strings(void); + +// ERR_load_RAND_strings does nothing. +OPENSSL_EXPORT void ERR_load_RAND_strings(void); + +// ERR_free_strings does nothing. +OPENSSL_EXPORT void ERR_free_strings(void); + + +// Reading and formatting errors. + +// ERR_GET_LIB returns the library code for the error. This is one of +// the |ERR_LIB_*| values. +OPENSSL_INLINE int ERR_GET_LIB(uint32_t packed_error) { + return (int)((packed_error >> 24) & 0xff); +} + +// ERR_GET_REASON returns the reason code for the error. This is one of +// library-specific |LIB_R_*| values where |LIB| is the library (see +// |ERR_GET_LIB|). Note that reason codes are specific to the library. +OPENSSL_INLINE int ERR_GET_REASON(uint32_t packed_error) { + return (int)(packed_error & 0xfff); +} + +// ERR_get_error gets the packed error code for the least recent error and +// removes that error from the queue. If there are no errors in the queue then +// it returns zero. +OPENSSL_EXPORT uint32_t ERR_get_error(void); + +// ERR_get_error_line acts like |ERR_get_error|, except that the file and line +// number of the call that added the error are also returned. +OPENSSL_EXPORT uint32_t ERR_get_error_line(const char **file, int *line); + +// ERR_FLAG_STRING means that the |data| member is a NUL-terminated string that +// can be printed. This is always set if |data| is non-NULL. +#define ERR_FLAG_STRING 1 + +// ERR_FLAG_MALLOCED is passed into |ERR_set_error_data| to indicate that |data| +// was allocated with |OPENSSL_malloc|. +// +// It is, separately, returned in |*flags| from |ERR_get_error_line_data| to +// indicate that |*data| has a non-static lifetime, but this lifetime is still +// managed by the library. The caller must not call |OPENSSL_free| or |free| on +// |data|. +#define ERR_FLAG_MALLOCED 2 + +// ERR_get_error_line_data acts like |ERR_get_error_line|, but also returns the +// error-specific data pointer and flags. The flags are a bitwise-OR of +// |ERR_FLAG_*| values. The error-specific data is owned by the error queue +// and the pointer becomes invalid after the next call that affects the same +// thread's error queue. If |*flags| contains |ERR_FLAG_STRING| then |*data| is +// human-readable. +OPENSSL_EXPORT uint32_t ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags); + +// The "peek" functions act like the |ERR_get_error| functions, above, but they +// do not remove the error from the queue. +OPENSSL_EXPORT uint32_t ERR_peek_error(void); +OPENSSL_EXPORT uint32_t ERR_peek_error_line(const char **file, int *line); +OPENSSL_EXPORT uint32_t ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags); + +// The "peek last" functions act like the "peek" functions, above, except that +// they return the most recent error. +OPENSSL_EXPORT uint32_t ERR_peek_last_error(void); +OPENSSL_EXPORT uint32_t ERR_peek_last_error_line(const char **file, int *line); +OPENSSL_EXPORT uint32_t ERR_peek_last_error_line_data(const char **file, + int *line, + const char **data, + int *flags); + +// ERR_error_string_n generates a human-readable string representing +// |packed_error|, places it at |buf|, and returns |buf|. It writes at most +// |len| bytes (including the terminating NUL) and truncates the string if +// necessary. If |len| is greater than zero then |buf| is always NUL terminated. +// +// The string will have the following format: +// +// error:[error code]:[library name]:OPENSSL_internal:[reason string] +// +// error code is an 8 digit hexadecimal number; library name and reason string +// are ASCII text. +OPENSSL_EXPORT char *ERR_error_string_n(uint32_t packed_error, char *buf, + size_t len); + +// ERR_lib_error_string returns a string representation of the library that +// generated |packed_error|, or a placeholder string is the library is +// unrecognized. +OPENSSL_EXPORT const char *ERR_lib_error_string(uint32_t packed_error); + +// ERR_reason_error_string returns a string representation of the reason for +// |packed_error|, or a placeholder string if the reason is unrecognized. +OPENSSL_EXPORT const char *ERR_reason_error_string(uint32_t packed_error); + +// ERR_print_errors_callback_t is the type of a function used by +// |ERR_print_errors_cb|. It takes a pointer to a human readable string (and +// its length) that describes an entry in the error queue. The |ctx| argument +// is an opaque pointer given to |ERR_print_errors_cb|. +// +// It should return one on success or zero on error, which will stop the +// iteration over the error queue. +typedef int (*ERR_print_errors_callback_t)(const char *str, size_t len, + void *ctx); + +// ERR_print_errors_cb clears the current thread's error queue, calling +// |callback| with a string representation of each error, from the least recent +// to the most recent error. +// +// The string will have the following format (which differs from +// |ERR_error_string|): +// +// [thread id]:error:[error code]:[library name]:OPENSSL_internal:[reason string]:[file]:[line number]:[optional string data] +// +// The callback can return one to continue the iteration or zero to stop it. +// The |ctx| argument is an opaque value that is passed through to the +// callback. +OPENSSL_EXPORT void ERR_print_errors_cb(ERR_print_errors_callback_t callback, + void *ctx); + +// ERR_print_errors_fp clears the current thread's error queue, printing each +// error to |file|. See |ERR_print_errors_cb| for the format. +OPENSSL_EXPORT void ERR_print_errors_fp(FILE *file); + + +// Clearing errors. + +// ERR_clear_error clears the error queue for the current thread. +OPENSSL_EXPORT void ERR_clear_error(void); + +// ERR_set_mark "marks" the most recent error for use with |ERR_pop_to_mark|. +// It returns one if an error was marked and zero if there are no errors. +OPENSSL_EXPORT int ERR_set_mark(void); + +// ERR_pop_to_mark removes errors from the most recent to the least recent +// until (and not including) a "marked" error. It returns zero if no marked +// error was found (and thus all errors were removed) and one otherwise. Errors +// are marked using |ERR_set_mark|. +OPENSSL_EXPORT int ERR_pop_to_mark(void); + + +// Custom errors. + +// ERR_get_next_error_library returns a value suitable for passing as the +// |library| argument to |ERR_put_error|. This is intended for code that wishes +// to push its own, non-standard errors to the error queue. +OPENSSL_EXPORT int ERR_get_next_error_library(void); + + +// Built-in library and reason codes. + +// The following values are built-in library codes. +enum { + ERR_LIB_NONE = 1, + ERR_LIB_SYS, + ERR_LIB_BN, + ERR_LIB_RSA, + ERR_LIB_DH, + ERR_LIB_EVP, + ERR_LIB_BUF, + ERR_LIB_OBJ, + ERR_LIB_PEM, + ERR_LIB_DSA, + ERR_LIB_X509, + ERR_LIB_ASN1, + ERR_LIB_CONF, + ERR_LIB_CRYPTO, + ERR_LIB_EC, + ERR_LIB_SSL, + ERR_LIB_BIO, + ERR_LIB_PKCS7, + ERR_LIB_PKCS8, + ERR_LIB_X509V3, + ERR_LIB_RAND, + ERR_LIB_ENGINE, + ERR_LIB_OCSP, + ERR_LIB_UI, + ERR_LIB_COMP, + ERR_LIB_ECDSA, + ERR_LIB_ECDH, + ERR_LIB_HMAC, + ERR_LIB_DIGEST, + ERR_LIB_CIPHER, + ERR_LIB_HKDF, + ERR_LIB_TRUST_TOKEN, + ERR_LIB_USER, + ERR_NUM_LIBS +}; + +// The following reason codes used to denote an error occuring in another +// library. They are sometimes used for a stack trace. +#define ERR_R_SYS_LIB ERR_LIB_SYS +#define ERR_R_BN_LIB ERR_LIB_BN +#define ERR_R_RSA_LIB ERR_LIB_RSA +#define ERR_R_DH_LIB ERR_LIB_DH +#define ERR_R_EVP_LIB ERR_LIB_EVP +#define ERR_R_BUF_LIB ERR_LIB_BUF +#define ERR_R_OBJ_LIB ERR_LIB_OBJ +#define ERR_R_PEM_LIB ERR_LIB_PEM +#define ERR_R_DSA_LIB ERR_LIB_DSA +#define ERR_R_X509_LIB ERR_LIB_X509 +#define ERR_R_ASN1_LIB ERR_LIB_ASN1 +#define ERR_R_CONF_LIB ERR_LIB_CONF +#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO +#define ERR_R_EC_LIB ERR_LIB_EC +#define ERR_R_SSL_LIB ERR_LIB_SSL +#define ERR_R_BIO_LIB ERR_LIB_BIO +#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7 +#define ERR_R_PKCS8_LIB ERR_LIB_PKCS8 +#define ERR_R_X509V3_LIB ERR_LIB_X509V3 +#define ERR_R_RAND_LIB ERR_LIB_RAND +#define ERR_R_DSO_LIB ERR_LIB_DSO +#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE +#define ERR_R_OCSP_LIB ERR_LIB_OCSP +#define ERR_R_UI_LIB ERR_LIB_UI +#define ERR_R_COMP_LIB ERR_LIB_COMP +#define ERR_R_ECDSA_LIB ERR_LIB_ECDSA +#define ERR_R_ECDH_LIB ERR_LIB_ECDH +#define ERR_R_STORE_LIB ERR_LIB_STORE +#define ERR_R_FIPS_LIB ERR_LIB_FIPS +#define ERR_R_CMS_LIB ERR_LIB_CMS +#define ERR_R_TS_LIB ERR_LIB_TS +#define ERR_R_HMAC_LIB ERR_LIB_HMAC +#define ERR_R_JPAKE_LIB ERR_LIB_JPAKE +#define ERR_R_USER_LIB ERR_LIB_USER +#define ERR_R_DIGEST_LIB ERR_LIB_DIGEST +#define ERR_R_CIPHER_LIB ERR_LIB_CIPHER +#define ERR_R_HKDF_LIB ERR_LIB_HKDF +#define ERR_R_TRUST_TOKEN_LIB ERR_LIB_TRUST_TOKEN + +// The following values are global reason codes. They may occur in any library. +#define ERR_R_FATAL 64 +#define ERR_R_MALLOC_FAILURE (1 | ERR_R_FATAL) +#define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2 | ERR_R_FATAL) +#define ERR_R_PASSED_NULL_PARAMETER (3 | ERR_R_FATAL) +#define ERR_R_INTERNAL_ERROR (4 | ERR_R_FATAL) +#define ERR_R_OVERFLOW (5 | ERR_R_FATAL) + + +// Deprecated functions. + +// ERR_remove_state calls |ERR_clear_error|. +OPENSSL_EXPORT void ERR_remove_state(unsigned long pid); + +// ERR_remove_thread_state clears the error queue for the current thread if +// |tid| is NULL. Otherwise it calls |assert(0)|, because it's no longer +// possible to delete the error queue for other threads. +// +// Use |ERR_clear_error| instead. Note error queues are deleted automatically on +// thread exit. You do not need to call this function to release memory. +OPENSSL_EXPORT void ERR_remove_thread_state(const CRYPTO_THREADID *tid); + +// ERR_func_error_string returns the string "OPENSSL_internal". +OPENSSL_EXPORT const char *ERR_func_error_string(uint32_t packed_error); + +// ERR_error_string behaves like |ERR_error_string_n| but |len| is implicitly +// |ERR_ERROR_STRING_BUF_LEN|. +// +// Additionally, if |buf| is NULL, the error string is placed in a static buffer +// which is returned. This is not thread-safe and only exists for backwards +// compatibility with legacy callers. The static buffer will be overridden by +// calls in other threads. +// +// Use |ERR_error_string_n| instead. +// +// TODO(fork): remove this function. +OPENSSL_EXPORT char *ERR_error_string(uint32_t packed_error, char *buf); +#define ERR_ERROR_STRING_BUF_LEN 120 + +// ERR_GET_FUNC returns zero. BoringSSL errors do not report a function code. +OPENSSL_INLINE int ERR_GET_FUNC(uint32_t packed_error) { + (void)packed_error; + return 0; +} + +// ERR_TXT_* are provided for compatibility with code that assumes that it's +// using OpenSSL. +#define ERR_TXT_STRING ERR_FLAG_STRING +#define ERR_TXT_MALLOCED ERR_FLAG_MALLOCED + + +// Private functions. + +// ERR_clear_system_error clears the system's error value (i.e. errno). +OPENSSL_EXPORT void ERR_clear_system_error(void); + +// OPENSSL_PUT_ERROR is used by OpenSSL code to add an error to the error +// queue. +#define OPENSSL_PUT_ERROR(library, reason) \ + ERR_put_error(ERR_LIB_##library, 0, reason, __FILE__, __LINE__) + +// OPENSSL_PUT_SYSTEM_ERROR is used by OpenSSL code to add an error from the +// operating system to the error queue. +// TODO(fork): include errno. +#define OPENSSL_PUT_SYSTEM_ERROR() \ + ERR_put_error(ERR_LIB_SYS, 0, 0, __FILE__, __LINE__); + +// ERR_put_error adds an error to the error queue, dropping the least recent +// error if necessary for space reasons. +OPENSSL_EXPORT void ERR_put_error(int library, int unused, int reason, + const char *file, unsigned line); + +// ERR_add_error_data takes a variable number (|count|) of const char* +// pointers, concatenates them and sets the result as the data on the most +// recent error. +OPENSSL_EXPORT void ERR_add_error_data(unsigned count, ...); + +// ERR_add_error_dataf takes a printf-style format and arguments, and sets the +// result as the data on the most recent error. +OPENSSL_EXPORT void ERR_add_error_dataf(const char *format, ...) + OPENSSL_PRINTF_FORMAT_FUNC(1, 2); + +// ERR_set_error_data sets the data on the most recent error to |data|, which +// must be a NUL-terminated string. |flags| must contain |ERR_FLAG_STRING|. If +// |flags| contains |ERR_FLAG_MALLOCED|, this function takes ownership of +// |data|, which must have been allocated with |OPENSSL_malloc|. Otherwise, it +// saves a copy of |data|. +// +// Note this differs from OpenSSL which, when |ERR_FLAG_MALLOCED| is unset, +// saves the pointer as-is and requires it remain valid for the lifetime of the +// address space. +OPENSSL_EXPORT void ERR_set_error_data(char *data, int flags); + +// ERR_NUM_ERRORS is one more than the limit of the number of errors in the +// queue. +#define ERR_NUM_ERRORS 16 + +#define ERR_PACK(lib, reason) \ + (((((uint32_t)(lib)) & 0xff) << 24) | ((((uint32_t)(reason)) & 0xfff))) + +// OPENSSL_DECLARE_ERROR_REASON is used by util/make_errors.h (which generates +// the error defines) to recognise that an additional reason value is needed. +// This is needed when the reason value is used outside of an +// |OPENSSL_PUT_ERROR| macro. The resulting define will be +// ${lib}_R_${reason}. +#define OPENSSL_DECLARE_ERROR_REASON(lib, reason) + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_ERR_H diff --git a/lib/boringssl/include/openssl/evp.h b/lib/boringssl/include/openssl/evp.h new file mode 100644 index 00000000..f69cf752 --- /dev/null +++ b/lib/boringssl/include/openssl/evp.h @@ -0,0 +1,1075 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_EVP_H +#define OPENSSL_HEADER_EVP_H + +#include + +#include +#include + +// OpenSSL included digest and cipher functions in this header so we include +// them for users that still expect that. +// +// TODO(fork): clean up callers so that they include what they use. +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// EVP abstracts over public/private key algorithms. + + +// Public key objects. +// +// An |EVP_PKEY| object represents a public or private key. A given object may +// be used concurrently on multiple threads by non-mutating functions, provided +// no other thread is concurrently calling a mutating function. Unless otherwise +// documented, functions which take a |const| pointer are non-mutating and +// functions which take a non-|const| pointer are mutating. + +// EVP_PKEY_new creates a new, empty public-key object and returns it or NULL +// on allocation failure. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new(void); + +// EVP_PKEY_free frees all data referenced by |pkey| and then frees |pkey| +// itself. +OPENSSL_EXPORT void EVP_PKEY_free(EVP_PKEY *pkey); + +// EVP_PKEY_up_ref increments the reference count of |pkey| and returns one. It +// does not mutate |pkey| for thread-safety purposes and may be used +// concurrently. +OPENSSL_EXPORT int EVP_PKEY_up_ref(EVP_PKEY *pkey); + +// EVP_PKEY_is_opaque returns one if |pkey| is opaque. Opaque keys are backed by +// custom implementations which do not expose key material and parameters. It is +// an error to attempt to duplicate, export, or compare an opaque key. +OPENSSL_EXPORT int EVP_PKEY_is_opaque(const EVP_PKEY *pkey); + +// EVP_PKEY_cmp compares |a| and |b| and returns one if they are equal, zero if +// not and a negative number on error. +// +// WARNING: this differs from the traditional return value of a "cmp" +// function. +OPENSSL_EXPORT int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); + +// EVP_PKEY_copy_parameters sets the parameters of |to| to equal the parameters +// of |from|. It returns one on success and zero on error. +OPENSSL_EXPORT int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); + +// EVP_PKEY_missing_parameters returns one if |pkey| is missing needed +// parameters or zero if not, or if the algorithm doesn't take parameters. +OPENSSL_EXPORT int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey); + +// EVP_PKEY_size returns the maximum size, in bytes, of a signature signed by +// |pkey|. For an RSA key, this returns the number of bytes needed to represent +// the modulus. For an EC key, this returns the maximum size of a DER-encoded +// ECDSA signature. +OPENSSL_EXPORT int EVP_PKEY_size(const EVP_PKEY *pkey); + +// EVP_PKEY_bits returns the "size", in bits, of |pkey|. For an RSA key, this +// returns the bit length of the modulus. For an EC key, this returns the bit +// length of the group order. +OPENSSL_EXPORT int EVP_PKEY_bits(const EVP_PKEY *pkey); + +// EVP_PKEY_id returns the type of |pkey|, which is one of the |EVP_PKEY_*| +// values. +OPENSSL_EXPORT int EVP_PKEY_id(const EVP_PKEY *pkey); + +// EVP_PKEY_type returns |nid| if |nid| is a known key type and |NID_undef| +// otherwise. +OPENSSL_EXPORT int EVP_PKEY_type(int nid); + + +// Getting and setting concrete public key types. +// +// The following functions get and set the underlying public key in an +// |EVP_PKEY| object. The |set1| functions take an additional reference to the +// underlying key and return one on success or zero if |key| is NULL. The +// |assign| functions adopt the caller's reference and return one on success or +// zero if |key| is NULL. The |get1| functions return a fresh reference to the +// underlying object or NULL if |pkey| is not of the correct type. The |get0| +// functions behave the same but return a non-owning pointer. +// +// The |get0| and |get1| functions take |const| pointers and are thus +// non-mutating for thread-safety purposes, but mutating functions on the +// returned lower-level objects are considered to also mutate the |EVP_PKEY| and +// may not be called concurrently with other operations on the |EVP_PKEY|. + +OPENSSL_EXPORT int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key); +OPENSSL_EXPORT int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key); +OPENSSL_EXPORT RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey); +OPENSSL_EXPORT RSA *EVP_PKEY_get1_RSA(const EVP_PKEY *pkey); + +OPENSSL_EXPORT int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key); +OPENSSL_EXPORT int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key); +OPENSSL_EXPORT DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey); +OPENSSL_EXPORT DSA *EVP_PKEY_get1_DSA(const EVP_PKEY *pkey); + +OPENSSL_EXPORT int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key); +OPENSSL_EXPORT int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key); +OPENSSL_EXPORT EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey); +OPENSSL_EXPORT EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey); + +#define EVP_PKEY_NONE NID_undef +#define EVP_PKEY_RSA NID_rsaEncryption +#define EVP_PKEY_RSA_PSS NID_rsassaPss +#define EVP_PKEY_DSA NID_dsa +#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey +#define EVP_PKEY_ED25519 NID_ED25519 +#define EVP_PKEY_X25519 NID_X25519 +#define EVP_PKEY_HKDF NID_hkdf + +// EVP_PKEY_assign sets the underlying key of |pkey| to |key|, which must be of +// the given type. It returns one if successful or zero if the |type| argument +// is not one of the |EVP_PKEY_*| values or if |key| is NULL. +OPENSSL_EXPORT int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); + +// EVP_PKEY_set_type sets the type of |pkey| to |type|. It returns one if +// successful or zero if the |type| argument is not one of the |EVP_PKEY_*| +// values. If |pkey| is NULL, it simply reports whether the type is known. +OPENSSL_EXPORT int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); + +// EVP_PKEY_cmp_parameters compares the parameters of |a| and |b|. It returns +// one if they match, zero if not, or a negative number of on error. +// +// WARNING: the return value differs from the usual return value convention. +OPENSSL_EXPORT int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, + const EVP_PKEY *b); + + +// ASN.1 functions + +// EVP_parse_public_key decodes a DER-encoded SubjectPublicKeyInfo structure +// (RFC 5280) from |cbs| and advances |cbs|. It returns a newly-allocated +// |EVP_PKEY| or NULL on error. If the key is an EC key, the curve is guaranteed +// to be set. +// +// The caller must check the type of the parsed public key to ensure it is +// suitable and validate other desired key properties such as RSA modulus size +// or EC curve. +OPENSSL_EXPORT EVP_PKEY *EVP_parse_public_key(CBS *cbs); + +// EVP_marshal_public_key marshals |key| as a DER-encoded SubjectPublicKeyInfo +// structure (RFC 5280) and appends the result to |cbb|. It returns one on +// success and zero on error. +OPENSSL_EXPORT int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key); + +// EVP_parse_private_key decodes a DER-encoded PrivateKeyInfo structure (RFC +// 5208) from |cbs| and advances |cbs|. It returns a newly-allocated |EVP_PKEY| +// or NULL on error. +// +// The caller must check the type of the parsed private key to ensure it is +// suitable and validate other desired key properties such as RSA modulus size +// or EC curve. In particular, RSA private key operations scale cubicly, so +// applications accepting RSA private keys from external sources may need to +// bound key sizes (use |EVP_PKEY_bits| or |RSA_bits|) to avoid a DoS vector. +// +// A PrivateKeyInfo ends with an optional set of attributes. These are not +// processed and so this function will silently ignore any trailing data in the +// structure. +OPENSSL_EXPORT EVP_PKEY *EVP_parse_private_key(CBS *cbs); + +// EVP_marshal_private_key marshals |key| as a DER-encoded PrivateKeyInfo +// structure (RFC 5208) and appends the result to |cbb|. It returns one on +// success and zero on error. +OPENSSL_EXPORT int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key); + + +// Raw keys +// +// Some keys types support a "raw" serialization. Currently the only supported +// raw formats are X25519 and Ed25519, where the formats are those specified in +// RFC 7748 and RFC 8032, respectively. Note the RFC 8032 private key format is +// the 32-byte prefix of |ED25519_sign|'s 64-byte private key. + +// EVP_PKEY_new_raw_private_key returns a newly allocated |EVP_PKEY| wrapping a +// private key of the specified type. It returns one on success and zero on +// error. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *unused, + const uint8_t *in, + size_t len); + +// EVP_PKEY_new_raw_public_key returns a newly allocated |EVP_PKEY| wrapping a +// public key of the specified type. It returns one on success and zero on +// error. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *unused, + const uint8_t *in, + size_t len); + +// EVP_PKEY_get_raw_private_key outputs the private key for |pkey| in raw form. +// If |out| is NULL, it sets |*out_len| to the size of the raw private key. +// Otherwise, it writes at most |*out_len| bytes to |out| and sets |*out_len| to +// the number of bytes written. +// +// It returns one on success and zero if |pkey| has no private key, the key +// type does not support a raw format, or the buffer is too small. +OPENSSL_EXPORT int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, + uint8_t *out, size_t *out_len); + +// EVP_PKEY_get_raw_public_key outputs the public key for |pkey| in raw form. +// If |out| is NULL, it sets |*out_len| to the size of the raw public key. +// Otherwise, it writes at most |*out_len| bytes to |out| and sets |*out_len| to +// the number of bytes written. +// +// It returns one on success and zero if |pkey| has no public key, the key +// type does not support a raw format, or the buffer is too small. +OPENSSL_EXPORT int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, + uint8_t *out, size_t *out_len); + + +// Signing + +// EVP_DigestSignInit sets up |ctx| for a signing operation with |type| and +// |pkey|. The |ctx| argument must have been initialised with +// |EVP_MD_CTX_init|. If |pctx| is not NULL, the |EVP_PKEY_CTX| of the signing +// operation will be written to |*pctx|; this can be used to set alternative +// signing options. +// +// For single-shot signing algorithms which do not use a pre-hash, such as +// Ed25519, |type| should be NULL. The |EVP_MD_CTX| itself is unused but is +// present so the API is uniform. See |EVP_DigestSign|. +// +// This function does not mutate |pkey| for thread-safety purposes and may be +// used concurrently with other non-mutating functions on |pkey|. +// +// It returns one on success, or zero on error. +OPENSSL_EXPORT int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); + +// EVP_DigestSignUpdate appends |len| bytes from |data| to the data which will +// be signed in |EVP_DigestSignFinal|. It returns one. +// +// This function performs a streaming signing operation and will fail for +// signature algorithms which do not support this. Use |EVP_DigestSign| for a +// single-shot operation. +OPENSSL_EXPORT int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +// EVP_DigestSignFinal signs the data that has been included by one or more +// calls to |EVP_DigestSignUpdate|. If |out_sig| is NULL then |*out_sig_len| is +// set to the maximum number of output bytes. Otherwise, on entry, +// |*out_sig_len| must contain the length of the |out_sig| buffer. If the call +// is successful, the signature is written to |out_sig| and |*out_sig_len| is +// set to its length. +// +// This function performs a streaming signing operation and will fail for +// signature algorithms which do not support this. Use |EVP_DigestSign| for a +// single-shot operation. +// +// It returns one on success, or zero on error. +OPENSSL_EXPORT int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig, + size_t *out_sig_len); + +// EVP_DigestSign signs |data_len| bytes from |data| using |ctx|. If |out_sig| +// is NULL then |*out_sig_len| is set to the maximum number of output +// bytes. Otherwise, on entry, |*out_sig_len| must contain the length of the +// |out_sig| buffer. If the call is successful, the signature is written to +// |out_sig| and |*out_sig_len| is set to its length. +// +// It returns one on success and zero on error. +OPENSSL_EXPORT int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, + size_t *out_sig_len, const uint8_t *data, + size_t data_len); + + +// Verifying + +// EVP_DigestVerifyInit sets up |ctx| for a signature verification operation +// with |type| and |pkey|. The |ctx| argument must have been initialised with +// |EVP_MD_CTX_init|. If |pctx| is not NULL, the |EVP_PKEY_CTX| of the signing +// operation will be written to |*pctx|; this can be used to set alternative +// signing options. +// +// For single-shot signing algorithms which do not use a pre-hash, such as +// Ed25519, |type| should be NULL. The |EVP_MD_CTX| itself is unused but is +// present so the API is uniform. See |EVP_DigestVerify|. +// +// This function does not mutate |pkey| for thread-safety purposes and may be +// used concurrently with other non-mutating functions on |pkey|. +// +// It returns one on success, or zero on error. +OPENSSL_EXPORT int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); + +// EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which +// will be verified by |EVP_DigestVerifyFinal|. It returns one. +// +// This function performs streaming signature verification and will fail for +// signature algorithms which do not support this. Use |EVP_PKEY_verify_message| +// for a single-shot verification. +OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +// EVP_DigestVerifyFinal verifies that |sig_len| bytes of |sig| are a valid +// signature for the data that has been included by one or more calls to +// |EVP_DigestVerifyUpdate|. It returns one on success and zero otherwise. +// +// This function performs streaming signature verification and will fail for +// signature algorithms which do not support this. Use |EVP_PKEY_verify_message| +// for a single-shot verification. +OPENSSL_EXPORT int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, + size_t sig_len); + +// EVP_DigestVerify verifies that |sig_len| bytes from |sig| are a valid +// signature for |data|. It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig, + size_t sig_len, const uint8_t *data, + size_t len); + + +// Signing (old functions) + +// EVP_SignInit_ex configures |ctx|, which must already have been initialised, +// for a fresh signing operation using the hash function |type|. It returns one +// on success and zero otherwise. +// +// (In order to initialise |ctx|, either obtain it initialised with +// |EVP_MD_CTX_create|, or use |EVP_MD_CTX_init|.) +OPENSSL_EXPORT int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *impl); + +// EVP_SignInit is a deprecated version of |EVP_SignInit_ex|. +// +// TODO(fork): remove. +OPENSSL_EXPORT int EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type); + +// EVP_SignUpdate appends |len| bytes from |data| to the data which will be +// signed in |EVP_SignFinal|. +OPENSSL_EXPORT int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +// EVP_SignFinal signs the data that has been included by one or more calls to +// |EVP_SignUpdate|, using the key |pkey|, and writes it to |sig|. On entry, +// |sig| must point to at least |EVP_PKEY_size(pkey)| bytes of space. The +// actual size of the signature is written to |*out_sig_len|. +// +// It returns one on success and zero otherwise. +// +// It does not modify |ctx|, thus it's possible to continue to use |ctx| in +// order to sign a longer message. It also does not mutate |pkey| for +// thread-safety purposes and may be used concurrently with other non-mutating +// functions on |pkey|. +OPENSSL_EXPORT int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig, + unsigned int *out_sig_len, EVP_PKEY *pkey); + + +// Verifying (old functions) + +// EVP_VerifyInit_ex configures |ctx|, which must already have been +// initialised, for a fresh signature verification operation using the hash +// function |type|. It returns one on success and zero otherwise. +// +// (In order to initialise |ctx|, either obtain it initialised with +// |EVP_MD_CTX_create|, or use |EVP_MD_CTX_init|.) +OPENSSL_EXPORT int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *impl); + +// EVP_VerifyInit is a deprecated version of |EVP_VerifyInit_ex|. +// +// TODO(fork): remove. +OPENSSL_EXPORT int EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type); + +// EVP_VerifyUpdate appends |len| bytes from |data| to the data which will be +// signed in |EVP_VerifyFinal|. +OPENSSL_EXPORT int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +// EVP_VerifyFinal verifies that |sig_len| bytes of |sig| are a valid +// signature, by |pkey|, for the data that has been included by one or more +// calls to |EVP_VerifyUpdate|. +// +// It returns one on success and zero otherwise. +// +// It does not modify |ctx|, thus it's possible to continue to use |ctx| in +// order to verify a longer message. It also does not mutate |pkey| for +// thread-safety purposes and may be used concurrently with other non-mutating +// functions on |pkey|. +OPENSSL_EXPORT int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, + size_t sig_len, EVP_PKEY *pkey); + + +// Printing + +// EVP_PKEY_print_public prints a textual representation of the public key in +// |pkey| to |out|. Returns one on success or zero otherwise. +OPENSSL_EXPORT int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + +// EVP_PKEY_print_private prints a textual representation of the private key in +// |pkey| to |out|. Returns one on success or zero otherwise. +OPENSSL_EXPORT int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + +// EVP_PKEY_print_params prints a textual representation of the parameters in +// |pkey| to |out|. Returns one on success or zero otherwise. +OPENSSL_EXPORT int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + + +// Password stretching. +// +// Password stretching functions take a low-entropy password and apply a slow +// function that results in a key suitable for use in symmetric +// cryptography. + +// PKCS5_PBKDF2_HMAC computes |iterations| iterations of PBKDF2 of |password| +// and |salt|, using |digest|, and outputs |key_len| bytes to |out_key|. It +// returns one on success and zero on allocation failure or if iterations is 0. +OPENSSL_EXPORT int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len, + const uint8_t *salt, size_t salt_len, + unsigned iterations, const EVP_MD *digest, + size_t key_len, uint8_t *out_key); + +// PKCS5_PBKDF2_HMAC_SHA1 is the same as PKCS5_PBKDF2_HMAC, but with |digest| +// fixed to |EVP_sha1|. +OPENSSL_EXPORT int PKCS5_PBKDF2_HMAC_SHA1(const char *password, + size_t password_len, + const uint8_t *salt, size_t salt_len, + unsigned iterations, size_t key_len, + uint8_t *out_key); + +// EVP_PBE_scrypt expands |password| into a secret key of length |key_len| using +// scrypt, as described in RFC 7914, and writes the result to |out_key|. It +// returns one on success and zero on allocation failure, if the memory required +// for the operation exceeds |max_mem|, or if any of the parameters are invalid +// as described below. +// +// |N|, |r|, and |p| are as described in RFC 7914 section 6. They determine the +// cost of the operation. If |max_mem| is zero, a defult limit of 32MiB will be +// used. +// +// The parameters are considered invalid under any of the following conditions: +// - |r| or |p| are zero +// - |p| > (2^30 - 1) / |r| +// - |N| is not a power of two +// - |N| > 2^32 +// - |N| > 2^(128 * |r| / 8) +OPENSSL_EXPORT int EVP_PBE_scrypt(const char *password, size_t password_len, + const uint8_t *salt, size_t salt_len, + uint64_t N, uint64_t r, uint64_t p, + size_t max_mem, uint8_t *out_key, + size_t key_len); + + +// Public key contexts. +// +// |EVP_PKEY_CTX| objects hold the context of an operation (e.g. signing or +// encrypting) that uses a public key. + +// EVP_PKEY_CTX_new allocates a fresh |EVP_PKEY_CTX| for use with |pkey|. It +// returns the context or NULL on error. +OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); + +// EVP_PKEY_CTX_new_id allocates a fresh |EVP_PKEY_CTX| for a key of type |id| +// (e.g. |EVP_PKEY_HMAC|). This can be used for key generation where +// |EVP_PKEY_CTX_new| can't be used because there isn't an |EVP_PKEY| to pass +// it. It returns the context or NULL on error. +OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); + +// EVP_PKEY_CTX_free frees |ctx| and the data it owns. +OPENSSL_EXPORT void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_CTX_dup allocates a fresh |EVP_PKEY_CTX| and sets it equal to the +// state of |ctx|. It returns the fresh |EVP_PKEY_CTX| or NULL on error. +OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_CTX_get0_pkey returns the |EVP_PKEY| associated with |ctx|. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_sign_init initialises an |EVP_PKEY_CTX| for a signing operation. It +// should be called before |EVP_PKEY_sign|. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_sign signs |digest_len| bytes from |digest| using |ctx|. If |sig| is +// NULL, the maximum size of the signature is written to |out_sig_len|. +// Otherwise, |*sig_len| must contain the number of bytes of space available at +// |sig|. If sufficient, the signature will be written to |sig| and |*sig_len| +// updated with the true length. This function will fail for signature +// algorithms like Ed25519 that do not support signing pre-hashed inputs. +// +// WARNING: |digest| must be the output of some hash function on the data to be +// signed. Passing unhashed inputs will not result in a secure signature scheme. +// Use |EVP_DigestSignInit| to sign an unhashed input. +// +// WARNING: Setting |sig| to NULL only gives the maximum size of the +// signature. The actual signature may be smaller. +// +// It returns one on success or zero on error. (Note: this differs from +// OpenSSL, which can also return negative values to indicate an error. ) +OPENSSL_EXPORT int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, + size_t *sig_len, const uint8_t *digest, + size_t digest_len); + +// EVP_PKEY_verify_init initialises an |EVP_PKEY_CTX| for a signature +// verification operation. It should be called before |EVP_PKEY_verify|. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_verify verifies that |sig_len| bytes from |sig| are a valid +// signature for |digest|. This function will fail for signature +// algorithms like Ed25519 that do not support signing pre-hashed inputs. +// +// WARNING: |digest| must be the output of some hash function on the data to be +// verified. Passing unhashed inputs will not result in a secure signature +// scheme. Use |EVP_DigestVerifyInit| to verify a signature given the unhashed +// input. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, + size_t sig_len, const uint8_t *digest, + size_t digest_len); + +// EVP_PKEY_encrypt_init initialises an |EVP_PKEY_CTX| for an encryption +// operation. It should be called before |EVP_PKEY_encrypt|. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_encrypt encrypts |in_len| bytes from |in|. If |out| is NULL, the +// maximum size of the ciphertext is written to |out_len|. Otherwise, |*out_len| +// must contain the number of bytes of space available at |out|. If sufficient, +// the ciphertext will be written to |out| and |*out_len| updated with the true +// length. +// +// WARNING: Setting |out| to NULL only gives the maximum size of the +// ciphertext. The actual ciphertext may be smaller. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *out_len, const uint8_t *in, + size_t in_len); + +// EVP_PKEY_decrypt_init initialises an |EVP_PKEY_CTX| for a decryption +// operation. It should be called before |EVP_PKEY_decrypt|. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_decrypt decrypts |in_len| bytes from |in|. If |out| is NULL, the +// maximum size of the plaintext is written to |out_len|. Otherwise, |*out_len| +// must contain the number of bytes of space available at |out|. If sufficient, +// the ciphertext will be written to |out| and |*out_len| updated with the true +// length. +// +// WARNING: Setting |out| to NULL only gives the maximum size of the +// plaintext. The actual plaintext may be smaller. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *out_len, const uint8_t *in, + size_t in_len); + +// EVP_PKEY_verify_recover_init initialises an |EVP_PKEY_CTX| for a public-key +// decryption operation. It should be called before |EVP_PKEY_verify_recover|. +// +// Public-key decryption is a very obscure operation that is only implemented +// by RSA keys. It is effectively a signature verification operation that +// returns the signed message directly. It is almost certainly not what you +// want. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_verify_recover decrypts |sig_len| bytes from |sig|. If |out| is +// NULL, the maximum size of the plaintext is written to |out_len|. Otherwise, +// |*out_len| must contain the number of bytes of space available at |out|. If +// sufficient, the ciphertext will be written to |out| and |*out_len| updated +// with the true length. +// +// WARNING: Setting |out| to NULL only gives the maximum size of the +// plaintext. The actual plaintext may be smaller. +// +// See the warning about this operation in |EVP_PKEY_verify_recover_init|. It +// is probably not what you want. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *out_len, const uint8_t *sig, + size_t siglen); + +// EVP_PKEY_derive_init initialises an |EVP_PKEY_CTX| for a key derivation +// operation. It should be called before |EVP_PKEY_derive_set_peer| and +// |EVP_PKEY_derive|. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_derive_set_peer sets the peer's key to be used for key derivation +// by |ctx| to |peer|. It should be called after |EVP_PKEY_derive_init|. (For +// example, this is used to set the peer's key in (EC)DH.) It returns one on +// success and zero on error. +OPENSSL_EXPORT int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); + +// EVP_PKEY_derive derives a shared key from |ctx|. If |key| is non-NULL then, +// on entry, |out_key_len| must contain the amount of space at |key|. If +// sufficient then the shared key will be written to |key| and |*out_key_len| +// will be set to the length. If |key| is NULL then |out_key_len| will be set to +// the maximum length. +// +// WARNING: Setting |out| to NULL only gives the maximum size of the key. The +// actual key may be smaller. +// +// It returns one on success and zero on error. +OPENSSL_EXPORT int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, uint8_t *key, + size_t *out_key_len); + +// EVP_PKEY_keygen_init initialises an |EVP_PKEY_CTX| for a key generation +// operation. It should be called before |EVP_PKEY_keygen|. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_keygen performs a key generation operation using the values from +// |ctx|. If |*out_pkey| is non-NULL, it overwrites |*out_pkey| with the +// resulting key. Otherwise, it sets |*out_pkey| to a newly-allocated |EVP_PKEY| +// containing the result. It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **out_pkey); + +// EVP_PKEY_paramgen_init initialises an |EVP_PKEY_CTX| for a parameter +// generation operation. It should be called before |EVP_PKEY_paramgen|. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); + +// EVP_PKEY_paramgen performs a parameter generation using the values from +// |ctx|. If |*out_pkey| is non-NULL, it overwrites |*out_pkey| with the +// resulting parameters, but no key. Otherwise, it sets |*out_pkey| to a +// newly-allocated |EVP_PKEY| containing the result. It returns one on success +// or zero on error. +OPENSSL_EXPORT int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **out_pkey); + + +// Generic control functions. + +// EVP_PKEY_CTX_set_signature_md sets |md| as the digest to be used in a +// signature operation. It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +// EVP_PKEY_CTX_get_signature_md sets |*out_md| to the digest to be used in a +// signature operation. It returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, + const EVP_MD **out_md); + + +// RSA specific control functions. + +// EVP_PKEY_CTX_set_rsa_padding sets the padding type to use. It should be one +// of the |RSA_*_PADDING| values. Returns one on success or zero on error. By +// default, the padding is |RSA_PKCS1_PADDING|. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding); + +// EVP_PKEY_CTX_get_rsa_padding sets |*out_padding| to the current padding +// value, which is one of the |RSA_*_PADDING| values. Returns one on success or +// zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, + int *out_padding); + +// EVP_PKEY_CTX_set_rsa_pss_saltlen sets the length of the salt in a PSS-padded +// signature. A value of -1 cause the salt to be the same length as the digest +// in the signature. A value of -2 causes the salt to be the maximum length +// that will fit when signing and recovered from the signature when verifying. +// Otherwise the value gives the size of the salt in bytes. +// +// If unsure, use -1. +// +// Returns one on success or zero on error. +// +// TODO(davidben): The default is currently -2. Switch it to -1. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, + int salt_len); + +// EVP_PKEY_CTX_get_rsa_pss_saltlen sets |*out_salt_len| to the salt length of +// a PSS-padded signature. See the documentation for +// |EVP_PKEY_CTX_set_rsa_pss_saltlen| for details of the special values that it +// can take. +// +// Returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, + int *out_salt_len); + +// EVP_PKEY_CTX_set_rsa_keygen_bits sets the size of the desired RSA modulus, +// in bits, for key generation. Returns one on success or zero on +// error. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, + int bits); + +// EVP_PKEY_CTX_set_rsa_keygen_pubexp sets |e| as the public exponent for key +// generation. Returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, + BIGNUM *e); + +// EVP_PKEY_CTX_set_rsa_oaep_md sets |md| as the digest used in OAEP padding. +// Returns one on success or zero on error. If unset, the default is SHA-1. +// Callers are recommended to overwrite this default. +// +// TODO(davidben): Remove the default and require callers specify this. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +// EVP_PKEY_CTX_get_rsa_oaep_md sets |*out_md| to the digest function used in +// OAEP padding. Returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, + const EVP_MD **out_md); + +// EVP_PKEY_CTX_set_rsa_mgf1_md sets |md| as the digest used in MGF1. Returns +// one on success or zero on error. +// +// If unset, the default is the signing hash for |RSA_PKCS1_PSS_PADDING| and the +// OAEP hash for |RSA_PKCS1_OAEP_PADDING|. Callers are recommended to use this +// default and not call this function. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +// EVP_PKEY_CTX_get_rsa_mgf1_md sets |*out_md| to the digest function used in +// MGF1. Returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, + const EVP_MD **out_md); + +// EVP_PKEY_CTX_set0_rsa_oaep_label sets |label_len| bytes from |label| as the +// label used in OAEP. DANGER: On success, this call takes ownership of |label| +// and will call |OPENSSL_free| on it when |ctx| is destroyed. +// +// Returns one on success or zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, + uint8_t *label, + size_t label_len); + +// EVP_PKEY_CTX_get0_rsa_oaep_label sets |*out_label| to point to the internal +// buffer containing the OAEP label (which may be NULL) and returns the length +// of the label or a negative value on error. +// +// WARNING: the return value differs from the usual return value convention. +OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, + const uint8_t **out_label); + + +// EC specific control functions. + +// EVP_PKEY_CTX_set_ec_paramgen_curve_nid sets the curve used for +// |EVP_PKEY_keygen| or |EVP_PKEY_paramgen| operations to |nid|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, + int nid); + + +// Deprecated functions. + +// EVP_PKEY_DH is defined for compatibility, but it is impossible to create an +// |EVP_PKEY| of that type. +#define EVP_PKEY_DH NID_dhKeyAgreement + +// EVP_PKEY_RSA2 was historically an alternate form for RSA public keys (OID +// 2.5.8.1.1), but is no longer accepted. +#define EVP_PKEY_RSA2 NID_rsa + +// EVP_PKEY_X448 is defined for OpenSSL compatibility, but we do not support +// X448 and attempts to create keys will fail. +#define EVP_PKEY_X448 NID_X448 + +// EVP_PKEY_ED448 is defined for OpenSSL compatibility, but we do not support +// Ed448 and attempts to create keys will fail. +#define EVP_PKEY_ED448 NID_ED448 + +// EVP_PKEY_get0 returns NULL. This function is provided for compatibility with +// OpenSSL but does not return anything. Use the typed |EVP_PKEY_get0_*| +// functions instead. +OPENSSL_EXPORT void *EVP_PKEY_get0(const EVP_PKEY *pkey); + +// OpenSSL_add_all_algorithms does nothing. +OPENSSL_EXPORT void OpenSSL_add_all_algorithms(void); + +// OPENSSL_add_all_algorithms_conf does nothing. +OPENSSL_EXPORT void OPENSSL_add_all_algorithms_conf(void); + +// OpenSSL_add_all_ciphers does nothing. +OPENSSL_EXPORT void OpenSSL_add_all_ciphers(void); + +// OpenSSL_add_all_digests does nothing. +OPENSSL_EXPORT void OpenSSL_add_all_digests(void); + +// EVP_cleanup does nothing. +OPENSSL_EXPORT void EVP_cleanup(void); + +OPENSSL_EXPORT void EVP_CIPHER_do_all_sorted( + void (*callback)(const EVP_CIPHER *cipher, const char *name, + const char *unused, void *arg), + void *arg); + +OPENSSL_EXPORT void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher, + const char *name, + const char *unused, + void *arg), + void *arg); + +OPENSSL_EXPORT void EVP_MD_do_all(void (*callback)(const EVP_MD *cipher, + const char *name, + const char *unused, + void *arg), + void *arg); + +// i2d_PrivateKey marshals a private key from |key| to type-specific format, as +// described in |i2d_SAMPLE|. +// +// RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 8017) structure. +// EC keys are serialized as a DER-encoded ECPrivateKey (RFC 5915) structure. +// +// Use |RSA_marshal_private_key| or |EC_KEY_marshal_private_key| instead. +OPENSSL_EXPORT int i2d_PrivateKey(const EVP_PKEY *key, uint8_t **outp); + +// i2d_PublicKey marshals a public key from |key| to a type-specific format, as +// described in |i2d_SAMPLE|. +// +// RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 8017) structure. +// EC keys are serialized as an EC point per SEC 1. +// +// Use |RSA_marshal_public_key| or |EC_POINT_point2cbb| instead. +OPENSSL_EXPORT int i2d_PublicKey(const EVP_PKEY *key, uint8_t **outp); + +// d2i_PrivateKey parses a DER-encoded private key from |len| bytes at |*inp|, +// as described in |d2i_SAMPLE|. The private key must have type |type|, +// otherwise it will be rejected. +// +// This function tries to detect one of several formats. Instead, use +// |EVP_parse_private_key| for a PrivateKeyInfo, |RSA_parse_private_key| for an +// RSAPrivateKey, and |EC_parse_private_key| for an ECPrivateKey. +OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, + const uint8_t **inp, long len); + +// d2i_AutoPrivateKey acts the same as |d2i_PrivateKey|, but detects the type +// of the private key. +// +// This function tries to detect one of several formats. Instead, use +// |EVP_parse_private_key| for a PrivateKeyInfo, |RSA_parse_private_key| for an +// RSAPrivateKey, and |EC_parse_private_key| for an ECPrivateKey. +OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, + long len); + +// d2i_PublicKey parses a public key from |len| bytes at |*inp| in a type- +// specific format specified by |type|, as described in |d2i_SAMPLE|. +// +// The only supported value for |type| is |EVP_PKEY_RSA|, which parses a +// DER-encoded RSAPublicKey (RFC 8017) structure. Parsing EC keys is not +// supported by this function. +// +// Use |RSA_parse_public_key| instead. +OPENSSL_EXPORT EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **out, + const uint8_t **inp, long len); + +// EVP_PKEY_get0_DH returns NULL. +OPENSSL_EXPORT DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey); + +// EVP_PKEY_get1_DH returns NULL. +OPENSSL_EXPORT DH *EVP_PKEY_get1_DH(const EVP_PKEY *pkey); + +// EVP_PKEY_CTX_set_ec_param_enc returns one if |encoding| is +// |OPENSSL_EC_NAMED_CURVE| or zero with an error otherwise. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, + int encoding); + +// EVP_PKEY_set1_tls_encodedpoint replaces |pkey| with a public key encoded by +// |in|. It returns one on success and zero on error. +// +// If |pkey| is an EC key, the format is an X9.62 point and |pkey| must already +// have an EC group configured. If it is an X25519 key, it is the 32-byte X25519 +// public key representation. This function is not supported for other key types +// and will fail. +OPENSSL_EXPORT int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, + const uint8_t *in, + size_t len); + +// EVP_PKEY_get1_tls_encodedpoint sets |*out_ptr| to a newly-allocated buffer +// containing the raw encoded public key for |pkey|. The caller must call +// |OPENSSL_free| to release this buffer. The function returns the length of the +// buffer on success and zero on error. +// +// If |pkey| is an EC key, the format is an X9.62 point with uncompressed +// coordinates. If it is an X25519 key, it is the 32-byte X25519 public key +// representation. This function is not supported for other key types and will +// fail. +OPENSSL_EXPORT size_t EVP_PKEY_get1_tls_encodedpoint(const EVP_PKEY *pkey, + uint8_t **out_ptr); + +// EVP_PKEY_base_id calls |EVP_PKEY_id|. +OPENSSL_EXPORT int EVP_PKEY_base_id(const EVP_PKEY *pkey); + +// EVP_PKEY_CTX_set_rsa_pss_keygen_md returns 0. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +// EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen returns 0. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx, + int salt_len); + +// EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md returns 0. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +// i2d_PUBKEY marshals |pkey| as a DER-encoded SubjectPublicKeyInfo, as +// described in |i2d_SAMPLE|. +// +// Use |EVP_marshal_public_key| instead. +OPENSSL_EXPORT int i2d_PUBKEY(const EVP_PKEY *pkey, uint8_t **outp); + +// d2i_PUBKEY parses a DER-encoded SubjectPublicKeyInfo from |len| bytes at +// |*inp|, as described in |d2i_SAMPLE|. +// +// Use |EVP_parse_public_key| instead. +OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY(EVP_PKEY **out, const uint8_t **inp, + long len); + +// i2d_RSA_PUBKEY marshals |rsa| as a DER-encoded SubjectPublicKeyInfo +// structure, as described in |i2d_SAMPLE|. +// +// Use |EVP_marshal_public_key| instead. +OPENSSL_EXPORT int i2d_RSA_PUBKEY(const RSA *rsa, uint8_t **outp); + +// d2i_RSA_PUBKEY parses an RSA public key as a DER-encoded SubjectPublicKeyInfo +// from |len| bytes at |*inp|, as described in |d2i_SAMPLE|. +// SubjectPublicKeyInfo structures containing other key types are rejected. +// +// Use |EVP_parse_public_key| instead. +OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY(RSA **out, const uint8_t **inp, long len); + +// i2d_DSA_PUBKEY marshals |dsa| as a DER-encoded SubjectPublicKeyInfo, as +// described in |i2d_SAMPLE|. +// +// Use |EVP_marshal_public_key| instead. +OPENSSL_EXPORT int i2d_DSA_PUBKEY(const DSA *dsa, uint8_t **outp); + +// d2i_DSA_PUBKEY parses a DSA public key as a DER-encoded SubjectPublicKeyInfo +// from |len| bytes at |*inp|, as described in |d2i_SAMPLE|. +// SubjectPublicKeyInfo structures containing other key types are rejected. +// +// Use |EVP_parse_public_key| instead. +OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY(DSA **out, const uint8_t **inp, long len); + +// i2d_EC_PUBKEY marshals |ec_key| as a DER-encoded SubjectPublicKeyInfo, as +// described in |i2d_SAMPLE|. +// +// Use |EVP_marshal_public_key| instead. +OPENSSL_EXPORT int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp); + +// d2i_EC_PUBKEY parses an EC public key as a DER-encoded SubjectPublicKeyInfo +// from |len| bytes at |*inp|, as described in |d2i_SAMPLE|. +// SubjectPublicKeyInfo structures containing other key types are rejected. +// +// Use |EVP_parse_public_key| instead. +OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY(EC_KEY **out, const uint8_t **inp, + long len); + +// EVP_PKEY_CTX_set_dsa_paramgen_bits returns zero. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, + int nbits); + +// EVP_PKEY_CTX_set_dsa_paramgen_q_bits returns zero. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, + int qbits); + + +// Preprocessor compatibility section (hidden). +// +// Historically, a number of APIs were implemented in OpenSSL as macros and +// constants to 'ctrl' functions. To avoid breaking #ifdefs in consumers, this +// section defines a number of legacy macros. + +// |BORINGSSL_PREFIX| already makes each of these symbols into macros, so there +// is no need to define conflicting macros. +#if !defined(BORINGSSL_PREFIX) +#define EVP_PKEY_CTX_set_rsa_oaep_md EVP_PKEY_CTX_set_rsa_oaep_md +#define EVP_PKEY_CTX_set0_rsa_oaep_label EVP_PKEY_CTX_set0_rsa_oaep_label +#endif + + +// Nodejs compatibility section (hidden). +// +// These defines exist for node.js, with the hope that we can eliminate the +// need for them over time. + +#define EVPerr(function, reason) \ + ERR_put_error(ERR_LIB_EVP, 0, reason, __FILE__, __LINE__) + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(EVP_PKEY, EVP_PKEY_free) +BORINGSSL_MAKE_UP_REF(EVP_PKEY, EVP_PKEY_up_ref) +BORINGSSL_MAKE_DELETER(EVP_PKEY_CTX, EVP_PKEY_CTX_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#endif // OPENSSL_HEADER_EVP_H diff --git a/lib/boringssl/include/openssl/evp_errors.h b/lib/boringssl/include/openssl/evp_errors.h new file mode 100644 index 00000000..8583f521 --- /dev/null +++ b/lib/boringssl/include/openssl/evp_errors.h @@ -0,0 +1,99 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_EVP_ERRORS_H +#define OPENSSL_HEADER_EVP_ERRORS_H + +#define EVP_R_BUFFER_TOO_SMALL 100 +#define EVP_R_COMMAND_NOT_SUPPORTED 101 +#define EVP_R_DECODE_ERROR 102 +#define EVP_R_DIFFERENT_KEY_TYPES 103 +#define EVP_R_DIFFERENT_PARAMETERS 104 +#define EVP_R_ENCODE_ERROR 105 +#define EVP_R_EXPECTING_AN_EC_KEY_KEY 106 +#define EVP_R_EXPECTING_AN_RSA_KEY 107 +#define EVP_R_EXPECTING_A_DSA_KEY 108 +#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 109 +#define EVP_R_INVALID_DIGEST_LENGTH 110 +#define EVP_R_INVALID_DIGEST_TYPE 111 +#define EVP_R_INVALID_KEYBITS 112 +#define EVP_R_INVALID_MGF1_MD 113 +#define EVP_R_INVALID_OPERATION 114 +#define EVP_R_INVALID_PADDING_MODE 115 +#define EVP_R_INVALID_PSS_SALTLEN 116 +#define EVP_R_KEYS_NOT_SET 117 +#define EVP_R_MISSING_PARAMETERS 118 +#define EVP_R_NO_DEFAULT_DIGEST 119 +#define EVP_R_NO_KEY_SET 120 +#define EVP_R_NO_MDC2_SUPPORT 121 +#define EVP_R_NO_NID_FOR_CURVE 122 +#define EVP_R_NO_OPERATION_SET 123 +#define EVP_R_NO_PARAMETERS_SET 124 +#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 125 +#define EVP_R_OPERATON_NOT_INITIALIZED 126 +#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 127 +#define EVP_R_UNSUPPORTED_ALGORITHM 128 +#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 129 +#define EVP_R_NOT_A_PRIVATE_KEY 130 +#define EVP_R_INVALID_SIGNATURE 131 +#define EVP_R_MEMORY_LIMIT_EXCEEDED 132 +#define EVP_R_INVALID_PARAMETERS 133 +#define EVP_R_INVALID_PEER_KEY 134 +#define EVP_R_NOT_XOF_OR_INVALID_LENGTH 135 +#define EVP_R_EMPTY_PSK 136 +#define EVP_R_INVALID_BUFFER_SIZE 137 + +#endif // OPENSSL_HEADER_EVP_ERRORS_H diff --git a/lib/boringssl/include/openssl/ex_data.h b/lib/boringssl/include/openssl/ex_data.h new file mode 100644 index 00000000..8f2f98b0 --- /dev/null +++ b/lib/boringssl/include/openssl/ex_data.h @@ -0,0 +1,203 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_EX_DATA_H +#define OPENSSL_HEADER_EX_DATA_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// ex_data is a mechanism for associating arbitrary extra data with objects. +// For each type of object that supports ex_data, different users can be +// assigned indexes in which to store their data. Each index has callback +// functions that are called when an object of that type is freed or +// duplicated. + + +typedef struct crypto_ex_data_st CRYPTO_EX_DATA; + + +// Type-specific functions. +// +// Each type that supports ex_data provides three functions: + +#if 0 // Sample + +// TYPE_get_ex_new_index allocates a new index for |TYPE|. An optional +// |free_func| argument may be provided which is called when the owning object +// is destroyed. See |CRYPTO_EX_free| for details. The |argl| and |argp| +// arguments are opaque values that are passed to the callback. It returns the +// new index or a negative number on error. +OPENSSL_EXPORT int TYPE_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); + +// TYPE_set_ex_data sets an extra data pointer on |t|. The |index| argument +// must have been returned from a previous call to |TYPE_get_ex_new_index|. +OPENSSL_EXPORT int TYPE_set_ex_data(TYPE *t, int index, void *arg); + +// TYPE_get_ex_data returns an extra data pointer for |t|, or NULL if no such +// pointer exists. The |index| argument should have been returned from a +// previous call to |TYPE_get_ex_new_index|. +OPENSSL_EXPORT void *TYPE_get_ex_data(const TYPE *t, int index); + +#endif // Sample + + +// Callback types. + +// CRYPTO_EX_free is a callback function that is called when an object of the +// class with extra data pointers is being destroyed. For example, if this +// callback has been passed to |SSL_get_ex_new_index| then it may be called each +// time an |SSL*| is destroyed. +// +// The callback is passed the new object (i.e. the |SSL*|) in |parent|. The +// arguments |argl| and |argp| contain opaque values that were given to +// |CRYPTO_get_ex_new_index|. The callback should return one on success, but +// the value is ignored. +// +// This callback may be called with a NULL value for |ptr| if |parent| has no +// value set for this index. However, the callbacks may also be skipped entirely +// if no extra data pointers are set on |parent| at all. +typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int index, long argl, void *argp); + + +// Deprecated functions. + +// CRYPTO_cleanup_all_ex_data does nothing. +OPENSSL_EXPORT void CRYPTO_cleanup_all_ex_data(void); + +// CRYPTO_EX_dup is a legacy callback function type which is ignored. +typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, + void **from_d, int index, long argl, void *argp); + + +// Private structures. + +// CRYPTO_EX_unused is a placeholder for an unused callback. It is aliased to +// int to ensure non-NULL callers fail to compile rather than fail silently. +typedef int CRYPTO_EX_unused; + +struct crypto_ex_data_st { + STACK_OF(void) *sk; +}; + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_EX_DATA_H diff --git a/lib/boringssl/include/openssl/hkdf.h b/lib/boringssl/include/openssl/hkdf.h new file mode 100644 index 00000000..5b27acc6 --- /dev/null +++ b/lib/boringssl/include/openssl/hkdf.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_HKDF_H +#define OPENSSL_HEADER_HKDF_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// HKDF. + + +// HKDF computes HKDF (as specified by RFC 5869) of initial keying material +// |secret| with |salt| and |info| using |digest|, and outputs |out_len| bytes +// to |out_key|. It returns one on success and zero on error. +// +// HKDF is an Extract-and-Expand algorithm. It does not do any key stretching, +// and as such, is not suited to be used alone to generate a key from a +// password. +OPENSSL_EXPORT int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, + const uint8_t *salt, size_t salt_len, + const uint8_t *info, size_t info_len); + +// HKDF_extract computes a HKDF PRK (as specified by RFC 5869) from initial +// keying material |secret| and salt |salt| using |digest|, and outputs +// |out_len| bytes to |out_key|. The maximum output size is |EVP_MAX_MD_SIZE|. +// It returns one on success and zero on error. +// +// WARNING: This function orders the inputs differently from RFC 5869 +// specification. Double-check which parameter is the secret/IKM and which is +// the salt when using. +OPENSSL_EXPORT int HKDF_extract(uint8_t *out_key, size_t *out_len, + const EVP_MD *digest, const uint8_t *secret, + size_t secret_len, const uint8_t *salt, + size_t salt_len); + +// HKDF_expand computes a HKDF OKM (as specified by RFC 5869) of length +// |out_len| from the PRK |prk| and info |info| using |digest|, and outputs +// the result to |out_key|. It returns one on success and zero on error. +OPENSSL_EXPORT int HKDF_expand(uint8_t *out_key, size_t out_len, + const EVP_MD *digest, const uint8_t *prk, + size_t prk_len, const uint8_t *info, + size_t info_len); + + +#if defined(__cplusplus) +} // extern C +#endif + +#define HKDF_R_OUTPUT_TOO_LARGE 100 + +#endif // OPENSSL_HEADER_HKDF_H diff --git a/lib/boringssl/include/openssl/hmac.h b/lib/boringssl/include/openssl/hmac.h new file mode 100644 index 00000000..7a4737f2 --- /dev/null +++ b/lib/boringssl/include/openssl/hmac.h @@ -0,0 +1,193 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_HMAC_H +#define OPENSSL_HEADER_HMAC_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// HMAC contains functions for constructing PRFs from Merkle–Damgård hash +// functions using HMAC. + + +// One-shot operation. + +// HMAC calculates the HMAC of |data_len| bytes of |data|, using the given key +// and hash function, and writes the result to |out|. On entry, |out| must +// contain at least |EVP_MD_size| bytes of space. The actual length of the +// result is written to |*out_len|. An output size of |EVP_MAX_MD_SIZE| will +// always be large enough. It returns |out| or NULL on error. +OPENSSL_EXPORT uint8_t *HMAC(const EVP_MD *evp_md, const void *key, + size_t key_len, const uint8_t *data, + size_t data_len, uint8_t *out, + unsigned int *out_len); + + +// Incremental operation. + +// HMAC_CTX_init initialises |ctx| for use in an HMAC operation. It's assumed +// that HMAC_CTX objects will be allocated on the stack thus no allocation +// function is provided. +OPENSSL_EXPORT void HMAC_CTX_init(HMAC_CTX *ctx); + +// HMAC_CTX_new allocates and initialises a new |HMAC_CTX| and returns it, or +// NULL on allocation failure. The caller must use |HMAC_CTX_free| to release +// the resulting object. +OPENSSL_EXPORT HMAC_CTX *HMAC_CTX_new(void); + +// HMAC_CTX_cleanup frees data owned by |ctx|. It does not free |ctx| itself. +OPENSSL_EXPORT void HMAC_CTX_cleanup(HMAC_CTX *ctx); + +// HMAC_CTX_cleanse zeros the digest state from |ctx| and then performs the +// actions of |HMAC_CTX_cleanup|. +OPENSSL_EXPORT void HMAC_CTX_cleanse(HMAC_CTX *ctx); + +// HMAC_CTX_free calls |HMAC_CTX_cleanup| and then frees |ctx| itself. +OPENSSL_EXPORT void HMAC_CTX_free(HMAC_CTX *ctx); + +// HMAC_Init_ex sets up an initialised |HMAC_CTX| to use |md| as the hash +// function and |key| as the key. For a non-initial call, |md| may be NULL, in +// which case the previous hash function will be used. If the hash function has +// not changed and |key| is NULL, |ctx| reuses the previous key. It returns one +// on success or zero on allocation failure. +// +// WARNING: NULL and empty keys are ambiguous on non-initial calls. Passing NULL +// |key| but repeating the previous |md| reuses the previous key rather than the +// empty key. +OPENSSL_EXPORT int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, + const EVP_MD *md, ENGINE *impl); + +// HMAC_Update hashes |data_len| bytes from |data| into the current HMAC +// operation in |ctx|. It returns one. +OPENSSL_EXPORT int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data, + size_t data_len); + +// HMAC_Final completes the HMAC operation in |ctx| and writes the result to +// |out| and the sets |*out_len| to the length of the result. On entry, |out| +// must contain at least |HMAC_size| bytes of space. An output size of +// |EVP_MAX_MD_SIZE| will always be large enough. It returns one on success or +// zero on allocation failure. +OPENSSL_EXPORT int HMAC_Final(HMAC_CTX *ctx, uint8_t *out, + unsigned int *out_len); + + +// Utility functions. + +// HMAC_size returns the size, in bytes, of the HMAC that will be produced by +// |ctx|. On entry, |ctx| must have been setup with |HMAC_Init_ex|. +OPENSSL_EXPORT size_t HMAC_size(const HMAC_CTX *ctx); + +// HMAC_CTX_get_md returns |ctx|'s hash function. +OPENSSL_EXPORT const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx); + +// HMAC_CTX_copy_ex sets |dest| equal to |src|. On entry, |dest| must have been +// initialised by calling |HMAC_CTX_init|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src); + +// HMAC_CTX_reset calls |HMAC_CTX_cleanup| followed by |HMAC_CTX_init|. +OPENSSL_EXPORT void HMAC_CTX_reset(HMAC_CTX *ctx); + + +// Deprecated functions. + +OPENSSL_EXPORT int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, + const EVP_MD *md); + +// HMAC_CTX_copy calls |HMAC_CTX_init| on |dest| and then sets it equal to +// |src|. On entry, |dest| must /not/ be initialised for an operation with +// |HMAC_Init_ex|. It returns one on success and zero on error. +OPENSSL_EXPORT int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src); + + +// Private functions + +struct hmac_ctx_st { + const EVP_MD *md; + EVP_MD_CTX md_ctx; + EVP_MD_CTX i_ctx; + EVP_MD_CTX o_ctx; +} /* HMAC_CTX */; + + +#if defined(__cplusplus) +} // extern C + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(HMAC_CTX, HMAC_CTX_free) + +using ScopedHMAC_CTX = + internal::StackAllocated; + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#endif + +#endif // OPENSSL_HEADER_HMAC_H diff --git a/lib/boringssl/include/openssl/hpke.h b/lib/boringssl/include/openssl/hpke.h new file mode 100644 index 00000000..eaf5947f --- /dev/null +++ b/lib/boringssl/include/openssl/hpke.h @@ -0,0 +1,403 @@ +/* Copyright (c) 2020, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H + +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Hybrid Public Key Encryption. +// +// Hybrid Public Key Encryption (HPKE) enables a sender to encrypt messages to a +// receiver with a public key. +// +// See RFC 9180. + + +// Parameters. +// +// An HPKE context is parameterized by KEM, KDF, and AEAD algorithms, +// represented by |EVP_HPKE_KEM|, |EVP_HPKE_KDF|, and |EVP_HPKE_AEAD| types, +// respectively. + +// The following constants are KEM identifiers. +#define EVP_HPKE_DHKEM_X25519_HKDF_SHA256 0x0020 + +// The following functions are KEM algorithms which may be used with HPKE. Note +// that, while some HPKE KEMs use KDFs internally, this is separate from the +// |EVP_HPKE_KDF| selection. +OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_x25519_hkdf_sha256(void); + +// EVP_HPKE_KEM_id returns the HPKE KEM identifier for |kem|, which +// will be one of the |EVP_HPKE_KEM_*| constants. +OPENSSL_EXPORT uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem); + +// EVP_HPKE_MAX_PUBLIC_KEY_LENGTH is the maximum length of an encoded public key +// for all KEMs currently supported by this library. +#define EVP_HPKE_MAX_PUBLIC_KEY_LENGTH 32 + +// EVP_HPKE_KEM_public_key_len returns the length of a public key for |kem|. +// This value will be at most |EVP_HPKE_MAX_PUBLIC_KEY_LENGTH|. +OPENSSL_EXPORT size_t EVP_HPKE_KEM_public_key_len(const EVP_HPKE_KEM *kem); + +// EVP_HPKE_MAX_PRIVATE_KEY_LENGTH is the maximum length of an encoded private +// key for all KEMs currently supported by this library. +#define EVP_HPKE_MAX_PRIVATE_KEY_LENGTH 32 + +// EVP_HPKE_KEM_private_key_len returns the length of a private key for |kem|. +// This value will be at most |EVP_HPKE_MAX_PRIVATE_KEY_LENGTH|. +OPENSSL_EXPORT size_t EVP_HPKE_KEM_private_key_len(const EVP_HPKE_KEM *kem); + +// EVP_HPKE_MAX_ENC_LENGTH is the maximum length of "enc", the encapsulated +// shared secret, for all KEMs currently supported by this library. +#define EVP_HPKE_MAX_ENC_LENGTH 32 + +// EVP_HPKE_KEM_enc_len returns the length of the "enc", the encapsulated shared +// secret, for |kem|. This value will be at most |EVP_HPKE_MAX_ENC_LENGTH|. +OPENSSL_EXPORT size_t EVP_HPKE_KEM_enc_len(const EVP_HPKE_KEM *kem); + +// The following constants are KDF identifiers. +#define EVP_HPKE_HKDF_SHA256 0x0001 + +// The following functions are KDF algorithms which may be used with HPKE. +OPENSSL_EXPORT const EVP_HPKE_KDF *EVP_hpke_hkdf_sha256(void); + +// EVP_HPKE_KDF_id returns the HPKE KDF identifier for |kdf|. +OPENSSL_EXPORT uint16_t EVP_HPKE_KDF_id(const EVP_HPKE_KDF *kdf); + +// EVP_HPKE_KDF_hkdf_md returns the HKDF hash function corresponding to |kdf|, +// or NULL if |kdf| is not an HKDF-based KDF. All currently supported KDFs are +// HKDF-based. +OPENSSL_EXPORT const EVP_MD *EVP_HPKE_KDF_hkdf_md(const EVP_HPKE_KDF *kdf); + +// The following constants are AEAD identifiers. +#define EVP_HPKE_AES_128_GCM 0x0001 +#define EVP_HPKE_AES_256_GCM 0x0002 +#define EVP_HPKE_CHACHA20_POLY1305 0x0003 + +// The following functions are AEAD algorithms which may be used with HPKE. +OPENSSL_EXPORT const EVP_HPKE_AEAD *EVP_hpke_aes_128_gcm(void); +OPENSSL_EXPORT const EVP_HPKE_AEAD *EVP_hpke_aes_256_gcm(void); +OPENSSL_EXPORT const EVP_HPKE_AEAD *EVP_hpke_chacha20_poly1305(void); + +// EVP_HPKE_AEAD_id returns the HPKE AEAD identifier for |aead|. +OPENSSL_EXPORT uint16_t EVP_HPKE_AEAD_id(const EVP_HPKE_AEAD *aead); + +// EVP_HPKE_AEAD_aead returns the |EVP_AEAD| corresponding to |aead|. +OPENSSL_EXPORT const EVP_AEAD *EVP_HPKE_AEAD_aead(const EVP_HPKE_AEAD *aead); + + +// Recipient keys. +// +// An HPKE recipient maintains a long-term KEM key. This library represents keys +// with the |EVP_HPKE_KEY| type. + +// EVP_HPKE_KEY_zero sets an uninitialized |EVP_HPKE_KEY| to the zero state. The +// caller should then use |EVP_HPKE_KEY_init|, |EVP_HPKE_KEY_copy|, or +// |EVP_HPKE_KEY_generate| to finish initializing |key|. +// +// It is safe, but not necessary to call |EVP_HPKE_KEY_cleanup| in this state. +// This may be used for more uniform cleanup of |EVP_HPKE_KEY|. +OPENSSL_EXPORT void EVP_HPKE_KEY_zero(EVP_HPKE_KEY *key); + +// EVP_HPKE_KEY_cleanup releases memory referenced by |key|. +OPENSSL_EXPORT void EVP_HPKE_KEY_cleanup(EVP_HPKE_KEY *key); + +// EVP_HPKE_KEY_new returns a newly-allocated |EVP_HPKE_KEY|, or NULL on error. +// The caller must call |EVP_HPKE_KEY_free| on the result to release it. +// +// This is a convenience function for callers that need a heap-allocated +// |EVP_HPKE_KEY|. +OPENSSL_EXPORT EVP_HPKE_KEY *EVP_HPKE_KEY_new(void); + +// EVP_HPKE_KEY_free releases memory associated with |key|, which must have been +// created with |EVP_HPKE_KEY_new|. +OPENSSL_EXPORT void EVP_HPKE_KEY_free(EVP_HPKE_KEY *key); + +// EVP_HPKE_KEY_copy sets |dst| to a copy of |src|. It returns one on success +// and zero on error. On success, the caller must call |EVP_HPKE_KEY_cleanup| to +// release |dst|. On failure, calling |EVP_HPKE_KEY_cleanup| is safe, but not +// necessary. +OPENSSL_EXPORT int EVP_HPKE_KEY_copy(EVP_HPKE_KEY *dst, + const EVP_HPKE_KEY *src); + +// EVP_HPKE_KEY_init decodes |priv_key| as a private key for |kem| and +// initializes |key| with the result. It returns one on success and zero if +// |priv_key| was invalid. On success, the caller must call +// |EVP_HPKE_KEY_cleanup| to release the key. On failure, calling +// |EVP_HPKE_KEY_cleanup| is safe, but not necessary. +OPENSSL_EXPORT int EVP_HPKE_KEY_init(EVP_HPKE_KEY *key, const EVP_HPKE_KEM *kem, + const uint8_t *priv_key, + size_t priv_key_len); + +// EVP_HPKE_KEY_generate sets |key| to a newly-generated key using |kem|. +OPENSSL_EXPORT int EVP_HPKE_KEY_generate(EVP_HPKE_KEY *key, + const EVP_HPKE_KEM *kem); + +// EVP_HPKE_KEY_kem returns the HPKE KEM used by |key|. +OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_HPKE_KEY_kem(const EVP_HPKE_KEY *key); + +// EVP_HPKE_KEY_public_key writes |key|'s public key to |out| and sets +// |*out_len| to the number of bytes written. On success, it returns one and +// writes at most |max_out| bytes. If |max_out| is too small, it returns zero. +// Setting |max_out| to |EVP_HPKE_MAX_PUBLIC_KEY_LENGTH| will ensure the public +// key fits. An exact size can also be determined by +// |EVP_HPKE_KEM_public_key_len|. +OPENSSL_EXPORT int EVP_HPKE_KEY_public_key(const EVP_HPKE_KEY *key, + uint8_t *out, size_t *out_len, + size_t max_out); + +// EVP_HPKE_KEY_private_key writes |key|'s private key to |out| and sets +// |*out_len| to the number of bytes written. On success, it returns one and +// writes at most |max_out| bytes. If |max_out| is too small, it returns zero. +// Setting |max_out| to |EVP_HPKE_MAX_PRIVATE_KEY_LENGTH| will ensure the +// private key fits. An exact size can also be determined by +// |EVP_HPKE_KEM_private_key_len|. +OPENSSL_EXPORT int EVP_HPKE_KEY_private_key(const EVP_HPKE_KEY *key, + uint8_t *out, size_t *out_len, + size_t max_out); + + +// Encryption contexts. +// +// An HPKE encryption context is represented by the |EVP_HPKE_CTX| type. + +// EVP_HPKE_CTX_zero sets an uninitialized |EVP_HPKE_CTX| to the zero state. The +// caller should then use one of the |EVP_HPKE_CTX_setup_*| functions to finish +// setting up |ctx|. +// +// It is safe, but not necessary to call |EVP_HPKE_CTX_cleanup| in this state. +// This may be used for more uniform cleanup of |EVP_HPKE_CTX|. +OPENSSL_EXPORT void EVP_HPKE_CTX_zero(EVP_HPKE_CTX *ctx); + +// EVP_HPKE_CTX_cleanup releases memory referenced by |ctx|. |ctx| must have +// been initialized with |EVP_HPKE_CTX_zero| or one of the +// |EVP_HPKE_CTX_setup_*| functions. +OPENSSL_EXPORT void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx); + +// EVP_HPKE_CTX_new returns a newly-allocated |EVP_HPKE_CTX|, or NULL on error. +// The caller must call |EVP_HPKE_CTX_free| on the result to release it. +// +// This is a convenience function for callers that need a heap-allocated +// |EVP_HPKE_CTX|. +OPENSSL_EXPORT EVP_HPKE_CTX *EVP_HPKE_CTX_new(void); + +// EVP_HPKE_CTX_free releases memory associated with |ctx|, which must have been +// created with |EVP_HPKE_CTX_new|. +OPENSSL_EXPORT void EVP_HPKE_CTX_free(EVP_HPKE_CTX *ctx); + +// EVP_HPKE_CTX_setup_sender implements the SetupBaseS HPKE operation. It +// encapsulates a shared secret for |peer_public_key| and sets up |ctx| as a +// sender context. It writes the encapsulated shared secret to |out_enc| and +// sets |*out_enc_len| to the number of bytes written. It writes at most +// |max_enc| bytes and fails if the buffer is too small. Setting |max_enc| to at +// least |EVP_HPKE_MAX_ENC_LENGTH| will ensure the buffer is large enough. An +// exact size may also be determined by |EVP_PKEY_KEM_enc_len|. +// +// This function returns one on success and zero on error. Note that +// |peer_public_key| may be invalid, in which case this function will return an +// error. +// +// On success, callers may call |EVP_HPKE_CTX_seal| to encrypt messages for the +// recipient. Callers must then call |EVP_HPKE_CTX_cleanup| when done. On +// failure, calling |EVP_HPKE_CTX_cleanup| is safe, but not required. +OPENSSL_EXPORT int EVP_HPKE_CTX_setup_sender( + EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc, + const EVP_HPKE_KEM *kem, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead, + const uint8_t *peer_public_key, size_t peer_public_key_len, + const uint8_t *info, size_t info_len); + +// EVP_HPKE_CTX_setup_sender_with_seed_for_testing behaves like +// |EVP_HPKE_CTX_setup_sender|, but takes a seed to behave deterministically. +// The seed's format depends on |kem|. For X25519, it is the sender's +// ephemeral private key. +OPENSSL_EXPORT int EVP_HPKE_CTX_setup_sender_with_seed_for_testing( + EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc, + const EVP_HPKE_KEM *kem, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead, + const uint8_t *peer_public_key, size_t peer_public_key_len, + const uint8_t *info, size_t info_len, const uint8_t *seed, size_t seed_len); + +// EVP_HPKE_CTX_setup_recipient implements the SetupBaseR HPKE operation. It +// decapsulates the shared secret in |enc| with |key| and sets up |ctx| as a +// recipient context. It returns one on success and zero on failure. Note that +// |enc| may be invalid, in which case this function will return an error. +// +// On success, callers may call |EVP_HPKE_CTX_open| to decrypt messages from the +// sender. Callers must then call |EVP_HPKE_CTX_cleanup| when done. On failure, +// calling |EVP_HPKE_CTX_cleanup| is safe, but not required. +OPENSSL_EXPORT int EVP_HPKE_CTX_setup_recipient( + EVP_HPKE_CTX *ctx, const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, + const EVP_HPKE_AEAD *aead, const uint8_t *enc, size_t enc_len, + const uint8_t *info, size_t info_len); + +// EVP_HPKE_CTX_setup_auth_sender implements the SetupAuthS HPKE operation. It +// behaves like |EVP_HPKE_CTX_setup_sender| but authenticates the resulting +// context with |key|. +OPENSSL_EXPORT int EVP_HPKE_CTX_setup_auth_sender( + EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc, + const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead, + const uint8_t *peer_public_key, size_t peer_public_key_len, + const uint8_t *info, size_t info_len); + +// EVP_HPKE_CTX_setup_auth_sender_with_seed_for_testing behaves like +// |EVP_HPKE_CTX_setup_auth_sender|, but takes a seed to behave +// deterministically. The seed's format depends on |kem|. For X25519, it is the +// sender's ephemeral private key. +OPENSSL_EXPORT int EVP_HPKE_CTX_setup_auth_sender_with_seed_for_testing( + EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc, + const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead, + const uint8_t *peer_public_key, size_t peer_public_key_len, + const uint8_t *info, size_t info_len, const uint8_t *seed, size_t seed_len); + +// EVP_HPKE_CTX_setup_auth_recipient implements the SetupAuthR HPKE operation. +// It behaves like |EVP_HPKE_CTX_setup_recipient| but checks the resulting +// context was authenticated with |peer_public_key|. +OPENSSL_EXPORT int EVP_HPKE_CTX_setup_auth_recipient( + EVP_HPKE_CTX *ctx, const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, + const EVP_HPKE_AEAD *aead, const uint8_t *enc, size_t enc_len, + const uint8_t *info, size_t info_len, const uint8_t *peer_public_key, + size_t peer_public_key_len); + + +// Using an HPKE context. +// +// Once set up, callers may encrypt or decrypt with an |EVP_HPKE_CTX| using the +// following functions. + +// EVP_HPKE_CTX_open uses the HPKE context |ctx| to authenticate |in_len| bytes +// from |in| and |ad_len| bytes from |ad| and to decrypt at most |in_len| bytes +// into |out|. It returns one on success, and zero otherwise. +// +// This operation will fail if the |ctx| context is not set up as a receiver. +// +// Note that HPKE encryption is stateful and ordered. The sender's first call to +// |EVP_HPKE_CTX_seal| must correspond to the recipient's first call to +// |EVP_HPKE_CTX_open|, etc. +// +// At most |in_len| bytes are written to |out|. In order to ensure success, +// |max_out_len| should be at least |in_len|. On successful return, |*out_len| +// is set to the actual number of bytes written. +OPENSSL_EXPORT int EVP_HPKE_CTX_open(EVP_HPKE_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len); + +// EVP_HPKE_CTX_seal uses the HPKE context |ctx| to encrypt and authenticate +// |in_len| bytes of ciphertext |in| and authenticate |ad_len| bytes from |ad|, +// writing the result to |out|. It returns one on success and zero otherwise. +// +// This operation will fail if the |ctx| context is not set up as a sender. +// +// Note that HPKE encryption is stateful and ordered. The sender's first call to +// |EVP_HPKE_CTX_seal| must correspond to the recipient's first call to +// |EVP_HPKE_CTX_open|, etc. +// +// At most, |max_out_len| encrypted bytes are written to |out|. On successful +// return, |*out_len| is set to the actual number of bytes written. +// +// To ensure success, |max_out_len| should be |in_len| plus the result of +// |EVP_HPKE_CTX_max_overhead| or |EVP_HPKE_MAX_OVERHEAD|. +OPENSSL_EXPORT int EVP_HPKE_CTX_seal(EVP_HPKE_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len); + +// EVP_HPKE_CTX_export uses the HPKE context |ctx| to export a secret of +// |secret_len| bytes into |out|. This function uses |context_len| bytes from +// |context| as a context string for the secret. This is necessary to separate +// different uses of exported secrets and bind relevant caller-specific context +// into the output. It returns one on success and zero otherwise. +OPENSSL_EXPORT int EVP_HPKE_CTX_export(const EVP_HPKE_CTX *ctx, uint8_t *out, + size_t secret_len, + const uint8_t *context, + size_t context_len); + +// EVP_HPKE_MAX_OVERHEAD contains the largest value that +// |EVP_HPKE_CTX_max_overhead| would ever return for any context. +#define EVP_HPKE_MAX_OVERHEAD EVP_AEAD_MAX_OVERHEAD + +// EVP_HPKE_CTX_max_overhead returns the maximum number of additional bytes +// added by sealing data with |EVP_HPKE_CTX_seal|. The |ctx| context must be set +// up as a sender. +OPENSSL_EXPORT size_t EVP_HPKE_CTX_max_overhead(const EVP_HPKE_CTX *ctx); + +// EVP_HPKE_CTX_kem returns |ctx|'s configured KEM, or NULL if the context has +// not been set up. +OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_HPKE_CTX_kem(const EVP_HPKE_CTX *ctx); + +// EVP_HPKE_CTX_aead returns |ctx|'s configured AEAD, or NULL if the context has +// not been set up. +OPENSSL_EXPORT const EVP_HPKE_AEAD *EVP_HPKE_CTX_aead(const EVP_HPKE_CTX *ctx); + +// EVP_HPKE_CTX_kdf returns |ctx|'s configured KDF, or NULL if the context has +// not been set up. +OPENSSL_EXPORT const EVP_HPKE_KDF *EVP_HPKE_CTX_kdf(const EVP_HPKE_CTX *ctx); + + +// Private structures. +// +// The following structures are exported so their types are stack-allocatable, +// but accessing or modifying their fields is forbidden. + +struct evp_hpke_ctx_st { + const EVP_HPKE_KEM *kem; + const EVP_HPKE_AEAD *aead; + const EVP_HPKE_KDF *kdf; + EVP_AEAD_CTX aead_ctx; + uint8_t base_nonce[EVP_AEAD_MAX_NONCE_LENGTH]; + uint8_t exporter_secret[EVP_MAX_MD_SIZE]; + uint64_t seq; + int is_sender; +}; + +struct evp_hpke_key_st { + const EVP_HPKE_KEM *kem; + uint8_t private_key[X25519_PRIVATE_KEY_LEN]; + uint8_t public_key[X25519_PUBLIC_VALUE_LEN]; +}; + + +#if defined(__cplusplus) +} // extern C +#endif + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +using ScopedEVP_HPKE_CTX = + internal::StackAllocated; +using ScopedEVP_HPKE_KEY = + internal::StackAllocated; + +BORINGSSL_MAKE_DELETER(EVP_HPKE_CTX, EVP_HPKE_CTX_free) +BORINGSSL_MAKE_DELETER(EVP_HPKE_KEY, EVP_HPKE_KEY_free) + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#endif // OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H diff --git a/lib/boringssl/include/openssl/hrss.h b/lib/boringssl/include/openssl/hrss.h new file mode 100644 index 00000000..016fe679 --- /dev/null +++ b/lib/boringssl/include/openssl/hrss.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_HRSS_H +#define OPENSSL_HEADER_HRSS_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +// HRSS +// +// HRSS is a structured-lattice-based post-quantum key encapsulation mechanism. +// The best exposition is https://eprint.iacr.org/2017/667.pdf although this +// implementation uses a different KEM construction based on +// https://eprint.iacr.org/2017/1005.pdf. + +struct HRSS_private_key { + uint8_t opaque[1808]; +}; + +struct HRSS_public_key { + uint8_t opaque[1424]; +}; + +// HRSS_SAMPLE_BYTES is the number of bytes of entropy needed to generate a +// short vector. There are 701 coefficients, but the final one is always set to +// zero when sampling. Otherwise, we need one byte of input per coefficient. +#define HRSS_SAMPLE_BYTES (701 - 1) +// HRSS_GENERATE_KEY_BYTES is the number of bytes of entropy needed to generate +// an HRSS key pair. +#define HRSS_GENERATE_KEY_BYTES (HRSS_SAMPLE_BYTES + HRSS_SAMPLE_BYTES + 32) +// HRSS_ENCAP_BYTES is the number of bytes of entropy needed to encapsulate a +// session key. +#define HRSS_ENCAP_BYTES (HRSS_SAMPLE_BYTES + HRSS_SAMPLE_BYTES) +// HRSS_PUBLIC_KEY_BYTES is the number of bytes in a public key. +#define HRSS_PUBLIC_KEY_BYTES 1138 +// HRSS_CIPHERTEXT_BYTES is the number of bytes in a ciphertext. +#define HRSS_CIPHERTEXT_BYTES 1138 +// HRSS_KEY_BYTES is the number of bytes in a shared key. +#define HRSS_KEY_BYTES 32 +// HRSS_POLY3_BYTES is the number of bytes needed to serialise a mod 3 +// polynomial. +#define HRSS_POLY3_BYTES 140 +#define HRSS_PRIVATE_KEY_BYTES \ + (HRSS_POLY3_BYTES * 2 + HRSS_PUBLIC_KEY_BYTES + 2 + 32) + +// HRSS_generate_key is a deterministic function that outputs a public and +// private key based on the given entropy. It returns one on success or zero +// on malloc failure. +OPENSSL_EXPORT int HRSS_generate_key( + struct HRSS_public_key *out_pub, struct HRSS_private_key *out_priv, + const uint8_t input[HRSS_GENERATE_KEY_BYTES]); + +// HRSS_encap is a deterministic function the generates and encrypts a random +// session key from the given entropy, writing those values to |out_shared_key| +// and |out_ciphertext|, respectively. It returns one on success or zero on +// malloc failure. +OPENSSL_EXPORT int HRSS_encap(uint8_t out_ciphertext[HRSS_CIPHERTEXT_BYTES], + uint8_t out_shared_key[HRSS_KEY_BYTES], + const struct HRSS_public_key *in_pub, + const uint8_t in[HRSS_ENCAP_BYTES]); + +// HRSS_decap decrypts a session key from |ciphertext_len| bytes of +// |ciphertext|. If the ciphertext is valid, the decrypted key is written to +// |out_shared_key|. Otherwise the HMAC of |ciphertext| under a secret key (kept +// in |in_priv|) is written. If the ciphertext is the wrong length then it will +// leak which was done via side-channels. Otherwise it should perform either +// action in constant-time. It returns one on success (whether the ciphertext +// was valid or not) and zero on malloc failure. +OPENSSL_EXPORT int HRSS_decap(uint8_t out_shared_key[HRSS_KEY_BYTES], + const struct HRSS_private_key *in_priv, + const uint8_t *ciphertext, size_t ciphertext_len); + +// HRSS_marshal_public_key serialises |in_pub| to |out|. +OPENSSL_EXPORT void HRSS_marshal_public_key( + uint8_t out[HRSS_PUBLIC_KEY_BYTES], const struct HRSS_public_key *in_pub); + +// HRSS_parse_public_key sets |*out| to the public-key encoded in |in|. It +// returns true on success and zero on error. +OPENSSL_EXPORT int HRSS_parse_public_key( + struct HRSS_public_key *out, const uint8_t in[HRSS_PUBLIC_KEY_BYTES]); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_HRSS_H diff --git a/lib/boringssl/include/openssl/is_boringssl.h b/lib/boringssl/include/openssl/is_boringssl.h new file mode 100644 index 00000000..302cbe29 --- /dev/null +++ b/lib/boringssl/include/openssl/is_boringssl.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2017, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +// This header is provided in order to catch include path errors in consuming +// BoringSSL. diff --git a/lib/boringssl/include/openssl/kdf.h b/lib/boringssl/include/openssl/kdf.h new file mode 100644 index 00000000..7adad381 --- /dev/null +++ b/lib/boringssl/include/openssl/kdf.h @@ -0,0 +1,91 @@ +/* Copyright (c) 2022, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_KDF_H +#define OPENSSL_HEADER_KDF_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// KDF support for EVP. + + +// HKDF-specific functions. +// +// The following functions are provided for OpenSSL compatibility. Prefer the +// HKDF functions in . In each, |ctx| must be created with +// |EVP_PKEY_CTX_new_id| with |EVP_PKEY_HKDF| and then initialized with +// |EVP_PKEY_derive_init|. + +// EVP_PKEY_HKDEF_MODE_* define "modes" for use with |EVP_PKEY_CTX_hkdf_mode|. +// The mispelling of "HKDF" as "HKDEF" is intentional for OpenSSL compatibility. +#define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0 +#define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY 1 +#define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY 2 + +// EVP_PKEY_CTX_hkdf_mode configures which HKDF operation to run. It returns one +// on success and zero on error. |mode| must be one of |EVP_PKEY_HKDEF_MODE_*|. +// By default, the mode is |EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND|. +// +// If |mode| is |EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND| or +// |EVP_PKEY_HKDEF_MODE_EXPAND_ONLY|, the output is variable-length. +// |EVP_PKEY_derive| uses the size of the output buffer as the output length for +// HKDF-Expand. +// +// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand +// are distinct operations with distinct inputs and distinct kinds of keys. +// Callers should not pass input secrets for one operation into the other. +OPENSSL_EXPORT int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *ctx, int mode); + +// EVP_PKEY_CTX_set_hkdf_md sets |md| as the digest to use with HKDF. It returns +// one on success and zero on error. +OPENSSL_EXPORT int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +// EVP_PKEY_CTX_set1_hkdf_key configures HKDF to use |key_len| bytes from |key| +// as the "key", described below. It returns one on success and zero on error. +// +// Which input is the key depends on the "mode" (see |EVP_PKEY_CTX_hkdf_mode|). +// If |EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND| or +// |EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY|, this function specifies the input keying +// material (IKM) for HKDF-Extract. If |EVP_PKEY_HKDEF_MODE_EXPAND_ONLY|, it +// instead specifies the pseudorandom key (PRK) for HKDF-Expand. +OPENSSL_EXPORT int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx, + const uint8_t *key, + size_t key_len); + +// EVP_PKEY_CTX_set1_hkdf_salt configures HKDF to use |salt_len| bytes from +// |salt| as the salt parameter to HKDF-Extract. It returns one on success and +// zero on error. If performing HKDF-Expand only, this parameter is ignored. +OPENSSL_EXPORT int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx, + const uint8_t *salt, + size_t salt_len); + +// EVP_PKEY_CTX_add1_hkdf_info appends |info_len| bytes from |info| to the info +// parameter used with HKDF-Expand. It returns one on success and zero on error. +// If performing HKDF-Extract only, this parameter is ignored. +OPENSSL_EXPORT int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx, + const uint8_t *info, + size_t info_len); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_KDF_H diff --git a/lib/boringssl/include/openssl/kyber.h b/lib/boringssl/include/openssl/kyber.h new file mode 100644 index 00000000..cafae9d1 --- /dev/null +++ b/lib/boringssl/include/openssl/kyber.h @@ -0,0 +1,128 @@ +/* Copyright (c) 2023, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_KYBER_H +#define OPENSSL_HEADER_KYBER_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Kyber768. + + +// KYBER_public_key contains a Kyber768 public key. The contents of this +// object should never leave the address space since the format is unstable. +struct KYBER_public_key { + union { + uint8_t bytes[512 * (3 + 9) + 32 + 32]; + uint16_t alignment; + } opaque; +}; + +// KYBER_private_key contains a Kyber768 private key. The contents of this +// object should never leave the address space since the format is unstable. +struct KYBER_private_key { + union { + uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32]; + uint16_t alignment; + } opaque; +}; + +// KYBER_PUBLIC_KEY_BYTES is the number of bytes in an encoded Kyber768 public +// key. +#define KYBER_PUBLIC_KEY_BYTES 1184 + +// KYBER_generate_key generates a random public/private key pair, writes the +// encoded public key to |out_encoded_public_key| and sets |out_private_key| to +// the private key. +OPENSSL_EXPORT void KYBER_generate_key( + uint8_t out_encoded_public_key[KYBER_PUBLIC_KEY_BYTES], + struct KYBER_private_key *out_private_key); + +// KYBER_public_from_private sets |*out_public_key| to the public key that +// corresponds to |private_key|. (This is faster than parsing the output of +// |KYBER_generate_key| if, for some reason, you need to encapsulate to a key +// that was just generated.) +OPENSSL_EXPORT void KYBER_public_from_private( + struct KYBER_public_key *out_public_key, + const struct KYBER_private_key *private_key); + +// KYBER_CIPHERTEXT_BYTES is number of bytes in the Kyber768 ciphertext. +#define KYBER_CIPHERTEXT_BYTES 1088 + +// KYBER_encap encrypts a random secret key of length |out_shared_secret_len| to +// |public_key|, writes the ciphertext to |ciphertext|, and writes the random +// key to |out_shared_secret|. The party calling |KYBER_decap| must already know +// the correct value of |out_shared_secret_len|. +OPENSSL_EXPORT void KYBER_encap(uint8_t out_ciphertext[KYBER_CIPHERTEXT_BYTES], + uint8_t *out_shared_secret, + size_t out_shared_secret_len, + const struct KYBER_public_key *public_key); + +// KYBER_decap decrypts a key of length |out_shared_secret_len| from +// |ciphertext| using |private_key| and writes it to |out_shared_secret|. If +// |ciphertext| is invalid, |out_shared_secret| is filled with a key that +// will always be the same for the same |ciphertext| and |private_key|, but +// which appears to be random unless one has access to |private_key|. These +// alternatives occur in constant time. Any subsequent symmetric encryption +// using |out_shared_secret| must use an authenticated encryption scheme in +// order to discover the decapsulation failure. +OPENSSL_EXPORT void KYBER_decap( + uint8_t *out_shared_secret, size_t out_shared_secret_len, + const uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES], + const struct KYBER_private_key *private_key); + + +// Serialisation of keys. + +// KYBER_marshal_public_key serializes |public_key| to |out| in the standard +// format for Kyber public keys. It returns one on success or zero on allocation +// error. +OPENSSL_EXPORT int KYBER_marshal_public_key( + CBB *out, const struct KYBER_public_key *public_key); + +// KYBER_parse_public_key parses a public key, in the format generated by +// |KYBER_marshal_public_key|, from |in| and writes the result to +// |out_public_key|. It returns one on success or zero on parse error or if +// there are trailing bytes in |in|. +OPENSSL_EXPORT int KYBER_parse_public_key( + struct KYBER_public_key *out_public_key, CBS *in); + +// KYBER_marshal_private_key serializes |private_key| to |out| in the standard +// format for Kyber private keys. It returns one on success or zero on +// allocation error. +OPENSSL_EXPORT int KYBER_marshal_private_key( + CBB *out, const struct KYBER_private_key *private_key); + +// KYBER_PRIVATE_KEY_BYTES is the length of the data produced by +// |KYBER_marshal_private_key|. +#define KYBER_PRIVATE_KEY_BYTES 2400 + +// KYBER_parse_private_key parses a private key, in the format generated by +// |KYBER_marshal_private_key|, from |in| and writes the result to +// |out_private_key|. It returns one on success or zero on parse error or if +// there are trailing bytes in |in|. +OPENSSL_EXPORT int KYBER_parse_private_key( + struct KYBER_private_key *out_private_key, CBS *in); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_KYBER_H diff --git a/lib/boringssl/include/openssl/lhash.h b/lib/boringssl/include/openssl/lhash.h new file mode 100644 index 00000000..12975416 --- /dev/null +++ b/lib/boringssl/include/openssl/lhash.h @@ -0,0 +1,81 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_LHASH_H +#define OPENSSL_HEADER_LHASH_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// lhash is an internal library and not exported for use outside BoringSSL. This +// header is provided for compatibility with code that expects OpenSSL. + + +// These two macros are exported for compatibility with existing callers of +// |X509V3_EXT_conf_nid|. Do not use these symbols outside BoringSSL. +#define LHASH_OF(type) struct lhash_st_##type +#define DECLARE_LHASH_OF(type) LHASH_OF(type); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_LHASH_H diff --git a/lib/boringssl/include/openssl/md4.h b/lib/boringssl/include/openssl/md4.h new file mode 100644 index 00000000..b213bc62 --- /dev/null +++ b/lib/boringssl/include/openssl/md4.h @@ -0,0 +1,108 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_MD4_H +#define OPENSSL_HEADER_MD4_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// MD4. + +// MD4_CBLOCK is the block size of MD4. +#define MD4_CBLOCK 64 + +// MD4_DIGEST_LENGTH is the length of an MD4 digest. +#define MD4_DIGEST_LENGTH 16 + +// MD4_Init initialises |md4| and returns one. +OPENSSL_EXPORT int MD4_Init(MD4_CTX *md4); + +// MD4_Update adds |len| bytes from |data| to |md4| and returns one. +OPENSSL_EXPORT int MD4_Update(MD4_CTX *md4, const void *data, size_t len); + +// MD4_Final adds the final padding to |md4| and writes the resulting digest to +// |out|, which must have at least |MD4_DIGEST_LENGTH| bytes of space. It +// returns one. +OPENSSL_EXPORT int MD4_Final(uint8_t out[MD4_DIGEST_LENGTH], MD4_CTX *md4); + +// MD4 writes the digest of |len| bytes from |data| to |out| and returns |out|. +// There must be at least |MD4_DIGEST_LENGTH| bytes of space in |out|. +OPENSSL_EXPORT uint8_t *MD4(const uint8_t *data, size_t len, + uint8_t out[MD4_DIGEST_LENGTH]); + +// MD4_Transform is a low-level function that performs a single, MD4 block +// transformation using the state from |md4| and 64 bytes from |block|. +OPENSSL_EXPORT void MD4_Transform(MD4_CTX *md4, + const uint8_t block[MD4_CBLOCK]); + +struct md4_state_st { + uint32_t h[4]; + uint32_t Nl, Nh; + uint8_t data[MD4_CBLOCK]; + unsigned num; +}; + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_MD4_H diff --git a/lib/boringssl/include/openssl/md5.h b/lib/boringssl/include/openssl/md5.h new file mode 100644 index 00000000..54865129 --- /dev/null +++ b/lib/boringssl/include/openssl/md5.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_MD5_H +#define OPENSSL_HEADER_MD5_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// MD5. + + +// MD5_CBLOCK is the block size of MD5. +#define MD5_CBLOCK 64 + +// MD5_DIGEST_LENGTH is the length of an MD5 digest. +#define MD5_DIGEST_LENGTH 16 + +// MD5_Init initialises |md5| and returns one. +OPENSSL_EXPORT int MD5_Init(MD5_CTX *md5); + +// MD5_Update adds |len| bytes from |data| to |md5| and returns one. +OPENSSL_EXPORT int MD5_Update(MD5_CTX *md5, const void *data, size_t len); + +// MD5_Final adds the final padding to |md5| and writes the resulting digest to +// |out|, which must have at least |MD5_DIGEST_LENGTH| bytes of space. It +// returns one. +OPENSSL_EXPORT int MD5_Final(uint8_t out[MD5_DIGEST_LENGTH], MD5_CTX *md5); + +// MD5 writes the digest of |len| bytes from |data| to |out| and returns |out|. +// There must be at least |MD5_DIGEST_LENGTH| bytes of space in |out|. +OPENSSL_EXPORT uint8_t *MD5(const uint8_t *data, size_t len, + uint8_t out[MD5_DIGEST_LENGTH]); + +// MD5_Transform is a low-level function that performs a single, MD5 block +// transformation using the state from |md5| and 64 bytes from |block|. +OPENSSL_EXPORT void MD5_Transform(MD5_CTX *md5, + const uint8_t block[MD5_CBLOCK]); + +struct md5_state_st { + uint32_t h[4]; + uint32_t Nl, Nh; + uint8_t data[MD5_CBLOCK]; + unsigned num; +}; + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_MD5_H diff --git a/lib/boringssl/include/openssl/mem.h b/lib/boringssl/include/openssl/mem.h new file mode 100644 index 00000000..8da1dd67 --- /dev/null +++ b/lib/boringssl/include/openssl/mem.h @@ -0,0 +1,250 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_MEM_H +#define OPENSSL_HEADER_MEM_H + +#include + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Memory and string functions, see also buf.h. +// +// BoringSSL has its own set of allocation functions, which keep track of +// allocation lengths and zero them out before freeing. All memory returned by +// BoringSSL API calls must therefore generally be freed using |OPENSSL_free| +// unless stated otherwise. + + +#ifndef _BORINGSSL_PROHIBIT_OPENSSL_MALLOC +// OPENSSL_malloc is similar to a regular |malloc|, but allocates additional +// private data. The resulting pointer must be freed with |OPENSSL_free|. In +// the case of a malloc failure, prior to returning NULL |OPENSSL_malloc| will +// push |ERR_R_MALLOC_FAILURE| onto the openssl error stack. +OPENSSL_EXPORT void *OPENSSL_malloc(size_t size); +#endif // !_BORINGSSL_PROHIBIT_OPENSSL_MALLOC + +// OPENSSL_free does nothing if |ptr| is NULL. Otherwise it zeros out the +// memory allocated at |ptr| and frees it along with the private data. +// It must only be used on on |ptr| values obtained from |OPENSSL_malloc| +OPENSSL_EXPORT void OPENSSL_free(void *ptr); + +#ifndef _BORINGSSL_PROHIBIT_OPENSSL_MALLOC +// OPENSSL_realloc returns a pointer to a buffer of |new_size| bytes that +// contains the contents of |ptr|. Unlike |realloc|, a new buffer is always +// allocated and the data at |ptr| is always wiped and freed. Memory is +// allocated with |OPENSSL_malloc| and must be freed with |OPENSSL_free|. +OPENSSL_EXPORT void *OPENSSL_realloc(void *ptr, size_t new_size); +#endif // !_BORINGSSL_PROHIBIT_OPENSSL_MALLOC + +// OPENSSL_cleanse zeros out |len| bytes of memory at |ptr|. This is similar to +// |memset_s| from C11. +OPENSSL_EXPORT void OPENSSL_cleanse(void *ptr, size_t len); + +// CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. It +// takes an amount of time dependent on |len|, but independent of the contents +// of |a| and |b|. Unlike memcmp, it cannot be used to put elements into a +// defined order as the return value when a != b is undefined, other than to be +// non-zero. +OPENSSL_EXPORT int CRYPTO_memcmp(const void *a, const void *b, size_t len); + +// OPENSSL_hash32 implements the 32 bit, FNV-1a hash. +OPENSSL_EXPORT uint32_t OPENSSL_hash32(const void *ptr, size_t len); + +// OPENSSL_strhash calls |OPENSSL_hash32| on the NUL-terminated string |s|. +OPENSSL_EXPORT uint32_t OPENSSL_strhash(const char *s); + +// OPENSSL_strdup has the same behaviour as strdup(3). +OPENSSL_EXPORT char *OPENSSL_strdup(const char *s); + +// OPENSSL_strnlen has the same behaviour as strnlen(3). +OPENSSL_EXPORT size_t OPENSSL_strnlen(const char *s, size_t len); + +// OPENSSL_isalpha is a locale-independent, ASCII-only version of isalpha(3), It +// only recognizes 'a' through 'z' and 'A' through 'Z' as alphabetic. +OPENSSL_EXPORT int OPENSSL_isalpha(int c); + +// OPENSSL_isdigit is a locale-independent, ASCII-only version of isdigit(3), It +// only recognizes '0' through '9' as digits. +OPENSSL_EXPORT int OPENSSL_isdigit(int c); + +// OPENSSL_isxdigit is a locale-independent, ASCII-only version of isxdigit(3), +// It only recognizes '0' through '9', 'a' through 'f', and 'A through 'F' as +// digits. +OPENSSL_EXPORT int OPENSSL_isxdigit(int c); + +// OPENSSL_fromxdigit returns one if |c| is a hexadecimal digit as recognized +// by OPENSSL_isxdigit, and sets |out| to the corresponding value. Otherwise +// zero is returned. +OPENSSL_EXPORT int OPENSSL_fromxdigit(uint8_t *out, int c); + +// OPENSSL_isalnum is a locale-independent, ASCII-only version of isalnum(3), It +// only recognizes what |OPENSSL_isalpha| and |OPENSSL_isdigit| recognize. +OPENSSL_EXPORT int OPENSSL_isalnum(int c); + +// OPENSSL_tolower is a locale-independent, ASCII-only version of tolower(3). It +// only lowercases ASCII values. Other values are returned as-is. +OPENSSL_EXPORT int OPENSSL_tolower(int c); + +// OPENSSL_isspace is a locale-independent, ASCII-only version of isspace(3). It +// only recognizes '\t', '\n', '\v', '\f', '\r', and ' '. +OPENSSL_EXPORT int OPENSSL_isspace(int c); + +// OPENSSL_strcasecmp is a locale-independent, ASCII-only version of +// strcasecmp(3). +OPENSSL_EXPORT int OPENSSL_strcasecmp(const char *a, const char *b); + +// OPENSSL_strncasecmp is a locale-independent, ASCII-only version of +// strncasecmp(3). +OPENSSL_EXPORT int OPENSSL_strncasecmp(const char *a, const char *b, size_t n); + +// DECIMAL_SIZE returns an upper bound for the length of the decimal +// representation of the given type. +#define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1) + +// BIO_snprintf has the same behavior as snprintf(3). +OPENSSL_EXPORT int BIO_snprintf(char *buf, size_t n, const char *format, ...) + OPENSSL_PRINTF_FORMAT_FUNC(3, 4); + +// BIO_vsnprintf has the same behavior as vsnprintf(3). +OPENSSL_EXPORT int BIO_vsnprintf(char *buf, size_t n, const char *format, + va_list args) OPENSSL_PRINTF_FORMAT_FUNC(3, 0); + +// OPENSSL_vasprintf has the same behavior as vasprintf(3), except that +// memory allocated in a returned string must be freed with |OPENSSL_free|. +OPENSSL_EXPORT int OPENSSL_vasprintf(char **str, const char *format, + va_list args) + OPENSSL_PRINTF_FORMAT_FUNC(2, 0); + +// OPENSSL_asprintf has the same behavior as asprintf(3), except that +// memory allocated in a returned string must be freed with |OPENSSL_free|. +OPENSSL_EXPORT int OPENSSL_asprintf(char **str, const char *format, ...) + OPENSSL_PRINTF_FORMAT_FUNC(2, 3); + +// OPENSSL_strndup returns an allocated, duplicate of |str|, which is, at most, +// |size| bytes. The result is always NUL terminated. The memory allocated +// must be freed with |OPENSSL_free|. +OPENSSL_EXPORT char *OPENSSL_strndup(const char *str, size_t size); + +// OPENSSL_memdup returns an allocated, duplicate of |size| bytes from |data| or +// NULL on allocation failure. The memory allocated must be freed with +// |OPENSSL_free|. +OPENSSL_EXPORT void *OPENSSL_memdup(const void *data, size_t size); + +// OPENSSL_strlcpy acts like strlcpy(3). +OPENSSL_EXPORT size_t OPENSSL_strlcpy(char *dst, const char *src, + size_t dst_size); + +// OPENSSL_strlcat acts like strlcat(3). +OPENSSL_EXPORT size_t OPENSSL_strlcat(char *dst, const char *src, + size_t dst_size); + + +// Deprecated functions. + +// CRYPTO_malloc calls |OPENSSL_malloc|. |file| and |line| are ignored. +OPENSSL_EXPORT void *CRYPTO_malloc(size_t size, const char *file, int line); + +// CRYPTO_realloc calls |OPENSSL_realloc|. |file| and |line| are ignored. +OPENSSL_EXPORT void *CRYPTO_realloc(void *ptr, size_t new_size, + const char *file, int line); + +// CRYPTO_free calls |OPENSSL_free|. |file| and |line| are ignored. +OPENSSL_EXPORT void CRYPTO_free(void *ptr, const char *file, int line); + +// OPENSSL_clear_free calls |OPENSSL_free|. BoringSSL automatically clears all +// allocations on free, but we define |OPENSSL_clear_free| for compatibility. +OPENSSL_EXPORT void OPENSSL_clear_free(void *ptr, size_t len); + +// CRYPTO_secure_malloc_init returns zero. +OPENSSL_EXPORT int CRYPTO_secure_malloc_init(size_t size, size_t min_size); + +// CRYPTO_secure_malloc_initialized returns zero. +OPENSSL_EXPORT int CRYPTO_secure_malloc_initialized(void); + +// CRYPTO_secure_used returns zero. +OPENSSL_EXPORT size_t CRYPTO_secure_used(void); + +// OPENSSL_secure_malloc calls |OPENSSL_malloc|. +OPENSSL_EXPORT void *OPENSSL_secure_malloc(size_t size); + +// OPENSSL_secure_clear_free calls |OPENSSL_clear_free|. +OPENSSL_EXPORT void OPENSSL_secure_clear_free(void *ptr, size_t len); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(char, OPENSSL_free) +BORINGSSL_MAKE_DELETER(uint8_t, OPENSSL_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#endif // OPENSSL_HEADER_MEM_H diff --git a/lib/boringssl/include/openssl/nid.h b/lib/boringssl/include/openssl/nid.h new file mode 100644 index 00000000..4dd8841b --- /dev/null +++ b/lib/boringssl/include/openssl/nid.h @@ -0,0 +1,4263 @@ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +/* This file is generated by crypto/obj/objects.go. */ + +#ifndef OPENSSL_HEADER_NID_H +#define OPENSSL_HEADER_NID_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* The nid library provides numbered values for ASN.1 object identifiers and + * other symbols. These values are used by other libraries to identify + * cryptographic primitives. + * + * A separate objects library, obj.h, provides functions for converting between + * nids and object identifiers. However it depends on large internal tables with + * the encodings of every nid defined. Consumers concerned with binary size + * should instead embed the encodings of the few consumed OIDs and compare + * against those. + * + * These values should not be used outside of a single process; they are not + * stable identifiers. */ + + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L + +#define SN_rsadsi "rsadsi" +#define LN_rsadsi "RSA Data Security, Inc." +#define NID_rsadsi 1 +#define OBJ_rsadsi 1L, 2L, 840L, 113549L + +#define SN_pkcs "pkcs" +#define LN_pkcs "RSA Data Security, Inc. PKCS" +#define NID_pkcs 2 +#define OBJ_pkcs 1L, 2L, 840L, 113549L, 1L + +#define SN_md2 "MD2" +#define LN_md2 "md2" +#define NID_md2 3 +#define OBJ_md2 1L, 2L, 840L, 113549L, 2L, 2L + +#define SN_md5 "MD5" +#define LN_md5 "md5" +#define NID_md5 4 +#define OBJ_md5 1L, 2L, 840L, 113549L, 2L, 5L + +#define SN_rc4 "RC4" +#define LN_rc4 "rc4" +#define NID_rc4 5 +#define OBJ_rc4 1L, 2L, 840L, 113549L, 3L, 4L + +#define LN_rsaEncryption "rsaEncryption" +#define NID_rsaEncryption 6 +#define OBJ_rsaEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 1L + +#define SN_md2WithRSAEncryption "RSA-MD2" +#define LN_md2WithRSAEncryption "md2WithRSAEncryption" +#define NID_md2WithRSAEncryption 7 +#define OBJ_md2WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 2L + +#define SN_md5WithRSAEncryption "RSA-MD5" +#define LN_md5WithRSAEncryption "md5WithRSAEncryption" +#define NID_md5WithRSAEncryption 8 +#define OBJ_md5WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 4L + +#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES" +#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC" +#define NID_pbeWithMD2AndDES_CBC 9 +#define OBJ_pbeWithMD2AndDES_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 1L + +#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES" +#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC" +#define NID_pbeWithMD5AndDES_CBC 10 +#define OBJ_pbeWithMD5AndDES_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 3L + +#define SN_X500 "X500" +#define LN_X500 "directory services (X.500)" +#define NID_X500 11 +#define OBJ_X500 2L, 5L + +#define SN_X509 "X509" +#define NID_X509 12 +#define OBJ_X509 2L, 5L, 4L + +#define SN_commonName "CN" +#define LN_commonName "commonName" +#define NID_commonName 13 +#define OBJ_commonName 2L, 5L, 4L, 3L + +#define SN_countryName "C" +#define LN_countryName "countryName" +#define NID_countryName 14 +#define OBJ_countryName 2L, 5L, 4L, 6L + +#define SN_localityName "L" +#define LN_localityName "localityName" +#define NID_localityName 15 +#define OBJ_localityName 2L, 5L, 4L, 7L + +#define SN_stateOrProvinceName "ST" +#define LN_stateOrProvinceName "stateOrProvinceName" +#define NID_stateOrProvinceName 16 +#define OBJ_stateOrProvinceName 2L, 5L, 4L, 8L + +#define SN_organizationName "O" +#define LN_organizationName "organizationName" +#define NID_organizationName 17 +#define OBJ_organizationName 2L, 5L, 4L, 10L + +#define SN_organizationalUnitName "OU" +#define LN_organizationalUnitName "organizationalUnitName" +#define NID_organizationalUnitName 18 +#define OBJ_organizationalUnitName 2L, 5L, 4L, 11L + +#define SN_rsa "RSA" +#define LN_rsa "rsa" +#define NID_rsa 19 +#define OBJ_rsa 2L, 5L, 8L, 1L, 1L + +#define SN_pkcs7 "pkcs7" +#define NID_pkcs7 20 +#define OBJ_pkcs7 1L, 2L, 840L, 113549L, 1L, 7L + +#define LN_pkcs7_data "pkcs7-data" +#define NID_pkcs7_data 21 +#define OBJ_pkcs7_data 1L, 2L, 840L, 113549L, 1L, 7L, 1L + +#define LN_pkcs7_signed "pkcs7-signedData" +#define NID_pkcs7_signed 22 +#define OBJ_pkcs7_signed 1L, 2L, 840L, 113549L, 1L, 7L, 2L + +#define LN_pkcs7_enveloped "pkcs7-envelopedData" +#define NID_pkcs7_enveloped 23 +#define OBJ_pkcs7_enveloped 1L, 2L, 840L, 113549L, 1L, 7L, 3L + +#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData" +#define NID_pkcs7_signedAndEnveloped 24 +#define OBJ_pkcs7_signedAndEnveloped 1L, 2L, 840L, 113549L, 1L, 7L, 4L + +#define LN_pkcs7_digest "pkcs7-digestData" +#define NID_pkcs7_digest 25 +#define OBJ_pkcs7_digest 1L, 2L, 840L, 113549L, 1L, 7L, 5L + +#define LN_pkcs7_encrypted "pkcs7-encryptedData" +#define NID_pkcs7_encrypted 26 +#define OBJ_pkcs7_encrypted 1L, 2L, 840L, 113549L, 1L, 7L, 6L + +#define SN_pkcs3 "pkcs3" +#define NID_pkcs3 27 +#define OBJ_pkcs3 1L, 2L, 840L, 113549L, 1L, 3L + +#define LN_dhKeyAgreement "dhKeyAgreement" +#define NID_dhKeyAgreement 28 +#define OBJ_dhKeyAgreement 1L, 2L, 840L, 113549L, 1L, 3L, 1L + +#define SN_des_ecb "DES-ECB" +#define LN_des_ecb "des-ecb" +#define NID_des_ecb 29 +#define OBJ_des_ecb 1L, 3L, 14L, 3L, 2L, 6L + +#define SN_des_cfb64 "DES-CFB" +#define LN_des_cfb64 "des-cfb" +#define NID_des_cfb64 30 +#define OBJ_des_cfb64 1L, 3L, 14L, 3L, 2L, 9L + +#define SN_des_cbc "DES-CBC" +#define LN_des_cbc "des-cbc" +#define NID_des_cbc 31 +#define OBJ_des_cbc 1L, 3L, 14L, 3L, 2L, 7L + +#define SN_des_ede_ecb "DES-EDE" +#define LN_des_ede_ecb "des-ede" +#define NID_des_ede_ecb 32 +#define OBJ_des_ede_ecb 1L, 3L, 14L, 3L, 2L, 17L + +#define SN_des_ede3_ecb "DES-EDE3" +#define LN_des_ede3_ecb "des-ede3" +#define NID_des_ede3_ecb 33 + +#define SN_idea_cbc "IDEA-CBC" +#define LN_idea_cbc "idea-cbc" +#define NID_idea_cbc 34 +#define OBJ_idea_cbc 1L, 3L, 6L, 1L, 4L, 1L, 188L, 7L, 1L, 1L, 2L + +#define SN_idea_cfb64 "IDEA-CFB" +#define LN_idea_cfb64 "idea-cfb" +#define NID_idea_cfb64 35 + +#define SN_idea_ecb "IDEA-ECB" +#define LN_idea_ecb "idea-ecb" +#define NID_idea_ecb 36 + +#define SN_rc2_cbc "RC2-CBC" +#define LN_rc2_cbc "rc2-cbc" +#define NID_rc2_cbc 37 +#define OBJ_rc2_cbc 1L, 2L, 840L, 113549L, 3L, 2L + +#define SN_rc2_ecb "RC2-ECB" +#define LN_rc2_ecb "rc2-ecb" +#define NID_rc2_ecb 38 + +#define SN_rc2_cfb64 "RC2-CFB" +#define LN_rc2_cfb64 "rc2-cfb" +#define NID_rc2_cfb64 39 + +#define SN_rc2_ofb64 "RC2-OFB" +#define LN_rc2_ofb64 "rc2-ofb" +#define NID_rc2_ofb64 40 + +#define SN_sha "SHA" +#define LN_sha "sha" +#define NID_sha 41 +#define OBJ_sha 1L, 3L, 14L, 3L, 2L, 18L + +#define SN_shaWithRSAEncryption "RSA-SHA" +#define LN_shaWithRSAEncryption "shaWithRSAEncryption" +#define NID_shaWithRSAEncryption 42 +#define OBJ_shaWithRSAEncryption 1L, 3L, 14L, 3L, 2L, 15L + +#define SN_des_ede_cbc "DES-EDE-CBC" +#define LN_des_ede_cbc "des-ede-cbc" +#define NID_des_ede_cbc 43 + +#define SN_des_ede3_cbc "DES-EDE3-CBC" +#define LN_des_ede3_cbc "des-ede3-cbc" +#define NID_des_ede3_cbc 44 +#define OBJ_des_ede3_cbc 1L, 2L, 840L, 113549L, 3L, 7L + +#define SN_des_ofb64 "DES-OFB" +#define LN_des_ofb64 "des-ofb" +#define NID_des_ofb64 45 +#define OBJ_des_ofb64 1L, 3L, 14L, 3L, 2L, 8L + +#define SN_idea_ofb64 "IDEA-OFB" +#define LN_idea_ofb64 "idea-ofb" +#define NID_idea_ofb64 46 + +#define SN_pkcs9 "pkcs9" +#define NID_pkcs9 47 +#define OBJ_pkcs9 1L, 2L, 840L, 113549L, 1L, 9L + +#define LN_pkcs9_emailAddress "emailAddress" +#define NID_pkcs9_emailAddress 48 +#define OBJ_pkcs9_emailAddress 1L, 2L, 840L, 113549L, 1L, 9L, 1L + +#define LN_pkcs9_unstructuredName "unstructuredName" +#define NID_pkcs9_unstructuredName 49 +#define OBJ_pkcs9_unstructuredName 1L, 2L, 840L, 113549L, 1L, 9L, 2L + +#define LN_pkcs9_contentType "contentType" +#define NID_pkcs9_contentType 50 +#define OBJ_pkcs9_contentType 1L, 2L, 840L, 113549L, 1L, 9L, 3L + +#define LN_pkcs9_messageDigest "messageDigest" +#define NID_pkcs9_messageDigest 51 +#define OBJ_pkcs9_messageDigest 1L, 2L, 840L, 113549L, 1L, 9L, 4L + +#define LN_pkcs9_signingTime "signingTime" +#define NID_pkcs9_signingTime 52 +#define OBJ_pkcs9_signingTime 1L, 2L, 840L, 113549L, 1L, 9L, 5L + +#define LN_pkcs9_countersignature "countersignature" +#define NID_pkcs9_countersignature 53 +#define OBJ_pkcs9_countersignature 1L, 2L, 840L, 113549L, 1L, 9L, 6L + +#define LN_pkcs9_challengePassword "challengePassword" +#define NID_pkcs9_challengePassword 54 +#define OBJ_pkcs9_challengePassword 1L, 2L, 840L, 113549L, 1L, 9L, 7L + +#define LN_pkcs9_unstructuredAddress "unstructuredAddress" +#define NID_pkcs9_unstructuredAddress 55 +#define OBJ_pkcs9_unstructuredAddress 1L, 2L, 840L, 113549L, 1L, 9L, 8L + +#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes" +#define NID_pkcs9_extCertAttributes 56 +#define OBJ_pkcs9_extCertAttributes 1L, 2L, 840L, 113549L, 1L, 9L, 9L + +#define SN_netscape "Netscape" +#define LN_netscape "Netscape Communications Corp." +#define NID_netscape 57 +#define OBJ_netscape 2L, 16L, 840L, 1L, 113730L + +#define SN_netscape_cert_extension "nsCertExt" +#define LN_netscape_cert_extension "Netscape Certificate Extension" +#define NID_netscape_cert_extension 58 +#define OBJ_netscape_cert_extension 2L, 16L, 840L, 1L, 113730L, 1L + +#define SN_netscape_data_type "nsDataType" +#define LN_netscape_data_type "Netscape Data Type" +#define NID_netscape_data_type 59 +#define OBJ_netscape_data_type 2L, 16L, 840L, 1L, 113730L, 2L + +#define SN_des_ede_cfb64 "DES-EDE-CFB" +#define LN_des_ede_cfb64 "des-ede-cfb" +#define NID_des_ede_cfb64 60 + +#define SN_des_ede3_cfb64 "DES-EDE3-CFB" +#define LN_des_ede3_cfb64 "des-ede3-cfb" +#define NID_des_ede3_cfb64 61 + +#define SN_des_ede_ofb64 "DES-EDE-OFB" +#define LN_des_ede_ofb64 "des-ede-ofb" +#define NID_des_ede_ofb64 62 + +#define SN_des_ede3_ofb64 "DES-EDE3-OFB" +#define LN_des_ede3_ofb64 "des-ede3-ofb" +#define NID_des_ede3_ofb64 63 + +#define SN_sha1 "SHA1" +#define LN_sha1 "sha1" +#define NID_sha1 64 +#define OBJ_sha1 1L, 3L, 14L, 3L, 2L, 26L + +#define SN_sha1WithRSAEncryption "RSA-SHA1" +#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption" +#define NID_sha1WithRSAEncryption 65 +#define OBJ_sha1WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 5L + +#define SN_dsaWithSHA "DSA-SHA" +#define LN_dsaWithSHA "dsaWithSHA" +#define NID_dsaWithSHA 66 +#define OBJ_dsaWithSHA 1L, 3L, 14L, 3L, 2L, 13L + +#define SN_dsa_2 "DSA-old" +#define LN_dsa_2 "dsaEncryption-old" +#define NID_dsa_2 67 +#define OBJ_dsa_2 1L, 3L, 14L, 3L, 2L, 12L + +#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64" +#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC" +#define NID_pbeWithSHA1AndRC2_CBC 68 +#define OBJ_pbeWithSHA1AndRC2_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 11L + +#define LN_id_pbkdf2 "PBKDF2" +#define NID_id_pbkdf2 69 +#define OBJ_id_pbkdf2 1L, 2L, 840L, 113549L, 1L, 5L, 12L + +#define SN_dsaWithSHA1_2 "DSA-SHA1-old" +#define LN_dsaWithSHA1_2 "dsaWithSHA1-old" +#define NID_dsaWithSHA1_2 70 +#define OBJ_dsaWithSHA1_2 1L, 3L, 14L, 3L, 2L, 27L + +#define SN_netscape_cert_type "nsCertType" +#define LN_netscape_cert_type "Netscape Cert Type" +#define NID_netscape_cert_type 71 +#define OBJ_netscape_cert_type 2L, 16L, 840L, 1L, 113730L, 1L, 1L + +#define SN_netscape_base_url "nsBaseUrl" +#define LN_netscape_base_url "Netscape Base Url" +#define NID_netscape_base_url 72 +#define OBJ_netscape_base_url 2L, 16L, 840L, 1L, 113730L, 1L, 2L + +#define SN_netscape_revocation_url "nsRevocationUrl" +#define LN_netscape_revocation_url "Netscape Revocation Url" +#define NID_netscape_revocation_url 73 +#define OBJ_netscape_revocation_url 2L, 16L, 840L, 1L, 113730L, 1L, 3L + +#define SN_netscape_ca_revocation_url "nsCaRevocationUrl" +#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url" +#define NID_netscape_ca_revocation_url 74 +#define OBJ_netscape_ca_revocation_url 2L, 16L, 840L, 1L, 113730L, 1L, 4L + +#define SN_netscape_renewal_url "nsRenewalUrl" +#define LN_netscape_renewal_url "Netscape Renewal Url" +#define NID_netscape_renewal_url 75 +#define OBJ_netscape_renewal_url 2L, 16L, 840L, 1L, 113730L, 1L, 7L + +#define SN_netscape_ca_policy_url "nsCaPolicyUrl" +#define LN_netscape_ca_policy_url "Netscape CA Policy Url" +#define NID_netscape_ca_policy_url 76 +#define OBJ_netscape_ca_policy_url 2L, 16L, 840L, 1L, 113730L, 1L, 8L + +#define SN_netscape_ssl_server_name "nsSslServerName" +#define LN_netscape_ssl_server_name "Netscape SSL Server Name" +#define NID_netscape_ssl_server_name 77 +#define OBJ_netscape_ssl_server_name 2L, 16L, 840L, 1L, 113730L, 1L, 12L + +#define SN_netscape_comment "nsComment" +#define LN_netscape_comment "Netscape Comment" +#define NID_netscape_comment 78 +#define OBJ_netscape_comment 2L, 16L, 840L, 1L, 113730L, 1L, 13L + +#define SN_netscape_cert_sequence "nsCertSequence" +#define LN_netscape_cert_sequence "Netscape Certificate Sequence" +#define NID_netscape_cert_sequence 79 +#define OBJ_netscape_cert_sequence 2L, 16L, 840L, 1L, 113730L, 2L, 5L + +#define SN_desx_cbc "DESX-CBC" +#define LN_desx_cbc "desx-cbc" +#define NID_desx_cbc 80 + +#define SN_id_ce "id-ce" +#define NID_id_ce 81 +#define OBJ_id_ce 2L, 5L, 29L + +#define SN_subject_key_identifier "subjectKeyIdentifier" +#define LN_subject_key_identifier "X509v3 Subject Key Identifier" +#define NID_subject_key_identifier 82 +#define OBJ_subject_key_identifier 2L, 5L, 29L, 14L + +#define SN_key_usage "keyUsage" +#define LN_key_usage "X509v3 Key Usage" +#define NID_key_usage 83 +#define OBJ_key_usage 2L, 5L, 29L, 15L + +#define SN_private_key_usage_period "privateKeyUsagePeriod" +#define LN_private_key_usage_period "X509v3 Private Key Usage Period" +#define NID_private_key_usage_period 84 +#define OBJ_private_key_usage_period 2L, 5L, 29L, 16L + +#define SN_subject_alt_name "subjectAltName" +#define LN_subject_alt_name "X509v3 Subject Alternative Name" +#define NID_subject_alt_name 85 +#define OBJ_subject_alt_name 2L, 5L, 29L, 17L + +#define SN_issuer_alt_name "issuerAltName" +#define LN_issuer_alt_name "X509v3 Issuer Alternative Name" +#define NID_issuer_alt_name 86 +#define OBJ_issuer_alt_name 2L, 5L, 29L, 18L + +#define SN_basic_constraints "basicConstraints" +#define LN_basic_constraints "X509v3 Basic Constraints" +#define NID_basic_constraints 87 +#define OBJ_basic_constraints 2L, 5L, 29L, 19L + +#define SN_crl_number "crlNumber" +#define LN_crl_number "X509v3 CRL Number" +#define NID_crl_number 88 +#define OBJ_crl_number 2L, 5L, 29L, 20L + +#define SN_certificate_policies "certificatePolicies" +#define LN_certificate_policies "X509v3 Certificate Policies" +#define NID_certificate_policies 89 +#define OBJ_certificate_policies 2L, 5L, 29L, 32L + +#define SN_authority_key_identifier "authorityKeyIdentifier" +#define LN_authority_key_identifier "X509v3 Authority Key Identifier" +#define NID_authority_key_identifier 90 +#define OBJ_authority_key_identifier 2L, 5L, 29L, 35L + +#define SN_bf_cbc "BF-CBC" +#define LN_bf_cbc "bf-cbc" +#define NID_bf_cbc 91 +#define OBJ_bf_cbc 1L, 3L, 6L, 1L, 4L, 1L, 3029L, 1L, 2L + +#define SN_bf_ecb "BF-ECB" +#define LN_bf_ecb "bf-ecb" +#define NID_bf_ecb 92 + +#define SN_bf_cfb64 "BF-CFB" +#define LN_bf_cfb64 "bf-cfb" +#define NID_bf_cfb64 93 + +#define SN_bf_ofb64 "BF-OFB" +#define LN_bf_ofb64 "bf-ofb" +#define NID_bf_ofb64 94 + +#define SN_mdc2 "MDC2" +#define LN_mdc2 "mdc2" +#define NID_mdc2 95 +#define OBJ_mdc2 2L, 5L, 8L, 3L, 101L + +#define SN_mdc2WithRSA "RSA-MDC2" +#define LN_mdc2WithRSA "mdc2WithRSA" +#define NID_mdc2WithRSA 96 +#define OBJ_mdc2WithRSA 2L, 5L, 8L, 3L, 100L + +#define SN_rc4_40 "RC4-40" +#define LN_rc4_40 "rc4-40" +#define NID_rc4_40 97 + +#define SN_rc2_40_cbc "RC2-40-CBC" +#define LN_rc2_40_cbc "rc2-40-cbc" +#define NID_rc2_40_cbc 98 + +#define SN_givenName "GN" +#define LN_givenName "givenName" +#define NID_givenName 99 +#define OBJ_givenName 2L, 5L, 4L, 42L + +#define SN_surname "SN" +#define LN_surname "surname" +#define NID_surname 100 +#define OBJ_surname 2L, 5L, 4L, 4L + +#define SN_initials "initials" +#define LN_initials "initials" +#define NID_initials 101 +#define OBJ_initials 2L, 5L, 4L, 43L + +#define SN_crl_distribution_points "crlDistributionPoints" +#define LN_crl_distribution_points "X509v3 CRL Distribution Points" +#define NID_crl_distribution_points 103 +#define OBJ_crl_distribution_points 2L, 5L, 29L, 31L + +#define SN_md5WithRSA "RSA-NP-MD5" +#define LN_md5WithRSA "md5WithRSA" +#define NID_md5WithRSA 104 +#define OBJ_md5WithRSA 1L, 3L, 14L, 3L, 2L, 3L + +#define LN_serialNumber "serialNumber" +#define NID_serialNumber 105 +#define OBJ_serialNumber 2L, 5L, 4L, 5L + +#define SN_title "title" +#define LN_title "title" +#define NID_title 106 +#define OBJ_title 2L, 5L, 4L, 12L + +#define LN_description "description" +#define NID_description 107 +#define OBJ_description 2L, 5L, 4L, 13L + +#define SN_cast5_cbc "CAST5-CBC" +#define LN_cast5_cbc "cast5-cbc" +#define NID_cast5_cbc 108 +#define OBJ_cast5_cbc 1L, 2L, 840L, 113533L, 7L, 66L, 10L + +#define SN_cast5_ecb "CAST5-ECB" +#define LN_cast5_ecb "cast5-ecb" +#define NID_cast5_ecb 109 + +#define SN_cast5_cfb64 "CAST5-CFB" +#define LN_cast5_cfb64 "cast5-cfb" +#define NID_cast5_cfb64 110 + +#define SN_cast5_ofb64 "CAST5-OFB" +#define LN_cast5_ofb64 "cast5-ofb" +#define NID_cast5_ofb64 111 + +#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC" +#define NID_pbeWithMD5AndCast5_CBC 112 +#define OBJ_pbeWithMD5AndCast5_CBC 1L, 2L, 840L, 113533L, 7L, 66L, 12L + +#define SN_dsaWithSHA1 "DSA-SHA1" +#define LN_dsaWithSHA1 "dsaWithSHA1" +#define NID_dsaWithSHA1 113 +#define OBJ_dsaWithSHA1 1L, 2L, 840L, 10040L, 4L, 3L + +#define SN_md5_sha1 "MD5-SHA1" +#define LN_md5_sha1 "md5-sha1" +#define NID_md5_sha1 114 + +#define SN_sha1WithRSA "RSA-SHA1-2" +#define LN_sha1WithRSA "sha1WithRSA" +#define NID_sha1WithRSA 115 +#define OBJ_sha1WithRSA 1L, 3L, 14L, 3L, 2L, 29L + +#define SN_dsa "DSA" +#define LN_dsa "dsaEncryption" +#define NID_dsa 116 +#define OBJ_dsa 1L, 2L, 840L, 10040L, 4L, 1L + +#define SN_ripemd160 "RIPEMD160" +#define LN_ripemd160 "ripemd160" +#define NID_ripemd160 117 +#define OBJ_ripemd160 1L, 3L, 36L, 3L, 2L, 1L + +#define SN_ripemd160WithRSA "RSA-RIPEMD160" +#define LN_ripemd160WithRSA "ripemd160WithRSA" +#define NID_ripemd160WithRSA 119 +#define OBJ_ripemd160WithRSA 1L, 3L, 36L, 3L, 3L, 1L, 2L + +#define SN_rc5_cbc "RC5-CBC" +#define LN_rc5_cbc "rc5-cbc" +#define NID_rc5_cbc 120 +#define OBJ_rc5_cbc 1L, 2L, 840L, 113549L, 3L, 8L + +#define SN_rc5_ecb "RC5-ECB" +#define LN_rc5_ecb "rc5-ecb" +#define NID_rc5_ecb 121 + +#define SN_rc5_cfb64 "RC5-CFB" +#define LN_rc5_cfb64 "rc5-cfb" +#define NID_rc5_cfb64 122 + +#define SN_rc5_ofb64 "RC5-OFB" +#define LN_rc5_ofb64 "rc5-ofb" +#define NID_rc5_ofb64 123 + +#define SN_zlib_compression "ZLIB" +#define LN_zlib_compression "zlib compression" +#define NID_zlib_compression 125 +#define OBJ_zlib_compression 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 8L + +#define SN_ext_key_usage "extendedKeyUsage" +#define LN_ext_key_usage "X509v3 Extended Key Usage" +#define NID_ext_key_usage 126 +#define OBJ_ext_key_usage 2L, 5L, 29L, 37L + +#define SN_id_pkix "PKIX" +#define NID_id_pkix 127 +#define OBJ_id_pkix 1L, 3L, 6L, 1L, 5L, 5L, 7L + +#define SN_id_kp "id-kp" +#define NID_id_kp 128 +#define OBJ_id_kp 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L + +#define SN_server_auth "serverAuth" +#define LN_server_auth "TLS Web Server Authentication" +#define NID_server_auth 129 +#define OBJ_server_auth 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 1L + +#define SN_client_auth "clientAuth" +#define LN_client_auth "TLS Web Client Authentication" +#define NID_client_auth 130 +#define OBJ_client_auth 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 2L + +#define SN_code_sign "codeSigning" +#define LN_code_sign "Code Signing" +#define NID_code_sign 131 +#define OBJ_code_sign 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 3L + +#define SN_email_protect "emailProtection" +#define LN_email_protect "E-mail Protection" +#define NID_email_protect 132 +#define OBJ_email_protect 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 4L + +#define SN_time_stamp "timeStamping" +#define LN_time_stamp "Time Stamping" +#define NID_time_stamp 133 +#define OBJ_time_stamp 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 8L + +#define SN_ms_code_ind "msCodeInd" +#define LN_ms_code_ind "Microsoft Individual Code Signing" +#define NID_ms_code_ind 134 +#define OBJ_ms_code_ind 1L, 3L, 6L, 1L, 4L, 1L, 311L, 2L, 1L, 21L + +#define SN_ms_code_com "msCodeCom" +#define LN_ms_code_com "Microsoft Commercial Code Signing" +#define NID_ms_code_com 135 +#define OBJ_ms_code_com 1L, 3L, 6L, 1L, 4L, 1L, 311L, 2L, 1L, 22L + +#define SN_ms_ctl_sign "msCTLSign" +#define LN_ms_ctl_sign "Microsoft Trust List Signing" +#define NID_ms_ctl_sign 136 +#define OBJ_ms_ctl_sign 1L, 3L, 6L, 1L, 4L, 1L, 311L, 10L, 3L, 1L + +#define SN_ms_sgc "msSGC" +#define LN_ms_sgc "Microsoft Server Gated Crypto" +#define NID_ms_sgc 137 +#define OBJ_ms_sgc 1L, 3L, 6L, 1L, 4L, 1L, 311L, 10L, 3L, 3L + +#define SN_ms_efs "msEFS" +#define LN_ms_efs "Microsoft Encrypted File System" +#define NID_ms_efs 138 +#define OBJ_ms_efs 1L, 3L, 6L, 1L, 4L, 1L, 311L, 10L, 3L, 4L + +#define SN_ns_sgc "nsSGC" +#define LN_ns_sgc "Netscape Server Gated Crypto" +#define NID_ns_sgc 139 +#define OBJ_ns_sgc 2L, 16L, 840L, 1L, 113730L, 4L, 1L + +#define SN_delta_crl "deltaCRL" +#define LN_delta_crl "X509v3 Delta CRL Indicator" +#define NID_delta_crl 140 +#define OBJ_delta_crl 2L, 5L, 29L, 27L + +#define SN_crl_reason "CRLReason" +#define LN_crl_reason "X509v3 CRL Reason Code" +#define NID_crl_reason 141 +#define OBJ_crl_reason 2L, 5L, 29L, 21L + +#define SN_invalidity_date "invalidityDate" +#define LN_invalidity_date "Invalidity Date" +#define NID_invalidity_date 142 +#define OBJ_invalidity_date 2L, 5L, 29L, 24L + +#define SN_sxnet "SXNetID" +#define LN_sxnet "Strong Extranet ID" +#define NID_sxnet 143 +#define OBJ_sxnet 1L, 3L, 101L, 1L, 4L, 1L + +#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128" +#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4" +#define NID_pbe_WithSHA1And128BitRC4 144 +#define OBJ_pbe_WithSHA1And128BitRC4 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 1L + +#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40" +#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4" +#define NID_pbe_WithSHA1And40BitRC4 145 +#define OBJ_pbe_WithSHA1And40BitRC4 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 2L + +#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES" +#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146 +#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC \ + 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 3L + +#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES" +#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147 +#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC \ + 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 4L + +#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128" +#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC" +#define NID_pbe_WithSHA1And128BitRC2_CBC 148 +#define OBJ_pbe_WithSHA1And128BitRC2_CBC 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 5L + +#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40" +#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC" +#define NID_pbe_WithSHA1And40BitRC2_CBC 149 +#define OBJ_pbe_WithSHA1And40BitRC2_CBC 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 6L + +#define LN_keyBag "keyBag" +#define NID_keyBag 150 +#define OBJ_keyBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 1L + +#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag" +#define NID_pkcs8ShroudedKeyBag 151 +#define OBJ_pkcs8ShroudedKeyBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 2L + +#define LN_certBag "certBag" +#define NID_certBag 152 +#define OBJ_certBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 3L + +#define LN_crlBag "crlBag" +#define NID_crlBag 153 +#define OBJ_crlBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 4L + +#define LN_secretBag "secretBag" +#define NID_secretBag 154 +#define OBJ_secretBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 5L + +#define LN_safeContentsBag "safeContentsBag" +#define NID_safeContentsBag 155 +#define OBJ_safeContentsBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 6L + +#define LN_friendlyName "friendlyName" +#define NID_friendlyName 156 +#define OBJ_friendlyName 1L, 2L, 840L, 113549L, 1L, 9L, 20L + +#define LN_localKeyID "localKeyID" +#define NID_localKeyID 157 +#define OBJ_localKeyID 1L, 2L, 840L, 113549L, 1L, 9L, 21L + +#define LN_x509Certificate "x509Certificate" +#define NID_x509Certificate 158 +#define OBJ_x509Certificate 1L, 2L, 840L, 113549L, 1L, 9L, 22L, 1L + +#define LN_sdsiCertificate "sdsiCertificate" +#define NID_sdsiCertificate 159 +#define OBJ_sdsiCertificate 1L, 2L, 840L, 113549L, 1L, 9L, 22L, 2L + +#define LN_x509Crl "x509Crl" +#define NID_x509Crl 160 +#define OBJ_x509Crl 1L, 2L, 840L, 113549L, 1L, 9L, 23L, 1L + +#define LN_pbes2 "PBES2" +#define NID_pbes2 161 +#define OBJ_pbes2 1L, 2L, 840L, 113549L, 1L, 5L, 13L + +#define LN_pbmac1 "PBMAC1" +#define NID_pbmac1 162 +#define OBJ_pbmac1 1L, 2L, 840L, 113549L, 1L, 5L, 14L + +#define LN_hmacWithSHA1 "hmacWithSHA1" +#define NID_hmacWithSHA1 163 +#define OBJ_hmacWithSHA1 1L, 2L, 840L, 113549L, 2L, 7L + +#define SN_id_qt_cps "id-qt-cps" +#define LN_id_qt_cps "Policy Qualifier CPS" +#define NID_id_qt_cps 164 +#define OBJ_id_qt_cps 1L, 3L, 6L, 1L, 5L, 5L, 7L, 2L, 1L + +#define SN_id_qt_unotice "id-qt-unotice" +#define LN_id_qt_unotice "Policy Qualifier User Notice" +#define NID_id_qt_unotice 165 +#define OBJ_id_qt_unotice 1L, 3L, 6L, 1L, 5L, 5L, 7L, 2L, 2L + +#define SN_rc2_64_cbc "RC2-64-CBC" +#define LN_rc2_64_cbc "rc2-64-cbc" +#define NID_rc2_64_cbc 166 + +#define SN_SMIMECapabilities "SMIME-CAPS" +#define LN_SMIMECapabilities "S/MIME Capabilities" +#define NID_SMIMECapabilities 167 +#define OBJ_SMIMECapabilities 1L, 2L, 840L, 113549L, 1L, 9L, 15L + +#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64" +#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC" +#define NID_pbeWithMD2AndRC2_CBC 168 +#define OBJ_pbeWithMD2AndRC2_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 4L + +#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64" +#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC" +#define NID_pbeWithMD5AndRC2_CBC 169 +#define OBJ_pbeWithMD5AndRC2_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 6L + +#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES" +#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC" +#define NID_pbeWithSHA1AndDES_CBC 170 +#define OBJ_pbeWithSHA1AndDES_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 10L + +#define SN_ms_ext_req "msExtReq" +#define LN_ms_ext_req "Microsoft Extension Request" +#define NID_ms_ext_req 171 +#define OBJ_ms_ext_req 1L, 3L, 6L, 1L, 4L, 1L, 311L, 2L, 1L, 14L + +#define SN_ext_req "extReq" +#define LN_ext_req "Extension Request" +#define NID_ext_req 172 +#define OBJ_ext_req 1L, 2L, 840L, 113549L, 1L, 9L, 14L + +#define SN_name "name" +#define LN_name "name" +#define NID_name 173 +#define OBJ_name 2L, 5L, 4L, 41L + +#define SN_dnQualifier "dnQualifier" +#define LN_dnQualifier "dnQualifier" +#define NID_dnQualifier 174 +#define OBJ_dnQualifier 2L, 5L, 4L, 46L + +#define SN_id_pe "id-pe" +#define NID_id_pe 175 +#define OBJ_id_pe 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L + +#define SN_id_ad "id-ad" +#define NID_id_ad 176 +#define OBJ_id_ad 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L + +#define SN_info_access "authorityInfoAccess" +#define LN_info_access "Authority Information Access" +#define NID_info_access 177 +#define OBJ_info_access 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 1L + +#define SN_ad_OCSP "OCSP" +#define LN_ad_OCSP "OCSP" +#define NID_ad_OCSP 178 +#define OBJ_ad_OCSP 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L + +#define SN_ad_ca_issuers "caIssuers" +#define LN_ad_ca_issuers "CA Issuers" +#define NID_ad_ca_issuers 179 +#define OBJ_ad_ca_issuers 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 2L + +#define SN_OCSP_sign "OCSPSigning" +#define LN_OCSP_sign "OCSP Signing" +#define NID_OCSP_sign 180 +#define OBJ_OCSP_sign 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 9L + +#define SN_iso "ISO" +#define LN_iso "iso" +#define NID_iso 181 +#define OBJ_iso 1L + +#define SN_member_body "member-body" +#define LN_member_body "ISO Member Body" +#define NID_member_body 182 +#define OBJ_member_body 1L, 2L + +#define SN_ISO_US "ISO-US" +#define LN_ISO_US "ISO US Member Body" +#define NID_ISO_US 183 +#define OBJ_ISO_US 1L, 2L, 840L + +#define SN_X9_57 "X9-57" +#define LN_X9_57 "X9.57" +#define NID_X9_57 184 +#define OBJ_X9_57 1L, 2L, 840L, 10040L + +#define SN_X9cm "X9cm" +#define LN_X9cm "X9.57 CM ?" +#define NID_X9cm 185 +#define OBJ_X9cm 1L, 2L, 840L, 10040L, 4L + +#define SN_pkcs1 "pkcs1" +#define NID_pkcs1 186 +#define OBJ_pkcs1 1L, 2L, 840L, 113549L, 1L, 1L + +#define SN_pkcs5 "pkcs5" +#define NID_pkcs5 187 +#define OBJ_pkcs5 1L, 2L, 840L, 113549L, 1L, 5L + +#define SN_SMIME "SMIME" +#define LN_SMIME "S/MIME" +#define NID_SMIME 188 +#define OBJ_SMIME 1L, 2L, 840L, 113549L, 1L, 9L, 16L + +#define SN_id_smime_mod "id-smime-mod" +#define NID_id_smime_mod 189 +#define OBJ_id_smime_mod 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L + +#define SN_id_smime_ct "id-smime-ct" +#define NID_id_smime_ct 190 +#define OBJ_id_smime_ct 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L + +#define SN_id_smime_aa "id-smime-aa" +#define NID_id_smime_aa 191 +#define OBJ_id_smime_aa 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L + +#define SN_id_smime_alg "id-smime-alg" +#define NID_id_smime_alg 192 +#define OBJ_id_smime_alg 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L + +#define SN_id_smime_cd "id-smime-cd" +#define NID_id_smime_cd 193 +#define OBJ_id_smime_cd 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 4L + +#define SN_id_smime_spq "id-smime-spq" +#define NID_id_smime_spq 194 +#define OBJ_id_smime_spq 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 5L + +#define SN_id_smime_cti "id-smime-cti" +#define NID_id_smime_cti 195 +#define OBJ_id_smime_cti 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L + +#define SN_id_smime_mod_cms "id-smime-mod-cms" +#define NID_id_smime_mod_cms 196 +#define OBJ_id_smime_mod_cms 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 1L + +#define SN_id_smime_mod_ess "id-smime-mod-ess" +#define NID_id_smime_mod_ess 197 +#define OBJ_id_smime_mod_ess 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 2L + +#define SN_id_smime_mod_oid "id-smime-mod-oid" +#define NID_id_smime_mod_oid 198 +#define OBJ_id_smime_mod_oid 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 3L + +#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3" +#define NID_id_smime_mod_msg_v3 199 +#define OBJ_id_smime_mod_msg_v3 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 4L + +#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88" +#define NID_id_smime_mod_ets_eSignature_88 200 +#define OBJ_id_smime_mod_ets_eSignature_88 \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 5L + +#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97" +#define NID_id_smime_mod_ets_eSignature_97 201 +#define OBJ_id_smime_mod_ets_eSignature_97 \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 6L + +#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88" +#define NID_id_smime_mod_ets_eSigPolicy_88 202 +#define OBJ_id_smime_mod_ets_eSigPolicy_88 \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 7L + +#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97" +#define NID_id_smime_mod_ets_eSigPolicy_97 203 +#define OBJ_id_smime_mod_ets_eSigPolicy_97 \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 8L + +#define SN_id_smime_ct_receipt "id-smime-ct-receipt" +#define NID_id_smime_ct_receipt 204 +#define OBJ_id_smime_ct_receipt 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 1L + +#define SN_id_smime_ct_authData "id-smime-ct-authData" +#define NID_id_smime_ct_authData 205 +#define OBJ_id_smime_ct_authData 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 2L + +#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert" +#define NID_id_smime_ct_publishCert 206 +#define OBJ_id_smime_ct_publishCert 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 3L + +#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo" +#define NID_id_smime_ct_TSTInfo 207 +#define OBJ_id_smime_ct_TSTInfo 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 4L + +#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo" +#define NID_id_smime_ct_TDTInfo 208 +#define OBJ_id_smime_ct_TDTInfo 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 5L + +#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo" +#define NID_id_smime_ct_contentInfo 209 +#define OBJ_id_smime_ct_contentInfo 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 6L + +#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData" +#define NID_id_smime_ct_DVCSRequestData 210 +#define OBJ_id_smime_ct_DVCSRequestData \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 7L + +#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData" +#define NID_id_smime_ct_DVCSResponseData 211 +#define OBJ_id_smime_ct_DVCSResponseData \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 8L + +#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest" +#define NID_id_smime_aa_receiptRequest 212 +#define OBJ_id_smime_aa_receiptRequest \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 1L + +#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel" +#define NID_id_smime_aa_securityLabel 213 +#define OBJ_id_smime_aa_securityLabel 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 2L + +#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory" +#define NID_id_smime_aa_mlExpandHistory 214 +#define OBJ_id_smime_aa_mlExpandHistory \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 3L + +#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint" +#define NID_id_smime_aa_contentHint 215 +#define OBJ_id_smime_aa_contentHint 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 4L + +#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest" +#define NID_id_smime_aa_msgSigDigest 216 +#define OBJ_id_smime_aa_msgSigDigest 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 5L + +#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType" +#define NID_id_smime_aa_encapContentType 217 +#define OBJ_id_smime_aa_encapContentType \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 6L + +#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier" +#define NID_id_smime_aa_contentIdentifier 218 +#define OBJ_id_smime_aa_contentIdentifier \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 7L + +#define SN_id_smime_aa_macValue "id-smime-aa-macValue" +#define NID_id_smime_aa_macValue 219 +#define OBJ_id_smime_aa_macValue 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 8L + +#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels" +#define NID_id_smime_aa_equivalentLabels 220 +#define OBJ_id_smime_aa_equivalentLabels \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 9L + +#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference" +#define NID_id_smime_aa_contentReference 221 +#define OBJ_id_smime_aa_contentReference \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 10L + +#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref" +#define NID_id_smime_aa_encrypKeyPref 222 +#define OBJ_id_smime_aa_encrypKeyPref \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 11L + +#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate" +#define NID_id_smime_aa_signingCertificate 223 +#define OBJ_id_smime_aa_signingCertificate \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 12L + +#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts" +#define NID_id_smime_aa_smimeEncryptCerts 224 +#define OBJ_id_smime_aa_smimeEncryptCerts \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 13L + +#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken" +#define NID_id_smime_aa_timeStampToken 225 +#define OBJ_id_smime_aa_timeStampToken \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 14L + +#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId" +#define NID_id_smime_aa_ets_sigPolicyId 226 +#define OBJ_id_smime_aa_ets_sigPolicyId \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 15L + +#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType" +#define NID_id_smime_aa_ets_commitmentType 227 +#define OBJ_id_smime_aa_ets_commitmentType \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 16L + +#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation" +#define NID_id_smime_aa_ets_signerLocation 228 +#define OBJ_id_smime_aa_ets_signerLocation \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 17L + +#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr" +#define NID_id_smime_aa_ets_signerAttr 229 +#define OBJ_id_smime_aa_ets_signerAttr \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 18L + +#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert" +#define NID_id_smime_aa_ets_otherSigCert 230 +#define OBJ_id_smime_aa_ets_otherSigCert \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 19L + +#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp" +#define NID_id_smime_aa_ets_contentTimestamp 231 +#define OBJ_id_smime_aa_ets_contentTimestamp \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 20L + +#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs" +#define NID_id_smime_aa_ets_CertificateRefs 232 +#define OBJ_id_smime_aa_ets_CertificateRefs \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 21L + +#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs" +#define NID_id_smime_aa_ets_RevocationRefs 233 +#define OBJ_id_smime_aa_ets_RevocationRefs \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 22L + +#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues" +#define NID_id_smime_aa_ets_certValues 234 +#define OBJ_id_smime_aa_ets_certValues \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 23L + +#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues" +#define NID_id_smime_aa_ets_revocationValues 235 +#define OBJ_id_smime_aa_ets_revocationValues \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 24L + +#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp" +#define NID_id_smime_aa_ets_escTimeStamp 236 +#define OBJ_id_smime_aa_ets_escTimeStamp \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 25L + +#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp" +#define NID_id_smime_aa_ets_certCRLTimestamp 237 +#define OBJ_id_smime_aa_ets_certCRLTimestamp \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 26L + +#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp" +#define NID_id_smime_aa_ets_archiveTimeStamp 238 +#define OBJ_id_smime_aa_ets_archiveTimeStamp \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 27L + +#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType" +#define NID_id_smime_aa_signatureType 239 +#define OBJ_id_smime_aa_signatureType \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 28L + +#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc" +#define NID_id_smime_aa_dvcs_dvc 240 +#define OBJ_id_smime_aa_dvcs_dvc 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 29L + +#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES" +#define NID_id_smime_alg_ESDHwith3DES 241 +#define OBJ_id_smime_alg_ESDHwith3DES 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 1L + +#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2" +#define NID_id_smime_alg_ESDHwithRC2 242 +#define OBJ_id_smime_alg_ESDHwithRC2 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 2L + +#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap" +#define NID_id_smime_alg_3DESwrap 243 +#define OBJ_id_smime_alg_3DESwrap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 3L + +#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap" +#define NID_id_smime_alg_RC2wrap 244 +#define OBJ_id_smime_alg_RC2wrap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 4L + +#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH" +#define NID_id_smime_alg_ESDH 245 +#define OBJ_id_smime_alg_ESDH 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 5L + +#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap" +#define NID_id_smime_alg_CMS3DESwrap 246 +#define OBJ_id_smime_alg_CMS3DESwrap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 6L + +#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap" +#define NID_id_smime_alg_CMSRC2wrap 247 +#define OBJ_id_smime_alg_CMSRC2wrap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 7L + +#define SN_id_smime_cd_ldap "id-smime-cd-ldap" +#define NID_id_smime_cd_ldap 248 +#define OBJ_id_smime_cd_ldap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 4L, 1L + +#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri" +#define NID_id_smime_spq_ets_sqt_uri 249 +#define OBJ_id_smime_spq_ets_sqt_uri 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 5L, 1L + +#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice" +#define NID_id_smime_spq_ets_sqt_unotice 250 +#define OBJ_id_smime_spq_ets_sqt_unotice \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 5L, 2L + +#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin" +#define NID_id_smime_cti_ets_proofOfOrigin 251 +#define OBJ_id_smime_cti_ets_proofOfOrigin \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 1L + +#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt" +#define NID_id_smime_cti_ets_proofOfReceipt 252 +#define OBJ_id_smime_cti_ets_proofOfReceipt \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 2L + +#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery" +#define NID_id_smime_cti_ets_proofOfDelivery 253 +#define OBJ_id_smime_cti_ets_proofOfDelivery \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 3L + +#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender" +#define NID_id_smime_cti_ets_proofOfSender 254 +#define OBJ_id_smime_cti_ets_proofOfSender \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 4L + +#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval" +#define NID_id_smime_cti_ets_proofOfApproval 255 +#define OBJ_id_smime_cti_ets_proofOfApproval \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 5L + +#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation" +#define NID_id_smime_cti_ets_proofOfCreation 256 +#define OBJ_id_smime_cti_ets_proofOfCreation \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 6L + +#define SN_md4 "MD4" +#define LN_md4 "md4" +#define NID_md4 257 +#define OBJ_md4 1L, 2L, 840L, 113549L, 2L, 4L + +#define SN_id_pkix_mod "id-pkix-mod" +#define NID_id_pkix_mod 258 +#define OBJ_id_pkix_mod 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L + +#define SN_id_qt "id-qt" +#define NID_id_qt 259 +#define OBJ_id_qt 1L, 3L, 6L, 1L, 5L, 5L, 7L, 2L + +#define SN_id_it "id-it" +#define NID_id_it 260 +#define OBJ_id_it 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L + +#define SN_id_pkip "id-pkip" +#define NID_id_pkip 261 +#define OBJ_id_pkip 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L + +#define SN_id_alg "id-alg" +#define NID_id_alg 262 +#define OBJ_id_alg 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L + +#define SN_id_cmc "id-cmc" +#define NID_id_cmc 263 +#define OBJ_id_cmc 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L + +#define SN_id_on "id-on" +#define NID_id_on 264 +#define OBJ_id_on 1L, 3L, 6L, 1L, 5L, 5L, 7L, 8L + +#define SN_id_pda "id-pda" +#define NID_id_pda 265 +#define OBJ_id_pda 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L + +#define SN_id_aca "id-aca" +#define NID_id_aca 266 +#define OBJ_id_aca 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L + +#define SN_id_qcs "id-qcs" +#define NID_id_qcs 267 +#define OBJ_id_qcs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 11L + +#define SN_id_cct "id-cct" +#define NID_id_cct 268 +#define OBJ_id_cct 1L, 3L, 6L, 1L, 5L, 5L, 7L, 12L + +#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88" +#define NID_id_pkix1_explicit_88 269 +#define OBJ_id_pkix1_explicit_88 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 1L + +#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88" +#define NID_id_pkix1_implicit_88 270 +#define OBJ_id_pkix1_implicit_88 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 2L + +#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93" +#define NID_id_pkix1_explicit_93 271 +#define OBJ_id_pkix1_explicit_93 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 3L + +#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93" +#define NID_id_pkix1_implicit_93 272 +#define OBJ_id_pkix1_implicit_93 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 4L + +#define SN_id_mod_crmf "id-mod-crmf" +#define NID_id_mod_crmf 273 +#define OBJ_id_mod_crmf 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 5L + +#define SN_id_mod_cmc "id-mod-cmc" +#define NID_id_mod_cmc 274 +#define OBJ_id_mod_cmc 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 6L + +#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88" +#define NID_id_mod_kea_profile_88 275 +#define OBJ_id_mod_kea_profile_88 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 7L + +#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93" +#define NID_id_mod_kea_profile_93 276 +#define OBJ_id_mod_kea_profile_93 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 8L + +#define SN_id_mod_cmp "id-mod-cmp" +#define NID_id_mod_cmp 277 +#define OBJ_id_mod_cmp 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 9L + +#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88" +#define NID_id_mod_qualified_cert_88 278 +#define OBJ_id_mod_qualified_cert_88 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 10L + +#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93" +#define NID_id_mod_qualified_cert_93 279 +#define OBJ_id_mod_qualified_cert_93 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 11L + +#define SN_id_mod_attribute_cert "id-mod-attribute-cert" +#define NID_id_mod_attribute_cert 280 +#define OBJ_id_mod_attribute_cert 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 12L + +#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol" +#define NID_id_mod_timestamp_protocol 281 +#define OBJ_id_mod_timestamp_protocol 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 13L + +#define SN_id_mod_ocsp "id-mod-ocsp" +#define NID_id_mod_ocsp 282 +#define OBJ_id_mod_ocsp 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 14L + +#define SN_id_mod_dvcs "id-mod-dvcs" +#define NID_id_mod_dvcs 283 +#define OBJ_id_mod_dvcs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 15L + +#define SN_id_mod_cmp2000 "id-mod-cmp2000" +#define NID_id_mod_cmp2000 284 +#define OBJ_id_mod_cmp2000 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 16L + +#define SN_biometricInfo "biometricInfo" +#define LN_biometricInfo "Biometric Info" +#define NID_biometricInfo 285 +#define OBJ_biometricInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 2L + +#define SN_qcStatements "qcStatements" +#define NID_qcStatements 286 +#define OBJ_qcStatements 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 3L + +#define SN_ac_auditEntity "ac-auditEntity" +#define NID_ac_auditEntity 287 +#define OBJ_ac_auditEntity 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 4L + +#define SN_ac_targeting "ac-targeting" +#define NID_ac_targeting 288 +#define OBJ_ac_targeting 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 5L + +#define SN_aaControls "aaControls" +#define NID_aaControls 289 +#define OBJ_aaControls 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 6L + +#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock" +#define NID_sbgp_ipAddrBlock 290 +#define OBJ_sbgp_ipAddrBlock 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 7L + +#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum" +#define NID_sbgp_autonomousSysNum 291 +#define OBJ_sbgp_autonomousSysNum 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 8L + +#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier" +#define NID_sbgp_routerIdentifier 292 +#define OBJ_sbgp_routerIdentifier 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 9L + +#define SN_textNotice "textNotice" +#define NID_textNotice 293 +#define OBJ_textNotice 1L, 3L, 6L, 1L, 5L, 5L, 7L, 2L, 3L + +#define SN_ipsecEndSystem "ipsecEndSystem" +#define LN_ipsecEndSystem "IPSec End System" +#define NID_ipsecEndSystem 294 +#define OBJ_ipsecEndSystem 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 5L + +#define SN_ipsecTunnel "ipsecTunnel" +#define LN_ipsecTunnel "IPSec Tunnel" +#define NID_ipsecTunnel 295 +#define OBJ_ipsecTunnel 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 6L + +#define SN_ipsecUser "ipsecUser" +#define LN_ipsecUser "IPSec User" +#define NID_ipsecUser 296 +#define OBJ_ipsecUser 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 7L + +#define SN_dvcs "DVCS" +#define LN_dvcs "dvcs" +#define NID_dvcs 297 +#define OBJ_dvcs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 10L + +#define SN_id_it_caProtEncCert "id-it-caProtEncCert" +#define NID_id_it_caProtEncCert 298 +#define OBJ_id_it_caProtEncCert 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 1L + +#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes" +#define NID_id_it_signKeyPairTypes 299 +#define OBJ_id_it_signKeyPairTypes 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 2L + +#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes" +#define NID_id_it_encKeyPairTypes 300 +#define OBJ_id_it_encKeyPairTypes 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 3L + +#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg" +#define NID_id_it_preferredSymmAlg 301 +#define OBJ_id_it_preferredSymmAlg 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 4L + +#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo" +#define NID_id_it_caKeyUpdateInfo 302 +#define OBJ_id_it_caKeyUpdateInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 5L + +#define SN_id_it_currentCRL "id-it-currentCRL" +#define NID_id_it_currentCRL 303 +#define OBJ_id_it_currentCRL 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 6L + +#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs" +#define NID_id_it_unsupportedOIDs 304 +#define OBJ_id_it_unsupportedOIDs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 7L + +#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest" +#define NID_id_it_subscriptionRequest 305 +#define OBJ_id_it_subscriptionRequest 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 8L + +#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse" +#define NID_id_it_subscriptionResponse 306 +#define OBJ_id_it_subscriptionResponse 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 9L + +#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq" +#define NID_id_it_keyPairParamReq 307 +#define OBJ_id_it_keyPairParamReq 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 10L + +#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep" +#define NID_id_it_keyPairParamRep 308 +#define OBJ_id_it_keyPairParamRep 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 11L + +#define SN_id_it_revPassphrase "id-it-revPassphrase" +#define NID_id_it_revPassphrase 309 +#define OBJ_id_it_revPassphrase 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 12L + +#define SN_id_it_implicitConfirm "id-it-implicitConfirm" +#define NID_id_it_implicitConfirm 310 +#define OBJ_id_it_implicitConfirm 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 13L + +#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime" +#define NID_id_it_confirmWaitTime 311 +#define OBJ_id_it_confirmWaitTime 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 14L + +#define SN_id_it_origPKIMessage "id-it-origPKIMessage" +#define NID_id_it_origPKIMessage 312 +#define OBJ_id_it_origPKIMessage 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 15L + +#define SN_id_regCtrl "id-regCtrl" +#define NID_id_regCtrl 313 +#define OBJ_id_regCtrl 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L + +#define SN_id_regInfo "id-regInfo" +#define NID_id_regInfo 314 +#define OBJ_id_regInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 2L + +#define SN_id_regCtrl_regToken "id-regCtrl-regToken" +#define NID_id_regCtrl_regToken 315 +#define OBJ_id_regCtrl_regToken 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 1L + +#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator" +#define NID_id_regCtrl_authenticator 316 +#define OBJ_id_regCtrl_authenticator 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 2L + +#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo" +#define NID_id_regCtrl_pkiPublicationInfo 317 +#define OBJ_id_regCtrl_pkiPublicationInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 3L + +#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions" +#define NID_id_regCtrl_pkiArchiveOptions 318 +#define OBJ_id_regCtrl_pkiArchiveOptions 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 4L + +#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID" +#define NID_id_regCtrl_oldCertID 319 +#define OBJ_id_regCtrl_oldCertID 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 5L + +#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey" +#define NID_id_regCtrl_protocolEncrKey 320 +#define OBJ_id_regCtrl_protocolEncrKey 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 6L + +#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs" +#define NID_id_regInfo_utf8Pairs 321 +#define OBJ_id_regInfo_utf8Pairs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 2L, 1L + +#define SN_id_regInfo_certReq "id-regInfo-certReq" +#define NID_id_regInfo_certReq 322 +#define OBJ_id_regInfo_certReq 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 2L, 2L + +#define SN_id_alg_des40 "id-alg-des40" +#define NID_id_alg_des40 323 +#define OBJ_id_alg_des40 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 1L + +#define SN_id_alg_noSignature "id-alg-noSignature" +#define NID_id_alg_noSignature 324 +#define OBJ_id_alg_noSignature 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 2L + +#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1" +#define NID_id_alg_dh_sig_hmac_sha1 325 +#define OBJ_id_alg_dh_sig_hmac_sha1 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 3L + +#define SN_id_alg_dh_pop "id-alg-dh-pop" +#define NID_id_alg_dh_pop 326 +#define OBJ_id_alg_dh_pop 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 4L + +#define SN_id_cmc_statusInfo "id-cmc-statusInfo" +#define NID_id_cmc_statusInfo 327 +#define OBJ_id_cmc_statusInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 1L + +#define SN_id_cmc_identification "id-cmc-identification" +#define NID_id_cmc_identification 328 +#define OBJ_id_cmc_identification 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 2L + +#define SN_id_cmc_identityProof "id-cmc-identityProof" +#define NID_id_cmc_identityProof 329 +#define OBJ_id_cmc_identityProof 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 3L + +#define SN_id_cmc_dataReturn "id-cmc-dataReturn" +#define NID_id_cmc_dataReturn 330 +#define OBJ_id_cmc_dataReturn 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 4L + +#define SN_id_cmc_transactionId "id-cmc-transactionId" +#define NID_id_cmc_transactionId 331 +#define OBJ_id_cmc_transactionId 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 5L + +#define SN_id_cmc_senderNonce "id-cmc-senderNonce" +#define NID_id_cmc_senderNonce 332 +#define OBJ_id_cmc_senderNonce 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 6L + +#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce" +#define NID_id_cmc_recipientNonce 333 +#define OBJ_id_cmc_recipientNonce 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 7L + +#define SN_id_cmc_addExtensions "id-cmc-addExtensions" +#define NID_id_cmc_addExtensions 334 +#define OBJ_id_cmc_addExtensions 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 8L + +#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP" +#define NID_id_cmc_encryptedPOP 335 +#define OBJ_id_cmc_encryptedPOP 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 9L + +#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP" +#define NID_id_cmc_decryptedPOP 336 +#define OBJ_id_cmc_decryptedPOP 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 10L + +#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness" +#define NID_id_cmc_lraPOPWitness 337 +#define OBJ_id_cmc_lraPOPWitness 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 11L + +#define SN_id_cmc_getCert "id-cmc-getCert" +#define NID_id_cmc_getCert 338 +#define OBJ_id_cmc_getCert 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 15L + +#define SN_id_cmc_getCRL "id-cmc-getCRL" +#define NID_id_cmc_getCRL 339 +#define OBJ_id_cmc_getCRL 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 16L + +#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest" +#define NID_id_cmc_revokeRequest 340 +#define OBJ_id_cmc_revokeRequest 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 17L + +#define SN_id_cmc_regInfo "id-cmc-regInfo" +#define NID_id_cmc_regInfo 341 +#define OBJ_id_cmc_regInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 18L + +#define SN_id_cmc_responseInfo "id-cmc-responseInfo" +#define NID_id_cmc_responseInfo 342 +#define OBJ_id_cmc_responseInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 19L + +#define SN_id_cmc_queryPending "id-cmc-queryPending" +#define NID_id_cmc_queryPending 343 +#define OBJ_id_cmc_queryPending 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 21L + +#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom" +#define NID_id_cmc_popLinkRandom 344 +#define OBJ_id_cmc_popLinkRandom 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 22L + +#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness" +#define NID_id_cmc_popLinkWitness 345 +#define OBJ_id_cmc_popLinkWitness 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 23L + +#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance" +#define NID_id_cmc_confirmCertAcceptance 346 +#define OBJ_id_cmc_confirmCertAcceptance 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 24L + +#define SN_id_on_personalData "id-on-personalData" +#define NID_id_on_personalData 347 +#define OBJ_id_on_personalData 1L, 3L, 6L, 1L, 5L, 5L, 7L, 8L, 1L + +#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth" +#define NID_id_pda_dateOfBirth 348 +#define OBJ_id_pda_dateOfBirth 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 1L + +#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth" +#define NID_id_pda_placeOfBirth 349 +#define OBJ_id_pda_placeOfBirth 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 2L + +#define SN_id_pda_gender "id-pda-gender" +#define NID_id_pda_gender 351 +#define OBJ_id_pda_gender 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 3L + +#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship" +#define NID_id_pda_countryOfCitizenship 352 +#define OBJ_id_pda_countryOfCitizenship 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 4L + +#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence" +#define NID_id_pda_countryOfResidence 353 +#define OBJ_id_pda_countryOfResidence 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 5L + +#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo" +#define NID_id_aca_authenticationInfo 354 +#define OBJ_id_aca_authenticationInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 1L + +#define SN_id_aca_accessIdentity "id-aca-accessIdentity" +#define NID_id_aca_accessIdentity 355 +#define OBJ_id_aca_accessIdentity 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 2L + +#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity" +#define NID_id_aca_chargingIdentity 356 +#define OBJ_id_aca_chargingIdentity 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 3L + +#define SN_id_aca_group "id-aca-group" +#define NID_id_aca_group 357 +#define OBJ_id_aca_group 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 4L + +#define SN_id_aca_role "id-aca-role" +#define NID_id_aca_role 358 +#define OBJ_id_aca_role 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 5L + +#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1" +#define NID_id_qcs_pkixQCSyntax_v1 359 +#define OBJ_id_qcs_pkixQCSyntax_v1 1L, 3L, 6L, 1L, 5L, 5L, 7L, 11L, 1L + +#define SN_id_cct_crs "id-cct-crs" +#define NID_id_cct_crs 360 +#define OBJ_id_cct_crs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 12L, 1L + +#define SN_id_cct_PKIData "id-cct-PKIData" +#define NID_id_cct_PKIData 361 +#define OBJ_id_cct_PKIData 1L, 3L, 6L, 1L, 5L, 5L, 7L, 12L, 2L + +#define SN_id_cct_PKIResponse "id-cct-PKIResponse" +#define NID_id_cct_PKIResponse 362 +#define OBJ_id_cct_PKIResponse 1L, 3L, 6L, 1L, 5L, 5L, 7L, 12L, 3L + +#define SN_ad_timeStamping "ad_timestamping" +#define LN_ad_timeStamping "AD Time Stamping" +#define NID_ad_timeStamping 363 +#define OBJ_ad_timeStamping 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 3L + +#define SN_ad_dvcs "AD_DVCS" +#define LN_ad_dvcs "ad dvcs" +#define NID_ad_dvcs 364 +#define OBJ_ad_dvcs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 4L + +#define SN_id_pkix_OCSP_basic "basicOCSPResponse" +#define LN_id_pkix_OCSP_basic "Basic OCSP Response" +#define NID_id_pkix_OCSP_basic 365 +#define OBJ_id_pkix_OCSP_basic 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 1L + +#define SN_id_pkix_OCSP_Nonce "Nonce" +#define LN_id_pkix_OCSP_Nonce "OCSP Nonce" +#define NID_id_pkix_OCSP_Nonce 366 +#define OBJ_id_pkix_OCSP_Nonce 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 2L + +#define SN_id_pkix_OCSP_CrlID "CrlID" +#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID" +#define NID_id_pkix_OCSP_CrlID 367 +#define OBJ_id_pkix_OCSP_CrlID 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 3L + +#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses" +#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses" +#define NID_id_pkix_OCSP_acceptableResponses 368 +#define OBJ_id_pkix_OCSP_acceptableResponses \ + 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 4L + +#define SN_id_pkix_OCSP_noCheck "noCheck" +#define LN_id_pkix_OCSP_noCheck "OCSP No Check" +#define NID_id_pkix_OCSP_noCheck 369 +#define OBJ_id_pkix_OCSP_noCheck 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 5L + +#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff" +#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff" +#define NID_id_pkix_OCSP_archiveCutoff 370 +#define OBJ_id_pkix_OCSP_archiveCutoff 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 6L + +#define SN_id_pkix_OCSP_serviceLocator "serviceLocator" +#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator" +#define NID_id_pkix_OCSP_serviceLocator 371 +#define OBJ_id_pkix_OCSP_serviceLocator 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 7L + +#define SN_id_pkix_OCSP_extendedStatus "extendedStatus" +#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status" +#define NID_id_pkix_OCSP_extendedStatus 372 +#define OBJ_id_pkix_OCSP_extendedStatus 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 8L + +#define SN_id_pkix_OCSP_valid "valid" +#define NID_id_pkix_OCSP_valid 373 +#define OBJ_id_pkix_OCSP_valid 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 9L + +#define SN_id_pkix_OCSP_path "path" +#define NID_id_pkix_OCSP_path 374 +#define OBJ_id_pkix_OCSP_path 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 10L + +#define SN_id_pkix_OCSP_trustRoot "trustRoot" +#define LN_id_pkix_OCSP_trustRoot "Trust Root" +#define NID_id_pkix_OCSP_trustRoot 375 +#define OBJ_id_pkix_OCSP_trustRoot 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 11L + +#define SN_algorithm "algorithm" +#define LN_algorithm "algorithm" +#define NID_algorithm 376 +#define OBJ_algorithm 1L, 3L, 14L, 3L, 2L + +#define SN_rsaSignature "rsaSignature" +#define NID_rsaSignature 377 +#define OBJ_rsaSignature 1L, 3L, 14L, 3L, 2L, 11L + +#define SN_X500algorithms "X500algorithms" +#define LN_X500algorithms "directory services - algorithms" +#define NID_X500algorithms 378 +#define OBJ_X500algorithms 2L, 5L, 8L + +#define SN_org "ORG" +#define LN_org "org" +#define NID_org 379 +#define OBJ_org 1L, 3L + +#define SN_dod "DOD" +#define LN_dod "dod" +#define NID_dod 380 +#define OBJ_dod 1L, 3L, 6L + +#define SN_iana "IANA" +#define LN_iana "iana" +#define NID_iana 381 +#define OBJ_iana 1L, 3L, 6L, 1L + +#define SN_Directory "directory" +#define LN_Directory "Directory" +#define NID_Directory 382 +#define OBJ_Directory 1L, 3L, 6L, 1L, 1L + +#define SN_Management "mgmt" +#define LN_Management "Management" +#define NID_Management 383 +#define OBJ_Management 1L, 3L, 6L, 1L, 2L + +#define SN_Experimental "experimental" +#define LN_Experimental "Experimental" +#define NID_Experimental 384 +#define OBJ_Experimental 1L, 3L, 6L, 1L, 3L + +#define SN_Private "private" +#define LN_Private "Private" +#define NID_Private 385 +#define OBJ_Private 1L, 3L, 6L, 1L, 4L + +#define SN_Security "security" +#define LN_Security "Security" +#define NID_Security 386 +#define OBJ_Security 1L, 3L, 6L, 1L, 5L + +#define SN_SNMPv2 "snmpv2" +#define LN_SNMPv2 "SNMPv2" +#define NID_SNMPv2 387 +#define OBJ_SNMPv2 1L, 3L, 6L, 1L, 6L + +#define LN_Mail "Mail" +#define NID_Mail 388 +#define OBJ_Mail 1L, 3L, 6L, 1L, 7L + +#define SN_Enterprises "enterprises" +#define LN_Enterprises "Enterprises" +#define NID_Enterprises 389 +#define OBJ_Enterprises 1L, 3L, 6L, 1L, 4L, 1L + +#define SN_dcObject "dcobject" +#define LN_dcObject "dcObject" +#define NID_dcObject 390 +#define OBJ_dcObject 1L, 3L, 6L, 1L, 4L, 1L, 1466L, 344L + +#define SN_domainComponent "DC" +#define LN_domainComponent "domainComponent" +#define NID_domainComponent 391 +#define OBJ_domainComponent 0L, 9L, 2342L, 19200300L, 100L, 1L, 25L + +#define SN_Domain "domain" +#define LN_Domain "Domain" +#define NID_Domain 392 +#define OBJ_Domain 0L, 9L, 2342L, 19200300L, 100L, 4L, 13L + +#define SN_selected_attribute_types "selected-attribute-types" +#define LN_selected_attribute_types "Selected Attribute Types" +#define NID_selected_attribute_types 394 +#define OBJ_selected_attribute_types 2L, 5L, 1L, 5L + +#define SN_clearance "clearance" +#define NID_clearance 395 +#define OBJ_clearance 2L, 5L, 1L, 5L, 55L + +#define SN_md4WithRSAEncryption "RSA-MD4" +#define LN_md4WithRSAEncryption "md4WithRSAEncryption" +#define NID_md4WithRSAEncryption 396 +#define OBJ_md4WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 3L + +#define SN_ac_proxying "ac-proxying" +#define NID_ac_proxying 397 +#define OBJ_ac_proxying 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 10L + +#define SN_sinfo_access "subjectInfoAccess" +#define LN_sinfo_access "Subject Information Access" +#define NID_sinfo_access 398 +#define OBJ_sinfo_access 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 11L + +#define SN_id_aca_encAttrs "id-aca-encAttrs" +#define NID_id_aca_encAttrs 399 +#define OBJ_id_aca_encAttrs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 6L + +#define SN_role "role" +#define LN_role "role" +#define NID_role 400 +#define OBJ_role 2L, 5L, 4L, 72L + +#define SN_policy_constraints "policyConstraints" +#define LN_policy_constraints "X509v3 Policy Constraints" +#define NID_policy_constraints 401 +#define OBJ_policy_constraints 2L, 5L, 29L, 36L + +#define SN_target_information "targetInformation" +#define LN_target_information "X509v3 AC Targeting" +#define NID_target_information 402 +#define OBJ_target_information 2L, 5L, 29L, 55L + +#define SN_no_rev_avail "noRevAvail" +#define LN_no_rev_avail "X509v3 No Revocation Available" +#define NID_no_rev_avail 403 +#define OBJ_no_rev_avail 2L, 5L, 29L, 56L + +#define SN_ansi_X9_62 "ansi-X9-62" +#define LN_ansi_X9_62 "ANSI X9.62" +#define NID_ansi_X9_62 405 +#define OBJ_ansi_X9_62 1L, 2L, 840L, 10045L + +#define SN_X9_62_prime_field "prime-field" +#define NID_X9_62_prime_field 406 +#define OBJ_X9_62_prime_field 1L, 2L, 840L, 10045L, 1L, 1L + +#define SN_X9_62_characteristic_two_field "characteristic-two-field" +#define NID_X9_62_characteristic_two_field 407 +#define OBJ_X9_62_characteristic_two_field 1L, 2L, 840L, 10045L, 1L, 2L + +#define SN_X9_62_id_ecPublicKey "id-ecPublicKey" +#define NID_X9_62_id_ecPublicKey 408 +#define OBJ_X9_62_id_ecPublicKey 1L, 2L, 840L, 10045L, 2L, 1L + +#define SN_X9_62_prime192v1 "prime192v1" +#define NID_X9_62_prime192v1 409 +#define OBJ_X9_62_prime192v1 1L, 2L, 840L, 10045L, 3L, 1L, 1L + +#define SN_X9_62_prime192v2 "prime192v2" +#define NID_X9_62_prime192v2 410 +#define OBJ_X9_62_prime192v2 1L, 2L, 840L, 10045L, 3L, 1L, 2L + +#define SN_X9_62_prime192v3 "prime192v3" +#define NID_X9_62_prime192v3 411 +#define OBJ_X9_62_prime192v3 1L, 2L, 840L, 10045L, 3L, 1L, 3L + +#define SN_X9_62_prime239v1 "prime239v1" +#define NID_X9_62_prime239v1 412 +#define OBJ_X9_62_prime239v1 1L, 2L, 840L, 10045L, 3L, 1L, 4L + +#define SN_X9_62_prime239v2 "prime239v2" +#define NID_X9_62_prime239v2 413 +#define OBJ_X9_62_prime239v2 1L, 2L, 840L, 10045L, 3L, 1L, 5L + +#define SN_X9_62_prime239v3 "prime239v3" +#define NID_X9_62_prime239v3 414 +#define OBJ_X9_62_prime239v3 1L, 2L, 840L, 10045L, 3L, 1L, 6L + +#define SN_X9_62_prime256v1 "prime256v1" +#define NID_X9_62_prime256v1 415 +#define OBJ_X9_62_prime256v1 1L, 2L, 840L, 10045L, 3L, 1L, 7L + +#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1" +#define NID_ecdsa_with_SHA1 416 +#define OBJ_ecdsa_with_SHA1 1L, 2L, 840L, 10045L, 4L, 1L + +#define SN_ms_csp_name "CSPName" +#define LN_ms_csp_name "Microsoft CSP Name" +#define NID_ms_csp_name 417 +#define OBJ_ms_csp_name 1L, 3L, 6L, 1L, 4L, 1L, 311L, 17L, 1L + +#define SN_aes_128_ecb "AES-128-ECB" +#define LN_aes_128_ecb "aes-128-ecb" +#define NID_aes_128_ecb 418 +#define OBJ_aes_128_ecb 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 1L + +#define SN_aes_128_cbc "AES-128-CBC" +#define LN_aes_128_cbc "aes-128-cbc" +#define NID_aes_128_cbc 419 +#define OBJ_aes_128_cbc 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 2L + +#define SN_aes_128_ofb128 "AES-128-OFB" +#define LN_aes_128_ofb128 "aes-128-ofb" +#define NID_aes_128_ofb128 420 +#define OBJ_aes_128_ofb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 3L + +#define SN_aes_128_cfb128 "AES-128-CFB" +#define LN_aes_128_cfb128 "aes-128-cfb" +#define NID_aes_128_cfb128 421 +#define OBJ_aes_128_cfb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 4L + +#define SN_aes_192_ecb "AES-192-ECB" +#define LN_aes_192_ecb "aes-192-ecb" +#define NID_aes_192_ecb 422 +#define OBJ_aes_192_ecb 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 21L + +#define SN_aes_192_cbc "AES-192-CBC" +#define LN_aes_192_cbc "aes-192-cbc" +#define NID_aes_192_cbc 423 +#define OBJ_aes_192_cbc 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 22L + +#define SN_aes_192_ofb128 "AES-192-OFB" +#define LN_aes_192_ofb128 "aes-192-ofb" +#define NID_aes_192_ofb128 424 +#define OBJ_aes_192_ofb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 23L + +#define SN_aes_192_cfb128 "AES-192-CFB" +#define LN_aes_192_cfb128 "aes-192-cfb" +#define NID_aes_192_cfb128 425 +#define OBJ_aes_192_cfb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 24L + +#define SN_aes_256_ecb "AES-256-ECB" +#define LN_aes_256_ecb "aes-256-ecb" +#define NID_aes_256_ecb 426 +#define OBJ_aes_256_ecb 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 41L + +#define SN_aes_256_cbc "AES-256-CBC" +#define LN_aes_256_cbc "aes-256-cbc" +#define NID_aes_256_cbc 427 +#define OBJ_aes_256_cbc 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 42L + +#define SN_aes_256_ofb128 "AES-256-OFB" +#define LN_aes_256_ofb128 "aes-256-ofb" +#define NID_aes_256_ofb128 428 +#define OBJ_aes_256_ofb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 43L + +#define SN_aes_256_cfb128 "AES-256-CFB" +#define LN_aes_256_cfb128 "aes-256-cfb" +#define NID_aes_256_cfb128 429 +#define OBJ_aes_256_cfb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 44L + +#define SN_hold_instruction_code "holdInstructionCode" +#define LN_hold_instruction_code "Hold Instruction Code" +#define NID_hold_instruction_code 430 +#define OBJ_hold_instruction_code 2L, 5L, 29L, 23L + +#define SN_hold_instruction_none "holdInstructionNone" +#define LN_hold_instruction_none "Hold Instruction None" +#define NID_hold_instruction_none 431 +#define OBJ_hold_instruction_none 1L, 2L, 840L, 10040L, 2L, 1L + +#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer" +#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer" +#define NID_hold_instruction_call_issuer 432 +#define OBJ_hold_instruction_call_issuer 1L, 2L, 840L, 10040L, 2L, 2L + +#define SN_hold_instruction_reject "holdInstructionReject" +#define LN_hold_instruction_reject "Hold Instruction Reject" +#define NID_hold_instruction_reject 433 +#define OBJ_hold_instruction_reject 1L, 2L, 840L, 10040L, 2L, 3L + +#define SN_data "data" +#define NID_data 434 +#define OBJ_data 0L, 9L + +#define SN_pss "pss" +#define NID_pss 435 +#define OBJ_pss 0L, 9L, 2342L + +#define SN_ucl "ucl" +#define NID_ucl 436 +#define OBJ_ucl 0L, 9L, 2342L, 19200300L + +#define SN_pilot "pilot" +#define NID_pilot 437 +#define OBJ_pilot 0L, 9L, 2342L, 19200300L, 100L + +#define LN_pilotAttributeType "pilotAttributeType" +#define NID_pilotAttributeType 438 +#define OBJ_pilotAttributeType 0L, 9L, 2342L, 19200300L, 100L, 1L + +#define LN_pilotAttributeSyntax "pilotAttributeSyntax" +#define NID_pilotAttributeSyntax 439 +#define OBJ_pilotAttributeSyntax 0L, 9L, 2342L, 19200300L, 100L, 3L + +#define LN_pilotObjectClass "pilotObjectClass" +#define NID_pilotObjectClass 440 +#define OBJ_pilotObjectClass 0L, 9L, 2342L, 19200300L, 100L, 4L + +#define LN_pilotGroups "pilotGroups" +#define NID_pilotGroups 441 +#define OBJ_pilotGroups 0L, 9L, 2342L, 19200300L, 100L, 10L + +#define LN_iA5StringSyntax "iA5StringSyntax" +#define NID_iA5StringSyntax 442 +#define OBJ_iA5StringSyntax 0L, 9L, 2342L, 19200300L, 100L, 3L, 4L + +#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax" +#define NID_caseIgnoreIA5StringSyntax 443 +#define OBJ_caseIgnoreIA5StringSyntax 0L, 9L, 2342L, 19200300L, 100L, 3L, 5L + +#define LN_pilotObject "pilotObject" +#define NID_pilotObject 444 +#define OBJ_pilotObject 0L, 9L, 2342L, 19200300L, 100L, 4L, 3L + +#define LN_pilotPerson "pilotPerson" +#define NID_pilotPerson 445 +#define OBJ_pilotPerson 0L, 9L, 2342L, 19200300L, 100L, 4L, 4L + +#define SN_account "account" +#define NID_account 446 +#define OBJ_account 0L, 9L, 2342L, 19200300L, 100L, 4L, 5L + +#define SN_document "document" +#define NID_document 447 +#define OBJ_document 0L, 9L, 2342L, 19200300L, 100L, 4L, 6L + +#define SN_room "room" +#define NID_room 448 +#define OBJ_room 0L, 9L, 2342L, 19200300L, 100L, 4L, 7L + +#define LN_documentSeries "documentSeries" +#define NID_documentSeries 449 +#define OBJ_documentSeries 0L, 9L, 2342L, 19200300L, 100L, 4L, 9L + +#define LN_rFC822localPart "rFC822localPart" +#define NID_rFC822localPart 450 +#define OBJ_rFC822localPart 0L, 9L, 2342L, 19200300L, 100L, 4L, 14L + +#define LN_dNSDomain "dNSDomain" +#define NID_dNSDomain 451 +#define OBJ_dNSDomain 0L, 9L, 2342L, 19200300L, 100L, 4L, 15L + +#define LN_domainRelatedObject "domainRelatedObject" +#define NID_domainRelatedObject 452 +#define OBJ_domainRelatedObject 0L, 9L, 2342L, 19200300L, 100L, 4L, 17L + +#define LN_friendlyCountry "friendlyCountry" +#define NID_friendlyCountry 453 +#define OBJ_friendlyCountry 0L, 9L, 2342L, 19200300L, 100L, 4L, 18L + +#define LN_simpleSecurityObject "simpleSecurityObject" +#define NID_simpleSecurityObject 454 +#define OBJ_simpleSecurityObject 0L, 9L, 2342L, 19200300L, 100L, 4L, 19L + +#define LN_pilotOrganization "pilotOrganization" +#define NID_pilotOrganization 455 +#define OBJ_pilotOrganization 0L, 9L, 2342L, 19200300L, 100L, 4L, 20L + +#define LN_pilotDSA "pilotDSA" +#define NID_pilotDSA 456 +#define OBJ_pilotDSA 0L, 9L, 2342L, 19200300L, 100L, 4L, 21L + +#define LN_qualityLabelledData "qualityLabelledData" +#define NID_qualityLabelledData 457 +#define OBJ_qualityLabelledData 0L, 9L, 2342L, 19200300L, 100L, 4L, 22L + +#define SN_userId "UID" +#define LN_userId "userId" +#define NID_userId 458 +#define OBJ_userId 0L, 9L, 2342L, 19200300L, 100L, 1L, 1L + +#define LN_textEncodedORAddress "textEncodedORAddress" +#define NID_textEncodedORAddress 459 +#define OBJ_textEncodedORAddress 0L, 9L, 2342L, 19200300L, 100L, 1L, 2L + +#define SN_rfc822Mailbox "mail" +#define LN_rfc822Mailbox "rfc822Mailbox" +#define NID_rfc822Mailbox 460 +#define OBJ_rfc822Mailbox 0L, 9L, 2342L, 19200300L, 100L, 1L, 3L + +#define SN_info "info" +#define NID_info 461 +#define OBJ_info 0L, 9L, 2342L, 19200300L, 100L, 1L, 4L + +#define LN_favouriteDrink "favouriteDrink" +#define NID_favouriteDrink 462 +#define OBJ_favouriteDrink 0L, 9L, 2342L, 19200300L, 100L, 1L, 5L + +#define LN_roomNumber "roomNumber" +#define NID_roomNumber 463 +#define OBJ_roomNumber 0L, 9L, 2342L, 19200300L, 100L, 1L, 6L + +#define SN_photo "photo" +#define NID_photo 464 +#define OBJ_photo 0L, 9L, 2342L, 19200300L, 100L, 1L, 7L + +#define LN_userClass "userClass" +#define NID_userClass 465 +#define OBJ_userClass 0L, 9L, 2342L, 19200300L, 100L, 1L, 8L + +#define SN_host "host" +#define NID_host 466 +#define OBJ_host 0L, 9L, 2342L, 19200300L, 100L, 1L, 9L + +#define SN_manager "manager" +#define NID_manager 467 +#define OBJ_manager 0L, 9L, 2342L, 19200300L, 100L, 1L, 10L + +#define LN_documentIdentifier "documentIdentifier" +#define NID_documentIdentifier 468 +#define OBJ_documentIdentifier 0L, 9L, 2342L, 19200300L, 100L, 1L, 11L + +#define LN_documentTitle "documentTitle" +#define NID_documentTitle 469 +#define OBJ_documentTitle 0L, 9L, 2342L, 19200300L, 100L, 1L, 12L + +#define LN_documentVersion "documentVersion" +#define NID_documentVersion 470 +#define OBJ_documentVersion 0L, 9L, 2342L, 19200300L, 100L, 1L, 13L + +#define LN_documentAuthor "documentAuthor" +#define NID_documentAuthor 471 +#define OBJ_documentAuthor 0L, 9L, 2342L, 19200300L, 100L, 1L, 14L + +#define LN_documentLocation "documentLocation" +#define NID_documentLocation 472 +#define OBJ_documentLocation 0L, 9L, 2342L, 19200300L, 100L, 1L, 15L + +#define LN_homeTelephoneNumber "homeTelephoneNumber" +#define NID_homeTelephoneNumber 473 +#define OBJ_homeTelephoneNumber 0L, 9L, 2342L, 19200300L, 100L, 1L, 20L + +#define SN_secretary "secretary" +#define NID_secretary 474 +#define OBJ_secretary 0L, 9L, 2342L, 19200300L, 100L, 1L, 21L + +#define LN_otherMailbox "otherMailbox" +#define NID_otherMailbox 475 +#define OBJ_otherMailbox 0L, 9L, 2342L, 19200300L, 100L, 1L, 22L + +#define LN_lastModifiedTime "lastModifiedTime" +#define NID_lastModifiedTime 476 +#define OBJ_lastModifiedTime 0L, 9L, 2342L, 19200300L, 100L, 1L, 23L + +#define LN_lastModifiedBy "lastModifiedBy" +#define NID_lastModifiedBy 477 +#define OBJ_lastModifiedBy 0L, 9L, 2342L, 19200300L, 100L, 1L, 24L + +#define LN_aRecord "aRecord" +#define NID_aRecord 478 +#define OBJ_aRecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 26L + +#define LN_pilotAttributeType27 "pilotAttributeType27" +#define NID_pilotAttributeType27 479 +#define OBJ_pilotAttributeType27 0L, 9L, 2342L, 19200300L, 100L, 1L, 27L + +#define LN_mXRecord "mXRecord" +#define NID_mXRecord 480 +#define OBJ_mXRecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 28L + +#define LN_nSRecord "nSRecord" +#define NID_nSRecord 481 +#define OBJ_nSRecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 29L + +#define LN_sOARecord "sOARecord" +#define NID_sOARecord 482 +#define OBJ_sOARecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 30L + +#define LN_cNAMERecord "cNAMERecord" +#define NID_cNAMERecord 483 +#define OBJ_cNAMERecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 31L + +#define LN_associatedDomain "associatedDomain" +#define NID_associatedDomain 484 +#define OBJ_associatedDomain 0L, 9L, 2342L, 19200300L, 100L, 1L, 37L + +#define LN_associatedName "associatedName" +#define NID_associatedName 485 +#define OBJ_associatedName 0L, 9L, 2342L, 19200300L, 100L, 1L, 38L + +#define LN_homePostalAddress "homePostalAddress" +#define NID_homePostalAddress 486 +#define OBJ_homePostalAddress 0L, 9L, 2342L, 19200300L, 100L, 1L, 39L + +#define LN_personalTitle "personalTitle" +#define NID_personalTitle 487 +#define OBJ_personalTitle 0L, 9L, 2342L, 19200300L, 100L, 1L, 40L + +#define LN_mobileTelephoneNumber "mobileTelephoneNumber" +#define NID_mobileTelephoneNumber 488 +#define OBJ_mobileTelephoneNumber 0L, 9L, 2342L, 19200300L, 100L, 1L, 41L + +#define LN_pagerTelephoneNumber "pagerTelephoneNumber" +#define NID_pagerTelephoneNumber 489 +#define OBJ_pagerTelephoneNumber 0L, 9L, 2342L, 19200300L, 100L, 1L, 42L + +#define LN_friendlyCountryName "friendlyCountryName" +#define NID_friendlyCountryName 490 +#define OBJ_friendlyCountryName 0L, 9L, 2342L, 19200300L, 100L, 1L, 43L + +#define LN_organizationalStatus "organizationalStatus" +#define NID_organizationalStatus 491 +#define OBJ_organizationalStatus 0L, 9L, 2342L, 19200300L, 100L, 1L, 45L + +#define LN_janetMailbox "janetMailbox" +#define NID_janetMailbox 492 +#define OBJ_janetMailbox 0L, 9L, 2342L, 19200300L, 100L, 1L, 46L + +#define LN_mailPreferenceOption "mailPreferenceOption" +#define NID_mailPreferenceOption 493 +#define OBJ_mailPreferenceOption 0L, 9L, 2342L, 19200300L, 100L, 1L, 47L + +#define LN_buildingName "buildingName" +#define NID_buildingName 494 +#define OBJ_buildingName 0L, 9L, 2342L, 19200300L, 100L, 1L, 48L + +#define LN_dSAQuality "dSAQuality" +#define NID_dSAQuality 495 +#define OBJ_dSAQuality 0L, 9L, 2342L, 19200300L, 100L, 1L, 49L + +#define LN_singleLevelQuality "singleLevelQuality" +#define NID_singleLevelQuality 496 +#define OBJ_singleLevelQuality 0L, 9L, 2342L, 19200300L, 100L, 1L, 50L + +#define LN_subtreeMinimumQuality "subtreeMinimumQuality" +#define NID_subtreeMinimumQuality 497 +#define OBJ_subtreeMinimumQuality 0L, 9L, 2342L, 19200300L, 100L, 1L, 51L + +#define LN_subtreeMaximumQuality "subtreeMaximumQuality" +#define NID_subtreeMaximumQuality 498 +#define OBJ_subtreeMaximumQuality 0L, 9L, 2342L, 19200300L, 100L, 1L, 52L + +#define LN_personalSignature "personalSignature" +#define NID_personalSignature 499 +#define OBJ_personalSignature 0L, 9L, 2342L, 19200300L, 100L, 1L, 53L + +#define LN_dITRedirect "dITRedirect" +#define NID_dITRedirect 500 +#define OBJ_dITRedirect 0L, 9L, 2342L, 19200300L, 100L, 1L, 54L + +#define SN_audio "audio" +#define NID_audio 501 +#define OBJ_audio 0L, 9L, 2342L, 19200300L, 100L, 1L, 55L + +#define LN_documentPublisher "documentPublisher" +#define NID_documentPublisher 502 +#define OBJ_documentPublisher 0L, 9L, 2342L, 19200300L, 100L, 1L, 56L + +#define LN_x500UniqueIdentifier "x500UniqueIdentifier" +#define NID_x500UniqueIdentifier 503 +#define OBJ_x500UniqueIdentifier 2L, 5L, 4L, 45L + +#define SN_mime_mhs "mime-mhs" +#define LN_mime_mhs "MIME MHS" +#define NID_mime_mhs 504 +#define OBJ_mime_mhs 1L, 3L, 6L, 1L, 7L, 1L + +#define SN_mime_mhs_headings "mime-mhs-headings" +#define LN_mime_mhs_headings "mime-mhs-headings" +#define NID_mime_mhs_headings 505 +#define OBJ_mime_mhs_headings 1L, 3L, 6L, 1L, 7L, 1L, 1L + +#define SN_mime_mhs_bodies "mime-mhs-bodies" +#define LN_mime_mhs_bodies "mime-mhs-bodies" +#define NID_mime_mhs_bodies 506 +#define OBJ_mime_mhs_bodies 1L, 3L, 6L, 1L, 7L, 1L, 2L + +#define SN_id_hex_partial_message "id-hex-partial-message" +#define LN_id_hex_partial_message "id-hex-partial-message" +#define NID_id_hex_partial_message 507 +#define OBJ_id_hex_partial_message 1L, 3L, 6L, 1L, 7L, 1L, 1L, 1L + +#define SN_id_hex_multipart_message "id-hex-multipart-message" +#define LN_id_hex_multipart_message "id-hex-multipart-message" +#define NID_id_hex_multipart_message 508 +#define OBJ_id_hex_multipart_message 1L, 3L, 6L, 1L, 7L, 1L, 1L, 2L + +#define LN_generationQualifier "generationQualifier" +#define NID_generationQualifier 509 +#define OBJ_generationQualifier 2L, 5L, 4L, 44L + +#define LN_pseudonym "pseudonym" +#define NID_pseudonym 510 +#define OBJ_pseudonym 2L, 5L, 4L, 65L + +#define SN_id_set "id-set" +#define LN_id_set "Secure Electronic Transactions" +#define NID_id_set 512 +#define OBJ_id_set 2L, 23L, 42L + +#define SN_set_ctype "set-ctype" +#define LN_set_ctype "content types" +#define NID_set_ctype 513 +#define OBJ_set_ctype 2L, 23L, 42L, 0L + +#define SN_set_msgExt "set-msgExt" +#define LN_set_msgExt "message extensions" +#define NID_set_msgExt 514 +#define OBJ_set_msgExt 2L, 23L, 42L, 1L + +#define SN_set_attr "set-attr" +#define NID_set_attr 515 +#define OBJ_set_attr 2L, 23L, 42L, 3L + +#define SN_set_policy "set-policy" +#define NID_set_policy 516 +#define OBJ_set_policy 2L, 23L, 42L, 5L + +#define SN_set_certExt "set-certExt" +#define LN_set_certExt "certificate extensions" +#define NID_set_certExt 517 +#define OBJ_set_certExt 2L, 23L, 42L, 7L + +#define SN_set_brand "set-brand" +#define NID_set_brand 518 +#define OBJ_set_brand 2L, 23L, 42L, 8L + +#define SN_setct_PANData "setct-PANData" +#define NID_setct_PANData 519 +#define OBJ_setct_PANData 2L, 23L, 42L, 0L, 0L + +#define SN_setct_PANToken "setct-PANToken" +#define NID_setct_PANToken 520 +#define OBJ_setct_PANToken 2L, 23L, 42L, 0L, 1L + +#define SN_setct_PANOnly "setct-PANOnly" +#define NID_setct_PANOnly 521 +#define OBJ_setct_PANOnly 2L, 23L, 42L, 0L, 2L + +#define SN_setct_OIData "setct-OIData" +#define NID_setct_OIData 522 +#define OBJ_setct_OIData 2L, 23L, 42L, 0L, 3L + +#define SN_setct_PI "setct-PI" +#define NID_setct_PI 523 +#define OBJ_setct_PI 2L, 23L, 42L, 0L, 4L + +#define SN_setct_PIData "setct-PIData" +#define NID_setct_PIData 524 +#define OBJ_setct_PIData 2L, 23L, 42L, 0L, 5L + +#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned" +#define NID_setct_PIDataUnsigned 525 +#define OBJ_setct_PIDataUnsigned 2L, 23L, 42L, 0L, 6L + +#define SN_setct_HODInput "setct-HODInput" +#define NID_setct_HODInput 526 +#define OBJ_setct_HODInput 2L, 23L, 42L, 0L, 7L + +#define SN_setct_AuthResBaggage "setct-AuthResBaggage" +#define NID_setct_AuthResBaggage 527 +#define OBJ_setct_AuthResBaggage 2L, 23L, 42L, 0L, 8L + +#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage" +#define NID_setct_AuthRevReqBaggage 528 +#define OBJ_setct_AuthRevReqBaggage 2L, 23L, 42L, 0L, 9L + +#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage" +#define NID_setct_AuthRevResBaggage 529 +#define OBJ_setct_AuthRevResBaggage 2L, 23L, 42L, 0L, 10L + +#define SN_setct_CapTokenSeq "setct-CapTokenSeq" +#define NID_setct_CapTokenSeq 530 +#define OBJ_setct_CapTokenSeq 2L, 23L, 42L, 0L, 11L + +#define SN_setct_PInitResData "setct-PInitResData" +#define NID_setct_PInitResData 531 +#define OBJ_setct_PInitResData 2L, 23L, 42L, 0L, 12L + +#define SN_setct_PI_TBS "setct-PI-TBS" +#define NID_setct_PI_TBS 532 +#define OBJ_setct_PI_TBS 2L, 23L, 42L, 0L, 13L + +#define SN_setct_PResData "setct-PResData" +#define NID_setct_PResData 533 +#define OBJ_setct_PResData 2L, 23L, 42L, 0L, 14L + +#define SN_setct_AuthReqTBS "setct-AuthReqTBS" +#define NID_setct_AuthReqTBS 534 +#define OBJ_setct_AuthReqTBS 2L, 23L, 42L, 0L, 16L + +#define SN_setct_AuthResTBS "setct-AuthResTBS" +#define NID_setct_AuthResTBS 535 +#define OBJ_setct_AuthResTBS 2L, 23L, 42L, 0L, 17L + +#define SN_setct_AuthResTBSX "setct-AuthResTBSX" +#define NID_setct_AuthResTBSX 536 +#define OBJ_setct_AuthResTBSX 2L, 23L, 42L, 0L, 18L + +#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS" +#define NID_setct_AuthTokenTBS 537 +#define OBJ_setct_AuthTokenTBS 2L, 23L, 42L, 0L, 19L + +#define SN_setct_CapTokenData "setct-CapTokenData" +#define NID_setct_CapTokenData 538 +#define OBJ_setct_CapTokenData 2L, 23L, 42L, 0L, 20L + +#define SN_setct_CapTokenTBS "setct-CapTokenTBS" +#define NID_setct_CapTokenTBS 539 +#define OBJ_setct_CapTokenTBS 2L, 23L, 42L, 0L, 21L + +#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg" +#define NID_setct_AcqCardCodeMsg 540 +#define OBJ_setct_AcqCardCodeMsg 2L, 23L, 42L, 0L, 22L + +#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS" +#define NID_setct_AuthRevReqTBS 541 +#define OBJ_setct_AuthRevReqTBS 2L, 23L, 42L, 0L, 23L + +#define SN_setct_AuthRevResData "setct-AuthRevResData" +#define NID_setct_AuthRevResData 542 +#define OBJ_setct_AuthRevResData 2L, 23L, 42L, 0L, 24L + +#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS" +#define NID_setct_AuthRevResTBS 543 +#define OBJ_setct_AuthRevResTBS 2L, 23L, 42L, 0L, 25L + +#define SN_setct_CapReqTBS "setct-CapReqTBS" +#define NID_setct_CapReqTBS 544 +#define OBJ_setct_CapReqTBS 2L, 23L, 42L, 0L, 26L + +#define SN_setct_CapReqTBSX "setct-CapReqTBSX" +#define NID_setct_CapReqTBSX 545 +#define OBJ_setct_CapReqTBSX 2L, 23L, 42L, 0L, 27L + +#define SN_setct_CapResData "setct-CapResData" +#define NID_setct_CapResData 546 +#define OBJ_setct_CapResData 2L, 23L, 42L, 0L, 28L + +#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS" +#define NID_setct_CapRevReqTBS 547 +#define OBJ_setct_CapRevReqTBS 2L, 23L, 42L, 0L, 29L + +#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX" +#define NID_setct_CapRevReqTBSX 548 +#define OBJ_setct_CapRevReqTBSX 2L, 23L, 42L, 0L, 30L + +#define SN_setct_CapRevResData "setct-CapRevResData" +#define NID_setct_CapRevResData 549 +#define OBJ_setct_CapRevResData 2L, 23L, 42L, 0L, 31L + +#define SN_setct_CredReqTBS "setct-CredReqTBS" +#define NID_setct_CredReqTBS 550 +#define OBJ_setct_CredReqTBS 2L, 23L, 42L, 0L, 32L + +#define SN_setct_CredReqTBSX "setct-CredReqTBSX" +#define NID_setct_CredReqTBSX 551 +#define OBJ_setct_CredReqTBSX 2L, 23L, 42L, 0L, 33L + +#define SN_setct_CredResData "setct-CredResData" +#define NID_setct_CredResData 552 +#define OBJ_setct_CredResData 2L, 23L, 42L, 0L, 34L + +#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS" +#define NID_setct_CredRevReqTBS 553 +#define OBJ_setct_CredRevReqTBS 2L, 23L, 42L, 0L, 35L + +#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX" +#define NID_setct_CredRevReqTBSX 554 +#define OBJ_setct_CredRevReqTBSX 2L, 23L, 42L, 0L, 36L + +#define SN_setct_CredRevResData "setct-CredRevResData" +#define NID_setct_CredRevResData 555 +#define OBJ_setct_CredRevResData 2L, 23L, 42L, 0L, 37L + +#define SN_setct_PCertReqData "setct-PCertReqData" +#define NID_setct_PCertReqData 556 +#define OBJ_setct_PCertReqData 2L, 23L, 42L, 0L, 38L + +#define SN_setct_PCertResTBS "setct-PCertResTBS" +#define NID_setct_PCertResTBS 557 +#define OBJ_setct_PCertResTBS 2L, 23L, 42L, 0L, 39L + +#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData" +#define NID_setct_BatchAdminReqData 558 +#define OBJ_setct_BatchAdminReqData 2L, 23L, 42L, 0L, 40L + +#define SN_setct_BatchAdminResData "setct-BatchAdminResData" +#define NID_setct_BatchAdminResData 559 +#define OBJ_setct_BatchAdminResData 2L, 23L, 42L, 0L, 41L + +#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS" +#define NID_setct_CardCInitResTBS 560 +#define OBJ_setct_CardCInitResTBS 2L, 23L, 42L, 0L, 42L + +#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS" +#define NID_setct_MeAqCInitResTBS 561 +#define OBJ_setct_MeAqCInitResTBS 2L, 23L, 42L, 0L, 43L + +#define SN_setct_RegFormResTBS "setct-RegFormResTBS" +#define NID_setct_RegFormResTBS 562 +#define OBJ_setct_RegFormResTBS 2L, 23L, 42L, 0L, 44L + +#define SN_setct_CertReqData "setct-CertReqData" +#define NID_setct_CertReqData 563 +#define OBJ_setct_CertReqData 2L, 23L, 42L, 0L, 45L + +#define SN_setct_CertReqTBS "setct-CertReqTBS" +#define NID_setct_CertReqTBS 564 +#define OBJ_setct_CertReqTBS 2L, 23L, 42L, 0L, 46L + +#define SN_setct_CertResData "setct-CertResData" +#define NID_setct_CertResData 565 +#define OBJ_setct_CertResData 2L, 23L, 42L, 0L, 47L + +#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS" +#define NID_setct_CertInqReqTBS 566 +#define OBJ_setct_CertInqReqTBS 2L, 23L, 42L, 0L, 48L + +#define SN_setct_ErrorTBS "setct-ErrorTBS" +#define NID_setct_ErrorTBS 567 +#define OBJ_setct_ErrorTBS 2L, 23L, 42L, 0L, 49L + +#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE" +#define NID_setct_PIDualSignedTBE 568 +#define OBJ_setct_PIDualSignedTBE 2L, 23L, 42L, 0L, 50L + +#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE" +#define NID_setct_PIUnsignedTBE 569 +#define OBJ_setct_PIUnsignedTBE 2L, 23L, 42L, 0L, 51L + +#define SN_setct_AuthReqTBE "setct-AuthReqTBE" +#define NID_setct_AuthReqTBE 570 +#define OBJ_setct_AuthReqTBE 2L, 23L, 42L, 0L, 52L + +#define SN_setct_AuthResTBE "setct-AuthResTBE" +#define NID_setct_AuthResTBE 571 +#define OBJ_setct_AuthResTBE 2L, 23L, 42L, 0L, 53L + +#define SN_setct_AuthResTBEX "setct-AuthResTBEX" +#define NID_setct_AuthResTBEX 572 +#define OBJ_setct_AuthResTBEX 2L, 23L, 42L, 0L, 54L + +#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE" +#define NID_setct_AuthTokenTBE 573 +#define OBJ_setct_AuthTokenTBE 2L, 23L, 42L, 0L, 55L + +#define SN_setct_CapTokenTBE "setct-CapTokenTBE" +#define NID_setct_CapTokenTBE 574 +#define OBJ_setct_CapTokenTBE 2L, 23L, 42L, 0L, 56L + +#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX" +#define NID_setct_CapTokenTBEX 575 +#define OBJ_setct_CapTokenTBEX 2L, 23L, 42L, 0L, 57L + +#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE" +#define NID_setct_AcqCardCodeMsgTBE 576 +#define OBJ_setct_AcqCardCodeMsgTBE 2L, 23L, 42L, 0L, 58L + +#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE" +#define NID_setct_AuthRevReqTBE 577 +#define OBJ_setct_AuthRevReqTBE 2L, 23L, 42L, 0L, 59L + +#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE" +#define NID_setct_AuthRevResTBE 578 +#define OBJ_setct_AuthRevResTBE 2L, 23L, 42L, 0L, 60L + +#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB" +#define NID_setct_AuthRevResTBEB 579 +#define OBJ_setct_AuthRevResTBEB 2L, 23L, 42L, 0L, 61L + +#define SN_setct_CapReqTBE "setct-CapReqTBE" +#define NID_setct_CapReqTBE 580 +#define OBJ_setct_CapReqTBE 2L, 23L, 42L, 0L, 62L + +#define SN_setct_CapReqTBEX "setct-CapReqTBEX" +#define NID_setct_CapReqTBEX 581 +#define OBJ_setct_CapReqTBEX 2L, 23L, 42L, 0L, 63L + +#define SN_setct_CapResTBE "setct-CapResTBE" +#define NID_setct_CapResTBE 582 +#define OBJ_setct_CapResTBE 2L, 23L, 42L, 0L, 64L + +#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE" +#define NID_setct_CapRevReqTBE 583 +#define OBJ_setct_CapRevReqTBE 2L, 23L, 42L, 0L, 65L + +#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX" +#define NID_setct_CapRevReqTBEX 584 +#define OBJ_setct_CapRevReqTBEX 2L, 23L, 42L, 0L, 66L + +#define SN_setct_CapRevResTBE "setct-CapRevResTBE" +#define NID_setct_CapRevResTBE 585 +#define OBJ_setct_CapRevResTBE 2L, 23L, 42L, 0L, 67L + +#define SN_setct_CredReqTBE "setct-CredReqTBE" +#define NID_setct_CredReqTBE 586 +#define OBJ_setct_CredReqTBE 2L, 23L, 42L, 0L, 68L + +#define SN_setct_CredReqTBEX "setct-CredReqTBEX" +#define NID_setct_CredReqTBEX 587 +#define OBJ_setct_CredReqTBEX 2L, 23L, 42L, 0L, 69L + +#define SN_setct_CredResTBE "setct-CredResTBE" +#define NID_setct_CredResTBE 588 +#define OBJ_setct_CredResTBE 2L, 23L, 42L, 0L, 70L + +#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE" +#define NID_setct_CredRevReqTBE 589 +#define OBJ_setct_CredRevReqTBE 2L, 23L, 42L, 0L, 71L + +#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX" +#define NID_setct_CredRevReqTBEX 590 +#define OBJ_setct_CredRevReqTBEX 2L, 23L, 42L, 0L, 72L + +#define SN_setct_CredRevResTBE "setct-CredRevResTBE" +#define NID_setct_CredRevResTBE 591 +#define OBJ_setct_CredRevResTBE 2L, 23L, 42L, 0L, 73L + +#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE" +#define NID_setct_BatchAdminReqTBE 592 +#define OBJ_setct_BatchAdminReqTBE 2L, 23L, 42L, 0L, 74L + +#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE" +#define NID_setct_BatchAdminResTBE 593 +#define OBJ_setct_BatchAdminResTBE 2L, 23L, 42L, 0L, 75L + +#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE" +#define NID_setct_RegFormReqTBE 594 +#define OBJ_setct_RegFormReqTBE 2L, 23L, 42L, 0L, 76L + +#define SN_setct_CertReqTBE "setct-CertReqTBE" +#define NID_setct_CertReqTBE 595 +#define OBJ_setct_CertReqTBE 2L, 23L, 42L, 0L, 77L + +#define SN_setct_CertReqTBEX "setct-CertReqTBEX" +#define NID_setct_CertReqTBEX 596 +#define OBJ_setct_CertReqTBEX 2L, 23L, 42L, 0L, 78L + +#define SN_setct_CertResTBE "setct-CertResTBE" +#define NID_setct_CertResTBE 597 +#define OBJ_setct_CertResTBE 2L, 23L, 42L, 0L, 79L + +#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS" +#define NID_setct_CRLNotificationTBS 598 +#define OBJ_setct_CRLNotificationTBS 2L, 23L, 42L, 0L, 80L + +#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS" +#define NID_setct_CRLNotificationResTBS 599 +#define OBJ_setct_CRLNotificationResTBS 2L, 23L, 42L, 0L, 81L + +#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS" +#define NID_setct_BCIDistributionTBS 600 +#define OBJ_setct_BCIDistributionTBS 2L, 23L, 42L, 0L, 82L + +#define SN_setext_genCrypt "setext-genCrypt" +#define LN_setext_genCrypt "generic cryptogram" +#define NID_setext_genCrypt 601 +#define OBJ_setext_genCrypt 2L, 23L, 42L, 1L, 1L + +#define SN_setext_miAuth "setext-miAuth" +#define LN_setext_miAuth "merchant initiated auth" +#define NID_setext_miAuth 602 +#define OBJ_setext_miAuth 2L, 23L, 42L, 1L, 3L + +#define SN_setext_pinSecure "setext-pinSecure" +#define NID_setext_pinSecure 603 +#define OBJ_setext_pinSecure 2L, 23L, 42L, 1L, 4L + +#define SN_setext_pinAny "setext-pinAny" +#define NID_setext_pinAny 604 +#define OBJ_setext_pinAny 2L, 23L, 42L, 1L, 5L + +#define SN_setext_track2 "setext-track2" +#define NID_setext_track2 605 +#define OBJ_setext_track2 2L, 23L, 42L, 1L, 7L + +#define SN_setext_cv "setext-cv" +#define LN_setext_cv "additional verification" +#define NID_setext_cv 606 +#define OBJ_setext_cv 2L, 23L, 42L, 1L, 8L + +#define SN_set_policy_root "set-policy-root" +#define NID_set_policy_root 607 +#define OBJ_set_policy_root 2L, 23L, 42L, 5L, 0L + +#define SN_setCext_hashedRoot "setCext-hashedRoot" +#define NID_setCext_hashedRoot 608 +#define OBJ_setCext_hashedRoot 2L, 23L, 42L, 7L, 0L + +#define SN_setCext_certType "setCext-certType" +#define NID_setCext_certType 609 +#define OBJ_setCext_certType 2L, 23L, 42L, 7L, 1L + +#define SN_setCext_merchData "setCext-merchData" +#define NID_setCext_merchData 610 +#define OBJ_setCext_merchData 2L, 23L, 42L, 7L, 2L + +#define SN_setCext_cCertRequired "setCext-cCertRequired" +#define NID_setCext_cCertRequired 611 +#define OBJ_setCext_cCertRequired 2L, 23L, 42L, 7L, 3L + +#define SN_setCext_tunneling "setCext-tunneling" +#define NID_setCext_tunneling 612 +#define OBJ_setCext_tunneling 2L, 23L, 42L, 7L, 4L + +#define SN_setCext_setExt "setCext-setExt" +#define NID_setCext_setExt 613 +#define OBJ_setCext_setExt 2L, 23L, 42L, 7L, 5L + +#define SN_setCext_setQualf "setCext-setQualf" +#define NID_setCext_setQualf 614 +#define OBJ_setCext_setQualf 2L, 23L, 42L, 7L, 6L + +#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities" +#define NID_setCext_PGWYcapabilities 615 +#define OBJ_setCext_PGWYcapabilities 2L, 23L, 42L, 7L, 7L + +#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier" +#define NID_setCext_TokenIdentifier 616 +#define OBJ_setCext_TokenIdentifier 2L, 23L, 42L, 7L, 8L + +#define SN_setCext_Track2Data "setCext-Track2Data" +#define NID_setCext_Track2Data 617 +#define OBJ_setCext_Track2Data 2L, 23L, 42L, 7L, 9L + +#define SN_setCext_TokenType "setCext-TokenType" +#define NID_setCext_TokenType 618 +#define OBJ_setCext_TokenType 2L, 23L, 42L, 7L, 10L + +#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities" +#define NID_setCext_IssuerCapabilities 619 +#define OBJ_setCext_IssuerCapabilities 2L, 23L, 42L, 7L, 11L + +#define SN_setAttr_Cert "setAttr-Cert" +#define NID_setAttr_Cert 620 +#define OBJ_setAttr_Cert 2L, 23L, 42L, 3L, 0L + +#define SN_setAttr_PGWYcap "setAttr-PGWYcap" +#define LN_setAttr_PGWYcap "payment gateway capabilities" +#define NID_setAttr_PGWYcap 621 +#define OBJ_setAttr_PGWYcap 2L, 23L, 42L, 3L, 1L + +#define SN_setAttr_TokenType "setAttr-TokenType" +#define NID_setAttr_TokenType 622 +#define OBJ_setAttr_TokenType 2L, 23L, 42L, 3L, 2L + +#define SN_setAttr_IssCap "setAttr-IssCap" +#define LN_setAttr_IssCap "issuer capabilities" +#define NID_setAttr_IssCap 623 +#define OBJ_setAttr_IssCap 2L, 23L, 42L, 3L, 3L + +#define SN_set_rootKeyThumb "set-rootKeyThumb" +#define NID_set_rootKeyThumb 624 +#define OBJ_set_rootKeyThumb 2L, 23L, 42L, 3L, 0L, 0L + +#define SN_set_addPolicy "set-addPolicy" +#define NID_set_addPolicy 625 +#define OBJ_set_addPolicy 2L, 23L, 42L, 3L, 0L, 1L + +#define SN_setAttr_Token_EMV "setAttr-Token-EMV" +#define NID_setAttr_Token_EMV 626 +#define OBJ_setAttr_Token_EMV 2L, 23L, 42L, 3L, 2L, 1L + +#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime" +#define NID_setAttr_Token_B0Prime 627 +#define OBJ_setAttr_Token_B0Prime 2L, 23L, 42L, 3L, 2L, 2L + +#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM" +#define NID_setAttr_IssCap_CVM 628 +#define OBJ_setAttr_IssCap_CVM 2L, 23L, 42L, 3L, 3L, 3L + +#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2" +#define NID_setAttr_IssCap_T2 629 +#define OBJ_setAttr_IssCap_T2 2L, 23L, 42L, 3L, 3L, 4L + +#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig" +#define NID_setAttr_IssCap_Sig 630 +#define OBJ_setAttr_IssCap_Sig 2L, 23L, 42L, 3L, 3L, 5L + +#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm" +#define LN_setAttr_GenCryptgrm "generate cryptogram" +#define NID_setAttr_GenCryptgrm 631 +#define OBJ_setAttr_GenCryptgrm 2L, 23L, 42L, 3L, 3L, 3L, 1L + +#define SN_setAttr_T2Enc "setAttr-T2Enc" +#define LN_setAttr_T2Enc "encrypted track 2" +#define NID_setAttr_T2Enc 632 +#define OBJ_setAttr_T2Enc 2L, 23L, 42L, 3L, 3L, 4L, 1L + +#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt" +#define LN_setAttr_T2cleartxt "cleartext track 2" +#define NID_setAttr_T2cleartxt 633 +#define OBJ_setAttr_T2cleartxt 2L, 23L, 42L, 3L, 3L, 4L, 2L + +#define SN_setAttr_TokICCsig "setAttr-TokICCsig" +#define LN_setAttr_TokICCsig "ICC or token signature" +#define NID_setAttr_TokICCsig 634 +#define OBJ_setAttr_TokICCsig 2L, 23L, 42L, 3L, 3L, 5L, 1L + +#define SN_setAttr_SecDevSig "setAttr-SecDevSig" +#define LN_setAttr_SecDevSig "secure device signature" +#define NID_setAttr_SecDevSig 635 +#define OBJ_setAttr_SecDevSig 2L, 23L, 42L, 3L, 3L, 5L, 2L + +#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA" +#define NID_set_brand_IATA_ATA 636 +#define OBJ_set_brand_IATA_ATA 2L, 23L, 42L, 8L, 1L + +#define SN_set_brand_Diners "set-brand-Diners" +#define NID_set_brand_Diners 637 +#define OBJ_set_brand_Diners 2L, 23L, 42L, 8L, 30L + +#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress" +#define NID_set_brand_AmericanExpress 638 +#define OBJ_set_brand_AmericanExpress 2L, 23L, 42L, 8L, 34L + +#define SN_set_brand_JCB "set-brand-JCB" +#define NID_set_brand_JCB 639 +#define OBJ_set_brand_JCB 2L, 23L, 42L, 8L, 35L + +#define SN_set_brand_Visa "set-brand-Visa" +#define NID_set_brand_Visa 640 +#define OBJ_set_brand_Visa 2L, 23L, 42L, 8L, 4L + +#define SN_set_brand_MasterCard "set-brand-MasterCard" +#define NID_set_brand_MasterCard 641 +#define OBJ_set_brand_MasterCard 2L, 23L, 42L, 8L, 5L + +#define SN_set_brand_Novus "set-brand-Novus" +#define NID_set_brand_Novus 642 +#define OBJ_set_brand_Novus 2L, 23L, 42L, 8L, 6011L + +#define SN_des_cdmf "DES-CDMF" +#define LN_des_cdmf "des-cdmf" +#define NID_des_cdmf 643 +#define OBJ_des_cdmf 1L, 2L, 840L, 113549L, 3L, 10L + +#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET" +#define NID_rsaOAEPEncryptionSET 644 +#define OBJ_rsaOAEPEncryptionSET 1L, 2L, 840L, 113549L, 1L, 1L, 6L + +#define SN_itu_t "ITU-T" +#define LN_itu_t "itu-t" +#define NID_itu_t 645 +#define OBJ_itu_t 0L + +#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T" +#define LN_joint_iso_itu_t "joint-iso-itu-t" +#define NID_joint_iso_itu_t 646 +#define OBJ_joint_iso_itu_t 2L + +#define SN_international_organizations "international-organizations" +#define LN_international_organizations "International Organizations" +#define NID_international_organizations 647 +#define OBJ_international_organizations 2L, 23L + +#define SN_ms_smartcard_login "msSmartcardLogin" +#define LN_ms_smartcard_login "Microsoft Smartcardlogin" +#define NID_ms_smartcard_login 648 +#define OBJ_ms_smartcard_login 1L, 3L, 6L, 1L, 4L, 1L, 311L, 20L, 2L, 2L + +#define SN_ms_upn "msUPN" +#define LN_ms_upn "Microsoft Universal Principal Name" +#define NID_ms_upn 649 +#define OBJ_ms_upn 1L, 3L, 6L, 1L, 4L, 1L, 311L, 20L, 2L, 3L + +#define SN_aes_128_cfb1 "AES-128-CFB1" +#define LN_aes_128_cfb1 "aes-128-cfb1" +#define NID_aes_128_cfb1 650 + +#define SN_aes_192_cfb1 "AES-192-CFB1" +#define LN_aes_192_cfb1 "aes-192-cfb1" +#define NID_aes_192_cfb1 651 + +#define SN_aes_256_cfb1 "AES-256-CFB1" +#define LN_aes_256_cfb1 "aes-256-cfb1" +#define NID_aes_256_cfb1 652 + +#define SN_aes_128_cfb8 "AES-128-CFB8" +#define LN_aes_128_cfb8 "aes-128-cfb8" +#define NID_aes_128_cfb8 653 + +#define SN_aes_192_cfb8 "AES-192-CFB8" +#define LN_aes_192_cfb8 "aes-192-cfb8" +#define NID_aes_192_cfb8 654 + +#define SN_aes_256_cfb8 "AES-256-CFB8" +#define LN_aes_256_cfb8 "aes-256-cfb8" +#define NID_aes_256_cfb8 655 + +#define SN_des_cfb1 "DES-CFB1" +#define LN_des_cfb1 "des-cfb1" +#define NID_des_cfb1 656 + +#define SN_des_cfb8 "DES-CFB8" +#define LN_des_cfb8 "des-cfb8" +#define NID_des_cfb8 657 + +#define SN_des_ede3_cfb1 "DES-EDE3-CFB1" +#define LN_des_ede3_cfb1 "des-ede3-cfb1" +#define NID_des_ede3_cfb1 658 + +#define SN_des_ede3_cfb8 "DES-EDE3-CFB8" +#define LN_des_ede3_cfb8 "des-ede3-cfb8" +#define NID_des_ede3_cfb8 659 + +#define SN_streetAddress "street" +#define LN_streetAddress "streetAddress" +#define NID_streetAddress 660 +#define OBJ_streetAddress 2L, 5L, 4L, 9L + +#define LN_postalCode "postalCode" +#define NID_postalCode 661 +#define OBJ_postalCode 2L, 5L, 4L, 17L + +#define SN_id_ppl "id-ppl" +#define NID_id_ppl 662 +#define OBJ_id_ppl 1L, 3L, 6L, 1L, 5L, 5L, 7L, 21L + +#define SN_proxyCertInfo "proxyCertInfo" +#define LN_proxyCertInfo "Proxy Certificate Information" +#define NID_proxyCertInfo 663 +#define OBJ_proxyCertInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 14L + +#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage" +#define LN_id_ppl_anyLanguage "Any language" +#define NID_id_ppl_anyLanguage 664 +#define OBJ_id_ppl_anyLanguage 1L, 3L, 6L, 1L, 5L, 5L, 7L, 21L, 0L + +#define SN_id_ppl_inheritAll "id-ppl-inheritAll" +#define LN_id_ppl_inheritAll "Inherit all" +#define NID_id_ppl_inheritAll 665 +#define OBJ_id_ppl_inheritAll 1L, 3L, 6L, 1L, 5L, 5L, 7L, 21L, 1L + +#define SN_name_constraints "nameConstraints" +#define LN_name_constraints "X509v3 Name Constraints" +#define NID_name_constraints 666 +#define OBJ_name_constraints 2L, 5L, 29L, 30L + +#define SN_Independent "id-ppl-independent" +#define LN_Independent "Independent" +#define NID_Independent 667 +#define OBJ_Independent 1L, 3L, 6L, 1L, 5L, 5L, 7L, 21L, 2L + +#define SN_sha256WithRSAEncryption "RSA-SHA256" +#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption" +#define NID_sha256WithRSAEncryption 668 +#define OBJ_sha256WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 11L + +#define SN_sha384WithRSAEncryption "RSA-SHA384" +#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption" +#define NID_sha384WithRSAEncryption 669 +#define OBJ_sha384WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 12L + +#define SN_sha512WithRSAEncryption "RSA-SHA512" +#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption" +#define NID_sha512WithRSAEncryption 670 +#define OBJ_sha512WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 13L + +#define SN_sha224WithRSAEncryption "RSA-SHA224" +#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption" +#define NID_sha224WithRSAEncryption 671 +#define OBJ_sha224WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 14L + +#define SN_sha256 "SHA256" +#define LN_sha256 "sha256" +#define NID_sha256 672 +#define OBJ_sha256 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 1L + +#define SN_sha384 "SHA384" +#define LN_sha384 "sha384" +#define NID_sha384 673 +#define OBJ_sha384 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 2L + +#define SN_sha512 "SHA512" +#define LN_sha512 "sha512" +#define NID_sha512 674 +#define OBJ_sha512 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 3L + +#define SN_sha224 "SHA224" +#define LN_sha224 "sha224" +#define NID_sha224 675 +#define OBJ_sha224 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 4L + +#define SN_identified_organization "identified-organization" +#define NID_identified_organization 676 +#define OBJ_identified_organization 1L, 3L + +#define SN_certicom_arc "certicom-arc" +#define NID_certicom_arc 677 +#define OBJ_certicom_arc 1L, 3L, 132L + +#define SN_wap "wap" +#define NID_wap 678 +#define OBJ_wap 2L, 23L, 43L + +#define SN_wap_wsg "wap-wsg" +#define NID_wap_wsg 679 +#define OBJ_wap_wsg 2L, 23L, 43L, 1L + +#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis" +#define NID_X9_62_id_characteristic_two_basis 680 +#define OBJ_X9_62_id_characteristic_two_basis 1L, 2L, 840L, 10045L, 1L, 2L, 3L + +#define SN_X9_62_onBasis "onBasis" +#define NID_X9_62_onBasis 681 +#define OBJ_X9_62_onBasis 1L, 2L, 840L, 10045L, 1L, 2L, 3L, 1L + +#define SN_X9_62_tpBasis "tpBasis" +#define NID_X9_62_tpBasis 682 +#define OBJ_X9_62_tpBasis 1L, 2L, 840L, 10045L, 1L, 2L, 3L, 2L + +#define SN_X9_62_ppBasis "ppBasis" +#define NID_X9_62_ppBasis 683 +#define OBJ_X9_62_ppBasis 1L, 2L, 840L, 10045L, 1L, 2L, 3L, 3L + +#define SN_X9_62_c2pnb163v1 "c2pnb163v1" +#define NID_X9_62_c2pnb163v1 684 +#define OBJ_X9_62_c2pnb163v1 1L, 2L, 840L, 10045L, 3L, 0L, 1L + +#define SN_X9_62_c2pnb163v2 "c2pnb163v2" +#define NID_X9_62_c2pnb163v2 685 +#define OBJ_X9_62_c2pnb163v2 1L, 2L, 840L, 10045L, 3L, 0L, 2L + +#define SN_X9_62_c2pnb163v3 "c2pnb163v3" +#define NID_X9_62_c2pnb163v3 686 +#define OBJ_X9_62_c2pnb163v3 1L, 2L, 840L, 10045L, 3L, 0L, 3L + +#define SN_X9_62_c2pnb176v1 "c2pnb176v1" +#define NID_X9_62_c2pnb176v1 687 +#define OBJ_X9_62_c2pnb176v1 1L, 2L, 840L, 10045L, 3L, 0L, 4L + +#define SN_X9_62_c2tnb191v1 "c2tnb191v1" +#define NID_X9_62_c2tnb191v1 688 +#define OBJ_X9_62_c2tnb191v1 1L, 2L, 840L, 10045L, 3L, 0L, 5L + +#define SN_X9_62_c2tnb191v2 "c2tnb191v2" +#define NID_X9_62_c2tnb191v2 689 +#define OBJ_X9_62_c2tnb191v2 1L, 2L, 840L, 10045L, 3L, 0L, 6L + +#define SN_X9_62_c2tnb191v3 "c2tnb191v3" +#define NID_X9_62_c2tnb191v3 690 +#define OBJ_X9_62_c2tnb191v3 1L, 2L, 840L, 10045L, 3L, 0L, 7L + +#define SN_X9_62_c2onb191v4 "c2onb191v4" +#define NID_X9_62_c2onb191v4 691 +#define OBJ_X9_62_c2onb191v4 1L, 2L, 840L, 10045L, 3L, 0L, 8L + +#define SN_X9_62_c2onb191v5 "c2onb191v5" +#define NID_X9_62_c2onb191v5 692 +#define OBJ_X9_62_c2onb191v5 1L, 2L, 840L, 10045L, 3L, 0L, 9L + +#define SN_X9_62_c2pnb208w1 "c2pnb208w1" +#define NID_X9_62_c2pnb208w1 693 +#define OBJ_X9_62_c2pnb208w1 1L, 2L, 840L, 10045L, 3L, 0L, 10L + +#define SN_X9_62_c2tnb239v1 "c2tnb239v1" +#define NID_X9_62_c2tnb239v1 694 +#define OBJ_X9_62_c2tnb239v1 1L, 2L, 840L, 10045L, 3L, 0L, 11L + +#define SN_X9_62_c2tnb239v2 "c2tnb239v2" +#define NID_X9_62_c2tnb239v2 695 +#define OBJ_X9_62_c2tnb239v2 1L, 2L, 840L, 10045L, 3L, 0L, 12L + +#define SN_X9_62_c2tnb239v3 "c2tnb239v3" +#define NID_X9_62_c2tnb239v3 696 +#define OBJ_X9_62_c2tnb239v3 1L, 2L, 840L, 10045L, 3L, 0L, 13L + +#define SN_X9_62_c2onb239v4 "c2onb239v4" +#define NID_X9_62_c2onb239v4 697 +#define OBJ_X9_62_c2onb239v4 1L, 2L, 840L, 10045L, 3L, 0L, 14L + +#define SN_X9_62_c2onb239v5 "c2onb239v5" +#define NID_X9_62_c2onb239v5 698 +#define OBJ_X9_62_c2onb239v5 1L, 2L, 840L, 10045L, 3L, 0L, 15L + +#define SN_X9_62_c2pnb272w1 "c2pnb272w1" +#define NID_X9_62_c2pnb272w1 699 +#define OBJ_X9_62_c2pnb272w1 1L, 2L, 840L, 10045L, 3L, 0L, 16L + +#define SN_X9_62_c2pnb304w1 "c2pnb304w1" +#define NID_X9_62_c2pnb304w1 700 +#define OBJ_X9_62_c2pnb304w1 1L, 2L, 840L, 10045L, 3L, 0L, 17L + +#define SN_X9_62_c2tnb359v1 "c2tnb359v1" +#define NID_X9_62_c2tnb359v1 701 +#define OBJ_X9_62_c2tnb359v1 1L, 2L, 840L, 10045L, 3L, 0L, 18L + +#define SN_X9_62_c2pnb368w1 "c2pnb368w1" +#define NID_X9_62_c2pnb368w1 702 +#define OBJ_X9_62_c2pnb368w1 1L, 2L, 840L, 10045L, 3L, 0L, 19L + +#define SN_X9_62_c2tnb431r1 "c2tnb431r1" +#define NID_X9_62_c2tnb431r1 703 +#define OBJ_X9_62_c2tnb431r1 1L, 2L, 840L, 10045L, 3L, 0L, 20L + +#define SN_secp112r1 "secp112r1" +#define NID_secp112r1 704 +#define OBJ_secp112r1 1L, 3L, 132L, 0L, 6L + +#define SN_secp112r2 "secp112r2" +#define NID_secp112r2 705 +#define OBJ_secp112r2 1L, 3L, 132L, 0L, 7L + +#define SN_secp128r1 "secp128r1" +#define NID_secp128r1 706 +#define OBJ_secp128r1 1L, 3L, 132L, 0L, 28L + +#define SN_secp128r2 "secp128r2" +#define NID_secp128r2 707 +#define OBJ_secp128r2 1L, 3L, 132L, 0L, 29L + +#define SN_secp160k1 "secp160k1" +#define NID_secp160k1 708 +#define OBJ_secp160k1 1L, 3L, 132L, 0L, 9L + +#define SN_secp160r1 "secp160r1" +#define NID_secp160r1 709 +#define OBJ_secp160r1 1L, 3L, 132L, 0L, 8L + +#define SN_secp160r2 "secp160r2" +#define NID_secp160r2 710 +#define OBJ_secp160r2 1L, 3L, 132L, 0L, 30L + +#define SN_secp192k1 "secp192k1" +#define NID_secp192k1 711 +#define OBJ_secp192k1 1L, 3L, 132L, 0L, 31L + +#define SN_secp224k1 "secp224k1" +#define NID_secp224k1 712 +#define OBJ_secp224k1 1L, 3L, 132L, 0L, 32L + +#define SN_secp224r1 "secp224r1" +#define NID_secp224r1 713 +#define OBJ_secp224r1 1L, 3L, 132L, 0L, 33L + +#define SN_secp256k1 "secp256k1" +#define NID_secp256k1 714 +#define OBJ_secp256k1 1L, 3L, 132L, 0L, 10L + +#define SN_secp384r1 "secp384r1" +#define NID_secp384r1 715 +#define OBJ_secp384r1 1L, 3L, 132L, 0L, 34L + +#define SN_secp521r1 "secp521r1" +#define NID_secp521r1 716 +#define OBJ_secp521r1 1L, 3L, 132L, 0L, 35L + +#define SN_sect113r1 "sect113r1" +#define NID_sect113r1 717 +#define OBJ_sect113r1 1L, 3L, 132L, 0L, 4L + +#define SN_sect113r2 "sect113r2" +#define NID_sect113r2 718 +#define OBJ_sect113r2 1L, 3L, 132L, 0L, 5L + +#define SN_sect131r1 "sect131r1" +#define NID_sect131r1 719 +#define OBJ_sect131r1 1L, 3L, 132L, 0L, 22L + +#define SN_sect131r2 "sect131r2" +#define NID_sect131r2 720 +#define OBJ_sect131r2 1L, 3L, 132L, 0L, 23L + +#define SN_sect163k1 "sect163k1" +#define NID_sect163k1 721 +#define OBJ_sect163k1 1L, 3L, 132L, 0L, 1L + +#define SN_sect163r1 "sect163r1" +#define NID_sect163r1 722 +#define OBJ_sect163r1 1L, 3L, 132L, 0L, 2L + +#define SN_sect163r2 "sect163r2" +#define NID_sect163r2 723 +#define OBJ_sect163r2 1L, 3L, 132L, 0L, 15L + +#define SN_sect193r1 "sect193r1" +#define NID_sect193r1 724 +#define OBJ_sect193r1 1L, 3L, 132L, 0L, 24L + +#define SN_sect193r2 "sect193r2" +#define NID_sect193r2 725 +#define OBJ_sect193r2 1L, 3L, 132L, 0L, 25L + +#define SN_sect233k1 "sect233k1" +#define NID_sect233k1 726 +#define OBJ_sect233k1 1L, 3L, 132L, 0L, 26L + +#define SN_sect233r1 "sect233r1" +#define NID_sect233r1 727 +#define OBJ_sect233r1 1L, 3L, 132L, 0L, 27L + +#define SN_sect239k1 "sect239k1" +#define NID_sect239k1 728 +#define OBJ_sect239k1 1L, 3L, 132L, 0L, 3L + +#define SN_sect283k1 "sect283k1" +#define NID_sect283k1 729 +#define OBJ_sect283k1 1L, 3L, 132L, 0L, 16L + +#define SN_sect283r1 "sect283r1" +#define NID_sect283r1 730 +#define OBJ_sect283r1 1L, 3L, 132L, 0L, 17L + +#define SN_sect409k1 "sect409k1" +#define NID_sect409k1 731 +#define OBJ_sect409k1 1L, 3L, 132L, 0L, 36L + +#define SN_sect409r1 "sect409r1" +#define NID_sect409r1 732 +#define OBJ_sect409r1 1L, 3L, 132L, 0L, 37L + +#define SN_sect571k1 "sect571k1" +#define NID_sect571k1 733 +#define OBJ_sect571k1 1L, 3L, 132L, 0L, 38L + +#define SN_sect571r1 "sect571r1" +#define NID_sect571r1 734 +#define OBJ_sect571r1 1L, 3L, 132L, 0L, 39L + +#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1" +#define NID_wap_wsg_idm_ecid_wtls1 735 +#define OBJ_wap_wsg_idm_ecid_wtls1 2L, 23L, 43L, 1L, 4L, 1L + +#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3" +#define NID_wap_wsg_idm_ecid_wtls3 736 +#define OBJ_wap_wsg_idm_ecid_wtls3 2L, 23L, 43L, 1L, 4L, 3L + +#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4" +#define NID_wap_wsg_idm_ecid_wtls4 737 +#define OBJ_wap_wsg_idm_ecid_wtls4 2L, 23L, 43L, 1L, 4L, 4L + +#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5" +#define NID_wap_wsg_idm_ecid_wtls5 738 +#define OBJ_wap_wsg_idm_ecid_wtls5 2L, 23L, 43L, 1L, 4L, 5L + +#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6" +#define NID_wap_wsg_idm_ecid_wtls6 739 +#define OBJ_wap_wsg_idm_ecid_wtls6 2L, 23L, 43L, 1L, 4L, 6L + +#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7" +#define NID_wap_wsg_idm_ecid_wtls7 740 +#define OBJ_wap_wsg_idm_ecid_wtls7 2L, 23L, 43L, 1L, 4L, 7L + +#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8" +#define NID_wap_wsg_idm_ecid_wtls8 741 +#define OBJ_wap_wsg_idm_ecid_wtls8 2L, 23L, 43L, 1L, 4L, 8L + +#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9" +#define NID_wap_wsg_idm_ecid_wtls9 742 +#define OBJ_wap_wsg_idm_ecid_wtls9 2L, 23L, 43L, 1L, 4L, 9L + +#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10" +#define NID_wap_wsg_idm_ecid_wtls10 743 +#define OBJ_wap_wsg_idm_ecid_wtls10 2L, 23L, 43L, 1L, 4L, 10L + +#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11" +#define NID_wap_wsg_idm_ecid_wtls11 744 +#define OBJ_wap_wsg_idm_ecid_wtls11 2L, 23L, 43L, 1L, 4L, 11L + +#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12" +#define NID_wap_wsg_idm_ecid_wtls12 745 +#define OBJ_wap_wsg_idm_ecid_wtls12 2L, 23L, 43L, 1L, 4L, 12L + +#define SN_any_policy "anyPolicy" +#define LN_any_policy "X509v3 Any Policy" +#define NID_any_policy 746 +#define OBJ_any_policy 2L, 5L, 29L, 32L, 0L + +#define SN_policy_mappings "policyMappings" +#define LN_policy_mappings "X509v3 Policy Mappings" +#define NID_policy_mappings 747 +#define OBJ_policy_mappings 2L, 5L, 29L, 33L + +#define SN_inhibit_any_policy "inhibitAnyPolicy" +#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy" +#define NID_inhibit_any_policy 748 +#define OBJ_inhibit_any_policy 2L, 5L, 29L, 54L + +#define SN_ipsec3 "Oakley-EC2N-3" +#define LN_ipsec3 "ipsec3" +#define NID_ipsec3 749 + +#define SN_ipsec4 "Oakley-EC2N-4" +#define LN_ipsec4 "ipsec4" +#define NID_ipsec4 750 + +#define SN_camellia_128_cbc "CAMELLIA-128-CBC" +#define LN_camellia_128_cbc "camellia-128-cbc" +#define NID_camellia_128_cbc 751 +#define OBJ_camellia_128_cbc 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 1L, 2L + +#define SN_camellia_192_cbc "CAMELLIA-192-CBC" +#define LN_camellia_192_cbc "camellia-192-cbc" +#define NID_camellia_192_cbc 752 +#define OBJ_camellia_192_cbc 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 1L, 3L + +#define SN_camellia_256_cbc "CAMELLIA-256-CBC" +#define LN_camellia_256_cbc "camellia-256-cbc" +#define NID_camellia_256_cbc 753 +#define OBJ_camellia_256_cbc 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 1L, 4L + +#define SN_camellia_128_ecb "CAMELLIA-128-ECB" +#define LN_camellia_128_ecb "camellia-128-ecb" +#define NID_camellia_128_ecb 754 +#define OBJ_camellia_128_ecb 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 1L + +#define SN_camellia_192_ecb "CAMELLIA-192-ECB" +#define LN_camellia_192_ecb "camellia-192-ecb" +#define NID_camellia_192_ecb 755 +#define OBJ_camellia_192_ecb 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 21L + +#define SN_camellia_256_ecb "CAMELLIA-256-ECB" +#define LN_camellia_256_ecb "camellia-256-ecb" +#define NID_camellia_256_ecb 756 +#define OBJ_camellia_256_ecb 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 41L + +#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB" +#define LN_camellia_128_cfb128 "camellia-128-cfb" +#define NID_camellia_128_cfb128 757 +#define OBJ_camellia_128_cfb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 4L + +#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB" +#define LN_camellia_192_cfb128 "camellia-192-cfb" +#define NID_camellia_192_cfb128 758 +#define OBJ_camellia_192_cfb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 24L + +#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB" +#define LN_camellia_256_cfb128 "camellia-256-cfb" +#define NID_camellia_256_cfb128 759 +#define OBJ_camellia_256_cfb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 44L + +#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1" +#define LN_camellia_128_cfb1 "camellia-128-cfb1" +#define NID_camellia_128_cfb1 760 + +#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1" +#define LN_camellia_192_cfb1 "camellia-192-cfb1" +#define NID_camellia_192_cfb1 761 + +#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1" +#define LN_camellia_256_cfb1 "camellia-256-cfb1" +#define NID_camellia_256_cfb1 762 + +#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8" +#define LN_camellia_128_cfb8 "camellia-128-cfb8" +#define NID_camellia_128_cfb8 763 + +#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8" +#define LN_camellia_192_cfb8 "camellia-192-cfb8" +#define NID_camellia_192_cfb8 764 + +#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8" +#define LN_camellia_256_cfb8 "camellia-256-cfb8" +#define NID_camellia_256_cfb8 765 + +#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB" +#define LN_camellia_128_ofb128 "camellia-128-ofb" +#define NID_camellia_128_ofb128 766 +#define OBJ_camellia_128_ofb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 3L + +#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB" +#define LN_camellia_192_ofb128 "camellia-192-ofb" +#define NID_camellia_192_ofb128 767 +#define OBJ_camellia_192_ofb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 23L + +#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB" +#define LN_camellia_256_ofb128 "camellia-256-ofb" +#define NID_camellia_256_ofb128 768 +#define OBJ_camellia_256_ofb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 43L + +#define SN_subject_directory_attributes "subjectDirectoryAttributes" +#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes" +#define NID_subject_directory_attributes 769 +#define OBJ_subject_directory_attributes 2L, 5L, 29L, 9L + +#define SN_issuing_distribution_point "issuingDistributionPoint" +#define LN_issuing_distribution_point "X509v3 Issuing Distribution Point" +#define NID_issuing_distribution_point 770 +#define OBJ_issuing_distribution_point 2L, 5L, 29L, 28L + +#define SN_certificate_issuer "certificateIssuer" +#define LN_certificate_issuer "X509v3 Certificate Issuer" +#define NID_certificate_issuer 771 +#define OBJ_certificate_issuer 2L, 5L, 29L, 29L + +#define SN_kisa "KISA" +#define LN_kisa "kisa" +#define NID_kisa 773 +#define OBJ_kisa 1L, 2L, 410L, 200004L + +#define SN_seed_ecb "SEED-ECB" +#define LN_seed_ecb "seed-ecb" +#define NID_seed_ecb 776 +#define OBJ_seed_ecb 1L, 2L, 410L, 200004L, 1L, 3L + +#define SN_seed_cbc "SEED-CBC" +#define LN_seed_cbc "seed-cbc" +#define NID_seed_cbc 777 +#define OBJ_seed_cbc 1L, 2L, 410L, 200004L, 1L, 4L + +#define SN_seed_ofb128 "SEED-OFB" +#define LN_seed_ofb128 "seed-ofb" +#define NID_seed_ofb128 778 +#define OBJ_seed_ofb128 1L, 2L, 410L, 200004L, 1L, 6L + +#define SN_seed_cfb128 "SEED-CFB" +#define LN_seed_cfb128 "seed-cfb" +#define NID_seed_cfb128 779 +#define OBJ_seed_cfb128 1L, 2L, 410L, 200004L, 1L, 5L + +#define SN_hmac_md5 "HMAC-MD5" +#define LN_hmac_md5 "hmac-md5" +#define NID_hmac_md5 780 +#define OBJ_hmac_md5 1L, 3L, 6L, 1L, 5L, 5L, 8L, 1L, 1L + +#define SN_hmac_sha1 "HMAC-SHA1" +#define LN_hmac_sha1 "hmac-sha1" +#define NID_hmac_sha1 781 +#define OBJ_hmac_sha1 1L, 3L, 6L, 1L, 5L, 5L, 8L, 1L, 2L + +#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC" +#define LN_id_PasswordBasedMAC "password based MAC" +#define NID_id_PasswordBasedMAC 782 +#define OBJ_id_PasswordBasedMAC 1L, 2L, 840L, 113533L, 7L, 66L, 13L + +#define SN_id_DHBasedMac "id-DHBasedMac" +#define LN_id_DHBasedMac "Diffie-Hellman based MAC" +#define NID_id_DHBasedMac 783 +#define OBJ_id_DHBasedMac 1L, 2L, 840L, 113533L, 7L, 66L, 30L + +#define SN_id_it_suppLangTags "id-it-suppLangTags" +#define NID_id_it_suppLangTags 784 +#define OBJ_id_it_suppLangTags 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 16L + +#define SN_caRepository "caRepository" +#define LN_caRepository "CA Repository" +#define NID_caRepository 785 +#define OBJ_caRepository 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 5L + +#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData" +#define NID_id_smime_ct_compressedData 786 +#define OBJ_id_smime_ct_compressedData \ + 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 9L + +#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF" +#define NID_id_ct_asciiTextWithCRLF 787 +#define OBJ_id_ct_asciiTextWithCRLF 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 27L + +#define SN_id_aes128_wrap "id-aes128-wrap" +#define NID_id_aes128_wrap 788 +#define OBJ_id_aes128_wrap 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 5L + +#define SN_id_aes192_wrap "id-aes192-wrap" +#define NID_id_aes192_wrap 789 +#define OBJ_id_aes192_wrap 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 25L + +#define SN_id_aes256_wrap "id-aes256-wrap" +#define NID_id_aes256_wrap 790 +#define OBJ_id_aes256_wrap 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 45L + +#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended" +#define NID_ecdsa_with_Recommended 791 +#define OBJ_ecdsa_with_Recommended 1L, 2L, 840L, 10045L, 4L, 2L + +#define SN_ecdsa_with_Specified "ecdsa-with-Specified" +#define NID_ecdsa_with_Specified 792 +#define OBJ_ecdsa_with_Specified 1L, 2L, 840L, 10045L, 4L, 3L + +#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224" +#define NID_ecdsa_with_SHA224 793 +#define OBJ_ecdsa_with_SHA224 1L, 2L, 840L, 10045L, 4L, 3L, 1L + +#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256" +#define NID_ecdsa_with_SHA256 794 +#define OBJ_ecdsa_with_SHA256 1L, 2L, 840L, 10045L, 4L, 3L, 2L + +#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384" +#define NID_ecdsa_with_SHA384 795 +#define OBJ_ecdsa_with_SHA384 1L, 2L, 840L, 10045L, 4L, 3L, 3L + +#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512" +#define NID_ecdsa_with_SHA512 796 +#define OBJ_ecdsa_with_SHA512 1L, 2L, 840L, 10045L, 4L, 3L, 4L + +#define LN_hmacWithMD5 "hmacWithMD5" +#define NID_hmacWithMD5 797 +#define OBJ_hmacWithMD5 1L, 2L, 840L, 113549L, 2L, 6L + +#define LN_hmacWithSHA224 "hmacWithSHA224" +#define NID_hmacWithSHA224 798 +#define OBJ_hmacWithSHA224 1L, 2L, 840L, 113549L, 2L, 8L + +#define LN_hmacWithSHA256 "hmacWithSHA256" +#define NID_hmacWithSHA256 799 +#define OBJ_hmacWithSHA256 1L, 2L, 840L, 113549L, 2L, 9L + +#define LN_hmacWithSHA384 "hmacWithSHA384" +#define NID_hmacWithSHA384 800 +#define OBJ_hmacWithSHA384 1L, 2L, 840L, 113549L, 2L, 10L + +#define LN_hmacWithSHA512 "hmacWithSHA512" +#define NID_hmacWithSHA512 801 +#define OBJ_hmacWithSHA512 1L, 2L, 840L, 113549L, 2L, 11L + +#define SN_dsa_with_SHA224 "dsa_with_SHA224" +#define NID_dsa_with_SHA224 802 +#define OBJ_dsa_with_SHA224 2L, 16L, 840L, 1L, 101L, 3L, 4L, 3L, 1L + +#define SN_dsa_with_SHA256 "dsa_with_SHA256" +#define NID_dsa_with_SHA256 803 +#define OBJ_dsa_with_SHA256 2L, 16L, 840L, 1L, 101L, 3L, 4L, 3L, 2L + +#define SN_whirlpool "whirlpool" +#define NID_whirlpool 804 +#define OBJ_whirlpool 1L, 0L, 10118L, 3L, 0L, 55L + +#define SN_cryptopro "cryptopro" +#define NID_cryptopro 805 +#define OBJ_cryptopro 1L, 2L, 643L, 2L, 2L + +#define SN_cryptocom "cryptocom" +#define NID_cryptocom 806 +#define OBJ_cryptocom 1L, 2L, 643L, 2L, 9L + +#define SN_id_GostR3411_94_with_GostR3410_2001 \ + "id-GostR3411-94-with-GostR3410-2001" +#define LN_id_GostR3411_94_with_GostR3410_2001 \ + "GOST R 34.11-94 with GOST R 34.10-2001" +#define NID_id_GostR3411_94_with_GostR3410_2001 807 +#define OBJ_id_GostR3411_94_with_GostR3410_2001 1L, 2L, 643L, 2L, 2L, 3L + +#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94" +#define LN_id_GostR3411_94_with_GostR3410_94 \ + "GOST R 34.11-94 with GOST R 34.10-94" +#define NID_id_GostR3411_94_with_GostR3410_94 808 +#define OBJ_id_GostR3411_94_with_GostR3410_94 1L, 2L, 643L, 2L, 2L, 4L + +#define SN_id_GostR3411_94 "md_gost94" +#define LN_id_GostR3411_94 "GOST R 34.11-94" +#define NID_id_GostR3411_94 809 +#define OBJ_id_GostR3411_94 1L, 2L, 643L, 2L, 2L, 9L + +#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94" +#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94" +#define NID_id_HMACGostR3411_94 810 +#define OBJ_id_HMACGostR3411_94 1L, 2L, 643L, 2L, 2L, 10L + +#define SN_id_GostR3410_2001 "gost2001" +#define LN_id_GostR3410_2001 "GOST R 34.10-2001" +#define NID_id_GostR3410_2001 811 +#define OBJ_id_GostR3410_2001 1L, 2L, 643L, 2L, 2L, 19L + +#define SN_id_GostR3410_94 "gost94" +#define LN_id_GostR3410_94 "GOST R 34.10-94" +#define NID_id_GostR3410_94 812 +#define OBJ_id_GostR3410_94 1L, 2L, 643L, 2L, 2L, 20L + +#define SN_id_Gost28147_89 "gost89" +#define LN_id_Gost28147_89 "GOST 28147-89" +#define NID_id_Gost28147_89 813 +#define OBJ_id_Gost28147_89 1L, 2L, 643L, 2L, 2L, 21L + +#define SN_gost89_cnt "gost89-cnt" +#define NID_gost89_cnt 814 + +#define SN_id_Gost28147_89_MAC "gost-mac" +#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC" +#define NID_id_Gost28147_89_MAC 815 +#define OBJ_id_Gost28147_89_MAC 1L, 2L, 643L, 2L, 2L, 22L + +#define SN_id_GostR3411_94_prf "prf-gostr3411-94" +#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF" +#define NID_id_GostR3411_94_prf 816 +#define OBJ_id_GostR3411_94_prf 1L, 2L, 643L, 2L, 2L, 23L + +#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH" +#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH" +#define NID_id_GostR3410_2001DH 817 +#define OBJ_id_GostR3410_2001DH 1L, 2L, 643L, 2L, 2L, 98L + +#define SN_id_GostR3410_94DH "id-GostR3410-94DH" +#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH" +#define NID_id_GostR3410_94DH 818 +#define OBJ_id_GostR3410_94DH 1L, 2L, 643L, 2L, 2L, 99L + +#define SN_id_Gost28147_89_CryptoPro_KeyMeshing \ + "id-Gost28147-89-CryptoPro-KeyMeshing" +#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819 +#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing 1L, 2L, 643L, 2L, 2L, 14L, 1L + +#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing" +#define NID_id_Gost28147_89_None_KeyMeshing 820 +#define OBJ_id_Gost28147_89_None_KeyMeshing 1L, 2L, 643L, 2L, 2L, 14L, 0L + +#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet" +#define NID_id_GostR3411_94_TestParamSet 821 +#define OBJ_id_GostR3411_94_TestParamSet 1L, 2L, 643L, 2L, 2L, 30L, 0L + +#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet" +#define NID_id_GostR3411_94_CryptoProParamSet 822 +#define OBJ_id_GostR3411_94_CryptoProParamSet 1L, 2L, 643L, 2L, 2L, 30L, 1L + +#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet" +#define NID_id_Gost28147_89_TestParamSet 823 +#define OBJ_id_Gost28147_89_TestParamSet 1L, 2L, 643L, 2L, 2L, 31L, 0L + +#define SN_id_Gost28147_89_CryptoPro_A_ParamSet \ + "id-Gost28147-89-CryptoPro-A-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824 +#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet 1L, 2L, 643L, 2L, 2L, 31L, 1L + +#define SN_id_Gost28147_89_CryptoPro_B_ParamSet \ + "id-Gost28147-89-CryptoPro-B-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825 +#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet 1L, 2L, 643L, 2L, 2L, 31L, 2L + +#define SN_id_Gost28147_89_CryptoPro_C_ParamSet \ + "id-Gost28147-89-CryptoPro-C-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826 +#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet 1L, 2L, 643L, 2L, 2L, 31L, 3L + +#define SN_id_Gost28147_89_CryptoPro_D_ParamSet \ + "id-Gost28147-89-CryptoPro-D-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827 +#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet 1L, 2L, 643L, 2L, 2L, 31L, 4L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet \ + "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet \ + 1L, 2L, 643L, 2L, 2L, 31L, 5L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet \ + "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet \ + 1L, 2L, 643L, 2L, 2L, 31L, 6L + +#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet \ + "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830 +#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet \ + 1L, 2L, 643L, 2L, 2L, 31L, 7L + +#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet" +#define NID_id_GostR3410_94_TestParamSet 831 +#define OBJ_id_GostR3410_94_TestParamSet 1L, 2L, 643L, 2L, 2L, 32L, 0L + +#define SN_id_GostR3410_94_CryptoPro_A_ParamSet \ + "id-GostR3410-94-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832 +#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet 1L, 2L, 643L, 2L, 2L, 32L, 2L + +#define SN_id_GostR3410_94_CryptoPro_B_ParamSet \ + "id-GostR3410-94-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833 +#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet 1L, 2L, 643L, 2L, 2L, 32L, 3L + +#define SN_id_GostR3410_94_CryptoPro_C_ParamSet \ + "id-GostR3410-94-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834 +#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet 1L, 2L, 643L, 2L, 2L, 32L, 4L + +#define SN_id_GostR3410_94_CryptoPro_D_ParamSet \ + "id-GostR3410-94-CryptoPro-D-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835 +#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet 1L, 2L, 643L, 2L, 2L, 32L, 5L + +#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet \ + "id-GostR3410-94-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836 +#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet \ + 1L, 2L, 643L, 2L, 2L, 33L, 1L + +#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet \ + "id-GostR3410-94-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837 +#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet \ + 1L, 2L, 643L, 2L, 2L, 33L, 2L + +#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet \ + "id-GostR3410-94-CryptoPro-XchC-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838 +#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet \ + 1L, 2L, 643L, 2L, 2L, 33L, 3L + +#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet" +#define NID_id_GostR3410_2001_TestParamSet 839 +#define OBJ_id_GostR3410_2001_TestParamSet 1L, 2L, 643L, 2L, 2L, 35L, 0L + +#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet \ + "id-GostR3410-2001-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840 +#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet 1L, 2L, 643L, 2L, 2L, 35L, 1L + +#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet \ + "id-GostR3410-2001-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841 +#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet 1L, 2L, 643L, 2L, 2L, 35L, 2L + +#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet \ + "id-GostR3410-2001-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842 +#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet 1L, 2L, 643L, 2L, 2L, 35L, 3L + +#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet \ + "id-GostR3410-2001-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843 +#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet \ + 1L, 2L, 643L, 2L, 2L, 36L, 0L + +#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet \ + "id-GostR3410-2001-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844 +#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet \ + 1L, 2L, 643L, 2L, 2L, 36L, 1L + +#define SN_id_GostR3410_94_a "id-GostR3410-94-a" +#define NID_id_GostR3410_94_a 845 +#define OBJ_id_GostR3410_94_a 1L, 2L, 643L, 2L, 2L, 20L, 1L + +#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis" +#define NID_id_GostR3410_94_aBis 846 +#define OBJ_id_GostR3410_94_aBis 1L, 2L, 643L, 2L, 2L, 20L, 2L + +#define SN_id_GostR3410_94_b "id-GostR3410-94-b" +#define NID_id_GostR3410_94_b 847 +#define OBJ_id_GostR3410_94_b 1L, 2L, 643L, 2L, 2L, 20L, 3L + +#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis" +#define NID_id_GostR3410_94_bBis 848 +#define OBJ_id_GostR3410_94_bBis 1L, 2L, 643L, 2L, 2L, 20L, 4L + +#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc" +#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet" +#define NID_id_Gost28147_89_cc 849 +#define OBJ_id_Gost28147_89_cc 1L, 2L, 643L, 2L, 9L, 1L, 6L, 1L + +#define SN_id_GostR3410_94_cc "gost94cc" +#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom" +#define NID_id_GostR3410_94_cc 850 +#define OBJ_id_GostR3410_94_cc 1L, 2L, 643L, 2L, 9L, 1L, 5L, 3L + +#define SN_id_GostR3410_2001_cc "gost2001cc" +#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom" +#define NID_id_GostR3410_2001_cc 851 +#define OBJ_id_GostR3410_2001_cc 1L, 2L, 643L, 2L, 9L, 1L, 5L, 4L + +#define SN_id_GostR3411_94_with_GostR3410_94_cc \ + "id-GostR3411-94-with-GostR3410-94-cc" +#define LN_id_GostR3411_94_with_GostR3410_94_cc \ + "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_94_cc 852 +#define OBJ_id_GostR3411_94_with_GostR3410_94_cc \ + 1L, 2L, 643L, 2L, 9L, 1L, 3L, 3L + +#define SN_id_GostR3411_94_with_GostR3410_2001_cc \ + "id-GostR3411-94-with-GostR3410-2001-cc" +#define LN_id_GostR3411_94_with_GostR3410_2001_cc \ + "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853 +#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc \ + 1L, 2L, 643L, 2L, 9L, 1L, 3L, 4L + +#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc" +#define LN_id_GostR3410_2001_ParamSet_cc \ + "GOST R 3410-2001 Parameter Set Cryptocom" +#define NID_id_GostR3410_2001_ParamSet_cc 854 +#define OBJ_id_GostR3410_2001_ParamSet_cc 1L, 2L, 643L, 2L, 9L, 1L, 8L, 1L + +#define SN_hmac "HMAC" +#define LN_hmac "hmac" +#define NID_hmac 855 + +#define SN_LocalKeySet "LocalKeySet" +#define LN_LocalKeySet "Microsoft Local Key set" +#define NID_LocalKeySet 856 +#define OBJ_LocalKeySet 1L, 3L, 6L, 1L, 4L, 1L, 311L, 17L, 2L + +#define SN_freshest_crl "freshestCRL" +#define LN_freshest_crl "X509v3 Freshest CRL" +#define NID_freshest_crl 857 +#define OBJ_freshest_crl 2L, 5L, 29L, 46L + +#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier" +#define LN_id_on_permanentIdentifier "Permanent Identifier" +#define NID_id_on_permanentIdentifier 858 +#define OBJ_id_on_permanentIdentifier 1L, 3L, 6L, 1L, 5L, 5L, 7L, 8L, 3L + +#define LN_searchGuide "searchGuide" +#define NID_searchGuide 859 +#define OBJ_searchGuide 2L, 5L, 4L, 14L + +#define LN_businessCategory "businessCategory" +#define NID_businessCategory 860 +#define OBJ_businessCategory 2L, 5L, 4L, 15L + +#define LN_postalAddress "postalAddress" +#define NID_postalAddress 861 +#define OBJ_postalAddress 2L, 5L, 4L, 16L + +#define LN_postOfficeBox "postOfficeBox" +#define NID_postOfficeBox 862 +#define OBJ_postOfficeBox 2L, 5L, 4L, 18L + +#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName" +#define NID_physicalDeliveryOfficeName 863 +#define OBJ_physicalDeliveryOfficeName 2L, 5L, 4L, 19L + +#define LN_telephoneNumber "telephoneNumber" +#define NID_telephoneNumber 864 +#define OBJ_telephoneNumber 2L, 5L, 4L, 20L + +#define LN_telexNumber "telexNumber" +#define NID_telexNumber 865 +#define OBJ_telexNumber 2L, 5L, 4L, 21L + +#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier" +#define NID_teletexTerminalIdentifier 866 +#define OBJ_teletexTerminalIdentifier 2L, 5L, 4L, 22L + +#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber" +#define NID_facsimileTelephoneNumber 867 +#define OBJ_facsimileTelephoneNumber 2L, 5L, 4L, 23L + +#define LN_x121Address "x121Address" +#define NID_x121Address 868 +#define OBJ_x121Address 2L, 5L, 4L, 24L + +#define LN_internationaliSDNNumber "internationaliSDNNumber" +#define NID_internationaliSDNNumber 869 +#define OBJ_internationaliSDNNumber 2L, 5L, 4L, 25L + +#define LN_registeredAddress "registeredAddress" +#define NID_registeredAddress 870 +#define OBJ_registeredAddress 2L, 5L, 4L, 26L + +#define LN_destinationIndicator "destinationIndicator" +#define NID_destinationIndicator 871 +#define OBJ_destinationIndicator 2L, 5L, 4L, 27L + +#define LN_preferredDeliveryMethod "preferredDeliveryMethod" +#define NID_preferredDeliveryMethod 872 +#define OBJ_preferredDeliveryMethod 2L, 5L, 4L, 28L + +#define LN_presentationAddress "presentationAddress" +#define NID_presentationAddress 873 +#define OBJ_presentationAddress 2L, 5L, 4L, 29L + +#define LN_supportedApplicationContext "supportedApplicationContext" +#define NID_supportedApplicationContext 874 +#define OBJ_supportedApplicationContext 2L, 5L, 4L, 30L + +#define SN_member "member" +#define NID_member 875 +#define OBJ_member 2L, 5L, 4L, 31L + +#define SN_owner "owner" +#define NID_owner 876 +#define OBJ_owner 2L, 5L, 4L, 32L + +#define LN_roleOccupant "roleOccupant" +#define NID_roleOccupant 877 +#define OBJ_roleOccupant 2L, 5L, 4L, 33L + +#define SN_seeAlso "seeAlso" +#define NID_seeAlso 878 +#define OBJ_seeAlso 2L, 5L, 4L, 34L + +#define LN_userPassword "userPassword" +#define NID_userPassword 879 +#define OBJ_userPassword 2L, 5L, 4L, 35L + +#define LN_userCertificate "userCertificate" +#define NID_userCertificate 880 +#define OBJ_userCertificate 2L, 5L, 4L, 36L + +#define LN_cACertificate "cACertificate" +#define NID_cACertificate 881 +#define OBJ_cACertificate 2L, 5L, 4L, 37L + +#define LN_authorityRevocationList "authorityRevocationList" +#define NID_authorityRevocationList 882 +#define OBJ_authorityRevocationList 2L, 5L, 4L, 38L + +#define LN_certificateRevocationList "certificateRevocationList" +#define NID_certificateRevocationList 883 +#define OBJ_certificateRevocationList 2L, 5L, 4L, 39L + +#define LN_crossCertificatePair "crossCertificatePair" +#define NID_crossCertificatePair 884 +#define OBJ_crossCertificatePair 2L, 5L, 4L, 40L + +#define LN_enhancedSearchGuide "enhancedSearchGuide" +#define NID_enhancedSearchGuide 885 +#define OBJ_enhancedSearchGuide 2L, 5L, 4L, 47L + +#define LN_protocolInformation "protocolInformation" +#define NID_protocolInformation 886 +#define OBJ_protocolInformation 2L, 5L, 4L, 48L + +#define LN_distinguishedName "distinguishedName" +#define NID_distinguishedName 887 +#define OBJ_distinguishedName 2L, 5L, 4L, 49L + +#define LN_uniqueMember "uniqueMember" +#define NID_uniqueMember 888 +#define OBJ_uniqueMember 2L, 5L, 4L, 50L + +#define LN_houseIdentifier "houseIdentifier" +#define NID_houseIdentifier 889 +#define OBJ_houseIdentifier 2L, 5L, 4L, 51L + +#define LN_supportedAlgorithms "supportedAlgorithms" +#define NID_supportedAlgorithms 890 +#define OBJ_supportedAlgorithms 2L, 5L, 4L, 52L + +#define LN_deltaRevocationList "deltaRevocationList" +#define NID_deltaRevocationList 891 +#define OBJ_deltaRevocationList 2L, 5L, 4L, 53L + +#define SN_dmdName "dmdName" +#define NID_dmdName 892 +#define OBJ_dmdName 2L, 5L, 4L, 54L + +#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK" +#define NID_id_alg_PWRI_KEK 893 +#define OBJ_id_alg_PWRI_KEK 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 9L + +#define SN_cmac "CMAC" +#define LN_cmac "cmac" +#define NID_cmac 894 + +#define SN_aes_128_gcm "id-aes128-GCM" +#define LN_aes_128_gcm "aes-128-gcm" +#define NID_aes_128_gcm 895 +#define OBJ_aes_128_gcm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 6L + +#define SN_aes_128_ccm "id-aes128-CCM" +#define LN_aes_128_ccm "aes-128-ccm" +#define NID_aes_128_ccm 896 +#define OBJ_aes_128_ccm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 7L + +#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad" +#define NID_id_aes128_wrap_pad 897 +#define OBJ_id_aes128_wrap_pad 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 8L + +#define SN_aes_192_gcm "id-aes192-GCM" +#define LN_aes_192_gcm "aes-192-gcm" +#define NID_aes_192_gcm 898 +#define OBJ_aes_192_gcm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 26L + +#define SN_aes_192_ccm "id-aes192-CCM" +#define LN_aes_192_ccm "aes-192-ccm" +#define NID_aes_192_ccm 899 +#define OBJ_aes_192_ccm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 27L + +#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad" +#define NID_id_aes192_wrap_pad 900 +#define OBJ_id_aes192_wrap_pad 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 28L + +#define SN_aes_256_gcm "id-aes256-GCM" +#define LN_aes_256_gcm "aes-256-gcm" +#define NID_aes_256_gcm 901 +#define OBJ_aes_256_gcm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 46L + +#define SN_aes_256_ccm "id-aes256-CCM" +#define LN_aes_256_ccm "aes-256-ccm" +#define NID_aes_256_ccm 902 +#define OBJ_aes_256_ccm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 47L + +#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad" +#define NID_id_aes256_wrap_pad 903 +#define OBJ_id_aes256_wrap_pad 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 48L + +#define SN_aes_128_ctr "AES-128-CTR" +#define LN_aes_128_ctr "aes-128-ctr" +#define NID_aes_128_ctr 904 + +#define SN_aes_192_ctr "AES-192-CTR" +#define LN_aes_192_ctr "aes-192-ctr" +#define NID_aes_192_ctr 905 + +#define SN_aes_256_ctr "AES-256-CTR" +#define LN_aes_256_ctr "aes-256-ctr" +#define NID_aes_256_ctr 906 + +#define SN_id_camellia128_wrap "id-camellia128-wrap" +#define NID_id_camellia128_wrap 907 +#define OBJ_id_camellia128_wrap 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 3L, 2L + +#define SN_id_camellia192_wrap "id-camellia192-wrap" +#define NID_id_camellia192_wrap 908 +#define OBJ_id_camellia192_wrap 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 3L, 3L + +#define SN_id_camellia256_wrap "id-camellia256-wrap" +#define NID_id_camellia256_wrap 909 +#define OBJ_id_camellia256_wrap 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 3L, 4L + +#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage" +#define LN_anyExtendedKeyUsage "Any Extended Key Usage" +#define NID_anyExtendedKeyUsage 910 +#define OBJ_anyExtendedKeyUsage 2L, 5L, 29L, 37L, 0L + +#define SN_mgf1 "MGF1" +#define LN_mgf1 "mgf1" +#define NID_mgf1 911 +#define OBJ_mgf1 1L, 2L, 840L, 113549L, 1L, 1L, 8L + +#define SN_rsassaPss "RSASSA-PSS" +#define LN_rsassaPss "rsassaPss" +#define NID_rsassaPss 912 +#define OBJ_rsassaPss 1L, 2L, 840L, 113549L, 1L, 1L, 10L + +#define SN_aes_128_xts "AES-128-XTS" +#define LN_aes_128_xts "aes-128-xts" +#define NID_aes_128_xts 913 + +#define SN_aes_256_xts "AES-256-XTS" +#define LN_aes_256_xts "aes-256-xts" +#define NID_aes_256_xts 914 + +#define SN_rc4_hmac_md5 "RC4-HMAC-MD5" +#define LN_rc4_hmac_md5 "rc4-hmac-md5" +#define NID_rc4_hmac_md5 915 + +#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1" +#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1" +#define NID_aes_128_cbc_hmac_sha1 916 + +#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1" +#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1" +#define NID_aes_192_cbc_hmac_sha1 917 + +#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1" +#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1" +#define NID_aes_256_cbc_hmac_sha1 918 + +#define SN_rsaesOaep "RSAES-OAEP" +#define LN_rsaesOaep "rsaesOaep" +#define NID_rsaesOaep 919 +#define OBJ_rsaesOaep 1L, 2L, 840L, 113549L, 1L, 1L, 7L + +#define SN_dhpublicnumber "dhpublicnumber" +#define LN_dhpublicnumber "X9.42 DH" +#define NID_dhpublicnumber 920 +#define OBJ_dhpublicnumber 1L, 2L, 840L, 10046L, 2L, 1L + +#define SN_brainpoolP160r1 "brainpoolP160r1" +#define NID_brainpoolP160r1 921 +#define OBJ_brainpoolP160r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 1L + +#define SN_brainpoolP160t1 "brainpoolP160t1" +#define NID_brainpoolP160t1 922 +#define OBJ_brainpoolP160t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 2L + +#define SN_brainpoolP192r1 "brainpoolP192r1" +#define NID_brainpoolP192r1 923 +#define OBJ_brainpoolP192r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 3L + +#define SN_brainpoolP192t1 "brainpoolP192t1" +#define NID_brainpoolP192t1 924 +#define OBJ_brainpoolP192t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 4L + +#define SN_brainpoolP224r1 "brainpoolP224r1" +#define NID_brainpoolP224r1 925 +#define OBJ_brainpoolP224r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 5L + +#define SN_brainpoolP224t1 "brainpoolP224t1" +#define NID_brainpoolP224t1 926 +#define OBJ_brainpoolP224t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 6L + +#define SN_brainpoolP256r1 "brainpoolP256r1" +#define NID_brainpoolP256r1 927 +#define OBJ_brainpoolP256r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 7L + +#define SN_brainpoolP256t1 "brainpoolP256t1" +#define NID_brainpoolP256t1 928 +#define OBJ_brainpoolP256t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 8L + +#define SN_brainpoolP320r1 "brainpoolP320r1" +#define NID_brainpoolP320r1 929 +#define OBJ_brainpoolP320r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 9L + +#define SN_brainpoolP320t1 "brainpoolP320t1" +#define NID_brainpoolP320t1 930 +#define OBJ_brainpoolP320t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 10L + +#define SN_brainpoolP384r1 "brainpoolP384r1" +#define NID_brainpoolP384r1 931 +#define OBJ_brainpoolP384r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 11L + +#define SN_brainpoolP384t1 "brainpoolP384t1" +#define NID_brainpoolP384t1 932 +#define OBJ_brainpoolP384t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 12L + +#define SN_brainpoolP512r1 "brainpoolP512r1" +#define NID_brainpoolP512r1 933 +#define OBJ_brainpoolP512r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 13L + +#define SN_brainpoolP512t1 "brainpoolP512t1" +#define NID_brainpoolP512t1 934 +#define OBJ_brainpoolP512t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 14L + +#define SN_pSpecified "PSPECIFIED" +#define LN_pSpecified "pSpecified" +#define NID_pSpecified 935 +#define OBJ_pSpecified 1L, 2L, 840L, 113549L, 1L, 1L, 9L + +#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme" +#define NID_dhSinglePass_stdDH_sha1kdf_scheme 936 +#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme \ + 1L, 3L, 133L, 16L, 840L, 63L, 0L, 2L + +#define SN_dhSinglePass_stdDH_sha224kdf_scheme \ + "dhSinglePass-stdDH-sha224kdf-scheme" +#define NID_dhSinglePass_stdDH_sha224kdf_scheme 937 +#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1L, 3L, 132L, 1L, 11L, 0L + +#define SN_dhSinglePass_stdDH_sha256kdf_scheme \ + "dhSinglePass-stdDH-sha256kdf-scheme" +#define NID_dhSinglePass_stdDH_sha256kdf_scheme 938 +#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1L, 3L, 132L, 1L, 11L, 1L + +#define SN_dhSinglePass_stdDH_sha384kdf_scheme \ + "dhSinglePass-stdDH-sha384kdf-scheme" +#define NID_dhSinglePass_stdDH_sha384kdf_scheme 939 +#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1L, 3L, 132L, 1L, 11L, 2L + +#define SN_dhSinglePass_stdDH_sha512kdf_scheme \ + "dhSinglePass-stdDH-sha512kdf-scheme" +#define NID_dhSinglePass_stdDH_sha512kdf_scheme 940 +#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1L, 3L, 132L, 1L, 11L, 3L + +#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme \ + "dhSinglePass-cofactorDH-sha1kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 941 +#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme \ + 1L, 3L, 133L, 16L, 840L, 63L, 0L, 3L + +#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme \ + "dhSinglePass-cofactorDH-sha224kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 942 +#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1L, 3L, 132L, 1L, 14L, 0L + +#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme \ + "dhSinglePass-cofactorDH-sha256kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 943 +#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1L, 3L, 132L, 1L, 14L, 1L + +#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme \ + "dhSinglePass-cofactorDH-sha384kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 944 +#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1L, 3L, 132L, 1L, 14L, 2L + +#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme \ + "dhSinglePass-cofactorDH-sha512kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 945 +#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme 1L, 3L, 132L, 1L, 14L, 3L + +#define SN_dh_std_kdf "dh-std-kdf" +#define NID_dh_std_kdf 946 + +#define SN_dh_cofactor_kdf "dh-cofactor-kdf" +#define NID_dh_cofactor_kdf 947 + +#define SN_X25519 "X25519" +#define NID_X25519 948 +#define OBJ_X25519 1L, 3L, 101L, 110L + +#define SN_ED25519 "ED25519" +#define NID_ED25519 949 +#define OBJ_ED25519 1L, 3L, 101L, 112L + +#define SN_chacha20_poly1305 "ChaCha20-Poly1305" +#define LN_chacha20_poly1305 "chacha20-poly1305" +#define NID_chacha20_poly1305 950 + +#define SN_kx_rsa "KxRSA" +#define LN_kx_rsa "kx-rsa" +#define NID_kx_rsa 951 + +#define SN_kx_ecdhe "KxECDHE" +#define LN_kx_ecdhe "kx-ecdhe" +#define NID_kx_ecdhe 952 + +#define SN_kx_psk "KxPSK" +#define LN_kx_psk "kx-psk" +#define NID_kx_psk 953 + +#define SN_auth_rsa "AuthRSA" +#define LN_auth_rsa "auth-rsa" +#define NID_auth_rsa 954 + +#define SN_auth_ecdsa "AuthECDSA" +#define LN_auth_ecdsa "auth-ecdsa" +#define NID_auth_ecdsa 955 + +#define SN_auth_psk "AuthPSK" +#define LN_auth_psk "auth-psk" +#define NID_auth_psk 956 + +#define SN_kx_any "KxANY" +#define LN_kx_any "kx-any" +#define NID_kx_any 957 + +#define SN_auth_any "AuthANY" +#define LN_auth_any "auth-any" +#define NID_auth_any 958 + +#define SN_ED448 "ED448" +#define NID_ED448 960 +#define OBJ_ED448 1L, 3L, 101L, 113L + +#define SN_X448 "X448" +#define NID_X448 961 +#define OBJ_X448 1L, 3L, 101L, 111L + +#define SN_sha512_256 "SHA512-256" +#define LN_sha512_256 "sha512-256" +#define NID_sha512_256 962 +#define OBJ_sha512_256 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 6L + +#define SN_hkdf "HKDF" +#define LN_hkdf "hkdf" +#define NID_hkdf 963 + +#define SN_X25519Kyber768Draft00 "X25519Kyber768Draft00" +#define NID_X25519Kyber768Draft00 964 + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_NID_H */ diff --git a/lib/boringssl/include/openssl/obj.h b/lib/boringssl/include/openssl/obj.h new file mode 100644 index 00000000..3fb8bdeb --- /dev/null +++ b/lib/boringssl/include/openssl/obj.h @@ -0,0 +1,263 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_OBJ_H +#define OPENSSL_HEADER_OBJ_H + +#include + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// The objects library deals with the registration and indexing of ASN.1 object +// identifiers. These values are often written as a dotted sequence of numbers, +// e.g. 1.2.840.113549.1.9.16.3.9. +// +// Internally, OpenSSL likes to deal with these values by numbering them with +// numbers called "nids". OpenSSL has a large, built-in database of common +// object identifiers and also has both short and long names for them. +// +// This library provides functions for translating between object identifiers, +// nids, short names and long names. +// +// The nid values should not be used outside of a single process: they are not +// stable identifiers. + + +// Basic operations. + +// OBJ_dup returns a duplicate copy of |obj| or NULL on allocation failure. The +// caller must call |ASN1_OBJECT_free| on the result to release it. +OPENSSL_EXPORT ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *obj); + +// OBJ_cmp returns a value less than, equal to or greater than zero if |a| is +// less than, equal to or greater than |b|, respectively. +OPENSSL_EXPORT int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); + +// OBJ_get0_data returns a pointer to the DER representation of |obj|. This is +// the contents of the DER-encoded identifier, not including the tag and length. +// If |obj| does not have an associated object identifier (i.e. it is a nid-only +// value), this value is the empty string. +OPENSSL_EXPORT const uint8_t *OBJ_get0_data(const ASN1_OBJECT *obj); + +// OBJ_length returns the length of the DER representation of |obj|. This is the +// contents of the DER-encoded identifier, not including the tag and length. If +// |obj| does not have an associated object identifier (i.e. it is a nid-only +// value), this value is the empty string. +OPENSSL_EXPORT size_t OBJ_length(const ASN1_OBJECT *obj); + + +// Looking up nids. + +// OBJ_obj2nid returns the nid corresponding to |obj|, or |NID_undef| if no +// such object is known. +OPENSSL_EXPORT int OBJ_obj2nid(const ASN1_OBJECT *obj); + +// OBJ_cbs2nid returns the nid corresponding to the DER data in |cbs|, or +// |NID_undef| if no such object is known. +OPENSSL_EXPORT int OBJ_cbs2nid(const CBS *cbs); + +// OBJ_sn2nid returns the nid corresponding to |short_name|, or |NID_undef| if +// no such short name is known. +OPENSSL_EXPORT int OBJ_sn2nid(const char *short_name); + +// OBJ_ln2nid returns the nid corresponding to |long_name|, or |NID_undef| if +// no such long name is known. +OPENSSL_EXPORT int OBJ_ln2nid(const char *long_name); + +// OBJ_txt2nid returns the nid corresponding to |s|, which may be a short name, +// long name, or an ASCII string containing a dotted sequence of numbers. It +// returns the nid or NID_undef if unknown. +OPENSSL_EXPORT int OBJ_txt2nid(const char *s); + + +// Getting information about nids. + +// OBJ_nid2obj returns the |ASN1_OBJECT| corresponding to |nid|, or NULL if +// |nid| is unknown. +// +// Although the output is not const, this function returns a static, immutable +// |ASN1_OBJECT|. It is not necessary to release the object with +// |ASN1_OBJECT_free|. +// +// However, functions like |X509_ALGOR_set0| expect to take ownership of a +// possibly dynamically-allocated |ASN1_OBJECT|. |ASN1_OBJECT_free| is a no-op +// for static |ASN1_OBJECT|s, so |OBJ_nid2obj| is compatible with such +// functions. +// +// Callers are encouraged to store the result of this function in a const +// pointer. However, if using functions like |X509_ALGOR_set0|, callers may use +// a non-const pointer and manage ownership. +OPENSSL_EXPORT ASN1_OBJECT *OBJ_nid2obj(int nid); + +// OBJ_nid2sn returns the short name for |nid|, or NULL if |nid| is unknown. +OPENSSL_EXPORT const char *OBJ_nid2sn(int nid); + +// OBJ_nid2ln returns the long name for |nid|, or NULL if |nid| is unknown. +OPENSSL_EXPORT const char *OBJ_nid2ln(int nid); + +// OBJ_nid2cbb writes |nid| as an ASN.1 OBJECT IDENTIFIER to |out|. It returns +// one on success or zero otherwise. +OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid); + + +// Dealing with textual representations of object identifiers. + +// OBJ_txt2obj returns an ASN1_OBJECT for the textual representation in |s|. +// If |dont_search_names| is zero, then |s| will be matched against the long +// and short names of a known objects to find a match. Otherwise |s| must +// contain an ASCII string with a dotted sequence of numbers. The resulting +// object need not be previously known. It returns a freshly allocated +// |ASN1_OBJECT| or NULL on error. +OPENSSL_EXPORT ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names); + +// OBJ_obj2txt converts |obj| to a textual representation. If +// |always_return_oid| is zero then |obj| will be matched against known objects +// and the long (preferably) or short name will be used if found. Otherwise +// |obj| will be converted into a dotted sequence of integers. If |out| is not +// NULL, then at most |out_len| bytes of the textual form will be written +// there. If |out_len| is at least one, then string written to |out| will +// always be NUL terminated. It returns the number of characters that could +// have been written, not including the final NUL, or -1 on error. +OPENSSL_EXPORT int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, + int always_return_oid); + + +// Adding objects at runtime. + +// OBJ_create adds a known object and returns the NID of the new object, or +// NID_undef on error. +// +// WARNING: This function modifies global state. The table cannot contain +// duplicate OIDs, short names, or long names. If two callers in the same +// address space add conflicting values, only one registration will take effect. +// Avoid this function if possible. Instead, callers can process OIDs unknown to +// BoringSSL by acting on the byte representation directly. See |OBJ_get0_data| +// and |OBJ_length|. +OPENSSL_EXPORT int OBJ_create(const char *oid, const char *short_name, + const char *long_name); + + +// Handling signature algorithm identifiers. +// +// Some NIDs (e.g. sha256WithRSAEncryption) specify both a digest algorithm and +// a public key algorithm. The following functions map between pairs of digest +// and public-key algorithms and the NIDs that specify their combination. +// +// Sometimes the combination NID leaves the digest unspecified (e.g. +// rsassaPss). In these cases, the digest NID is |NID_undef|. + +// OBJ_find_sigid_algs finds the digest and public-key NIDs that correspond to +// the signing algorithm |sign_nid|. If successful, it sets |*out_digest_nid| +// and |*out_pkey_nid| and returns one. Otherwise it returns zero. Any of +// |out_digest_nid| or |out_pkey_nid| can be NULL if the caller doesn't need +// that output value. +OPENSSL_EXPORT int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, + int *out_pkey_nid); + +// OBJ_find_sigid_by_algs finds the signature NID that corresponds to the +// combination of |digest_nid| and |pkey_nid|. If success, it sets +// |*out_sign_nid| and returns one. Otherwise it returns zero. The +// |out_sign_nid| argument can be NULL if the caller only wishes to learn +// whether the combination is valid. +OPENSSL_EXPORT int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid, + int pkey_nid); + + +// Deprecated functions. + +typedef struct obj_name_st { + int type; + int alias; + const char *name; + const char *data; +} OBJ_NAME; + +#define OBJ_NAME_TYPE_MD_METH 1 +#define OBJ_NAME_TYPE_CIPHER_METH 2 + +// OBJ_NAME_do_all_sorted calls |callback| zero or more times, each time with +// the name of a different primitive. If |type| is |OBJ_NAME_TYPE_MD_METH| then +// the primitives will be hash functions, alternatively if |type| is +// |OBJ_NAME_TYPE_CIPHER_METH| then the primitives will be ciphers or cipher +// modes. +// +// This function is ill-specified and should never be used. +OPENSSL_EXPORT void OBJ_NAME_do_all_sorted( + int type, void (*callback)(const OBJ_NAME *, void *arg), void *arg); + +// OBJ_NAME_do_all calls |OBJ_NAME_do_all_sorted|. +OPENSSL_EXPORT void OBJ_NAME_do_all(int type, void (*callback)(const OBJ_NAME *, + void *arg), + void *arg); + +// OBJ_cleanup does nothing. +OPENSSL_EXPORT void OBJ_cleanup(void); + + +#if defined(__cplusplus) +} // extern C +#endif + +#define OBJ_R_UNKNOWN_NID 100 +#define OBJ_R_INVALID_OID_STRING 101 + +#endif // OPENSSL_HEADER_OBJ_H diff --git a/lib/boringssl/include/openssl/obj_mac.h b/lib/boringssl/include/openssl/obj_mac.h new file mode 100644 index 00000000..e7ccadc1 --- /dev/null +++ b/lib/boringssl/include/openssl/obj_mac.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "nid.h" diff --git a/lib/boringssl/include/openssl/objects.h b/lib/boringssl/include/openssl/objects.h new file mode 100644 index 00000000..dd6556f2 --- /dev/null +++ b/lib/boringssl/include/openssl/objects.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "obj.h" diff --git a/lib/boringssl/include/openssl/opensslconf.h b/lib/boringssl/include/openssl/opensslconf.h new file mode 100644 index 00000000..51657030 --- /dev/null +++ b/lib/boringssl/include/openssl/opensslconf.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#ifndef OPENSSL_HEADER_OPENSSLCONF_H +#define OPENSSL_HEADER_OPENSSLCONF_H + + +#define OPENSSL_NO_ASYNC +#define OPENSSL_NO_BF +#define OPENSSL_NO_BLAKE2 +#define OPENSSL_NO_BUF_FREELISTS +#define OPENSSL_NO_CAMELLIA +#define OPENSSL_NO_CAPIENG +#define OPENSSL_NO_CAST +#define OPENSSL_NO_CMS +#define OPENSSL_NO_COMP +#define OPENSSL_NO_CT +#define OPENSSL_NO_DANE +#define OPENSSL_NO_DEPRECATED +#define OPENSSL_NO_DGRAM +#define OPENSSL_NO_DYNAMIC_ENGINE +#define OPENSSL_NO_EC_NISTP_64_GCC_128 +#define OPENSSL_NO_EC2M +#define OPENSSL_NO_EGD +#define OPENSSL_NO_ENGINE +#define OPENSSL_NO_GMP +#define OPENSSL_NO_GOST +#define OPENSSL_NO_HEARTBEATS +#define OPENSSL_NO_HW +#define OPENSSL_NO_IDEA +#define OPENSSL_NO_JPAKE +#define OPENSSL_NO_KRB5 +#define OPENSSL_NO_MD2 +#define OPENSSL_NO_MDC2 +#define OPENSSL_NO_OCB +#define OPENSSL_NO_OCSP +#define OPENSSL_NO_RC2 +#define OPENSSL_NO_RC5 +#define OPENSSL_NO_RFC3779 +#define OPENSSL_NO_RIPEMD +#define OPENSSL_NO_RMD160 +#define OPENSSL_NO_SCTP +#define OPENSSL_NO_SEED +#define OPENSSL_NO_SM2 +#define OPENSSL_NO_SM3 +#define OPENSSL_NO_SM4 +#define OPENSSL_NO_SRP +#define OPENSSL_NO_SSL_TRACE +#define OPENSSL_NO_SSL2 +#define OPENSSL_NO_SSL3 +#define OPENSSL_NO_SSL3_METHOD +#define OPENSSL_NO_STATIC_ENGINE +#define OPENSSL_NO_STORE +#define OPENSSL_NO_WHIRLPOOL + + +#endif // OPENSSL_HEADER_OPENSSLCONF_H diff --git a/lib/boringssl/include/openssl/opensslv.h b/lib/boringssl/include/openssl/opensslv.h new file mode 100644 index 00000000..a3555d4f --- /dev/null +++ b/lib/boringssl/include/openssl/opensslv.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "crypto.h" diff --git a/lib/boringssl/include/openssl/ossl_typ.h b/lib/boringssl/include/openssl/ossl_typ.h new file mode 100644 index 00000000..c2b3fe7c --- /dev/null +++ b/lib/boringssl/include/openssl/ossl_typ.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "base.h" diff --git a/lib/boringssl/include/openssl/pem.h b/lib/boringssl/include/openssl/pem.h new file mode 100644 index 00000000..21885ba3 --- /dev/null +++ b/lib/boringssl/include/openssl/pem.h @@ -0,0 +1,476 @@ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_PEM_H +#define OPENSSL_HEADER_PEM_H + +#include +#include +#include +#include +#include +#include +#include +#include + +// For compatibility with open-iscsi, which assumes that it can get +// |OPENSSL_malloc| from pem.h or err.h +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define PEM_BUFSIZE 1024 + +#define PEM_STRING_X509_OLD "X509 CERTIFICATE" +#define PEM_STRING_X509 "CERTIFICATE" +#define PEM_STRING_X509_PAIR "CERTIFICATE PAIR" +#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" +#define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" +#define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" +#define PEM_STRING_X509_CRL "X509 CRL" +#define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" +#define PEM_STRING_PUBLIC "PUBLIC KEY" +#define PEM_STRING_RSA "RSA PRIVATE KEY" +#define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" +#define PEM_STRING_DSA "DSA PRIVATE KEY" +#define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY" +#define PEM_STRING_EC "EC PRIVATE KEY" +#define PEM_STRING_PKCS7 "PKCS7" +#define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA" +#define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY" +#define PEM_STRING_PKCS8INF "PRIVATE KEY" +#define PEM_STRING_DHPARAMS "DH PARAMETERS" +#define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS" +#define PEM_STRING_DSAPARAMS "DSA PARAMETERS" +#define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY" +#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY" +#define PEM_STRING_CMS "CMS" + +// enc_type is one off +#define PEM_TYPE_ENCRYPTED 10 +#define PEM_TYPE_MIC_ONLY 20 +#define PEM_TYPE_MIC_CLEAR 30 +#define PEM_TYPE_CLEAR 40 + +// These macros make the PEM_read/PEM_write functions easier to maintain and +// write. Now they are all implemented with either: +// IMPLEMENT_PEM_rw(...) or IMPLEMENT_PEM_rw_cb(...) + + +#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ + static void *pem_read_##name##_d2i(void **x, const unsigned char **inp, \ + long len) { \ + return d2i_##asn1((type **)x, inp, len); \ + } \ + OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **x, \ + pem_password_cb *cb, void *u) { \ + return (type *)PEM_ASN1_read(pem_read_##name##_d2i, str, fp, (void **)x, \ + cb, u); \ + } + +#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ + static int pem_write_##name##_i2d(const void *x, unsigned char **outp) { \ + return i2d_##asn1((type *)x, outp); \ + } \ + OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x) { \ + return PEM_ASN1_write(pem_write_##name##_i2d, str, fp, x, NULL, NULL, 0, \ + NULL, NULL); \ + } + +#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \ + static int pem_write_##name##_i2d(const void *x, unsigned char **outp) { \ + return i2d_##asn1((const type *)x, outp); \ + } \ + OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *x) { \ + return PEM_ASN1_write(pem_write_##name##_i2d, str, fp, (void *)x, NULL, \ + NULL, 0, NULL, NULL); \ + } + +#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \ + static int pem_write_##name##_i2d(const void *x, unsigned char **outp) { \ + return i2d_##asn1((type *)x, outp); \ + } \ + OPENSSL_EXPORT int PEM_write_##name( \ + FILE *fp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \ + pem_password_cb *cb, void *u) { \ + return PEM_ASN1_write(pem_write_##name##_i2d, str, fp, x, enc, kstr, klen, \ + cb, u); \ + } + +#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \ + static int pem_write_##name##_i2d(const void *x, unsigned char **outp) { \ + return i2d_##asn1((const type *)x, outp); \ + } \ + OPENSSL_EXPORT int PEM_write_##name( \ + FILE *fp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \ + pem_password_cb *cb, void *u) { \ + return PEM_ASN1_write(pem_write_##name##_i2d, str, fp, x, enc, kstr, klen, \ + cb, u); \ + } + + +#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + static void *pem_read_bio_##name##_d2i(void **x, const unsigned char **inp, \ + long len) { \ + return d2i_##asn1((type **)x, inp, len); \ + } \ + OPENSSL_EXPORT type *PEM_read_bio_##name(BIO *bp, type **x, \ + pem_password_cb *cb, void *u) { \ + return (type *)PEM_ASN1_read_bio(pem_read_bio_##name##_d2i, str, bp, \ + (void **)x, cb, u); \ + } + +#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ + static int pem_write_bio_##name##_i2d(const void *x, unsigned char **outp) { \ + return i2d_##asn1((type *)x, outp); \ + } \ + OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x) { \ + return PEM_ASN1_write_bio(pem_write_bio_##name##_i2d, str, bp, x, NULL, \ + NULL, 0, NULL, NULL); \ + } + +#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ + static int pem_write_bio_##name##_i2d(const void *x, unsigned char **outp) { \ + return i2d_##asn1((const type *)x, outp); \ + } \ + OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, const type *x) { \ + return PEM_ASN1_write_bio(pem_write_bio_##name##_i2d, str, bp, (void *)x, \ + NULL, NULL, 0, NULL, NULL); \ + } + +#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ + static int pem_write_bio_##name##_i2d(const void *x, unsigned char **outp) { \ + return i2d_##asn1((type *)x, outp); \ + } \ + OPENSSL_EXPORT int PEM_write_bio_##name( \ + BIO *bp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \ + pem_password_cb *cb, void *u) { \ + return PEM_ASN1_write_bio(pem_write_bio_##name##_i2d, str, bp, x, enc, \ + kstr, klen, cb, u); \ + } + +#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ + static int pem_write_bio_##name##_i2d(const void *x, unsigned char **outp) { \ + return i2d_##asn1((const type *)x, outp); \ + } \ + OPENSSL_EXPORT int PEM_write_bio_##name( \ + BIO *bp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \ + pem_password_cb *cb, void *u) { \ + return PEM_ASN1_write_bio(pem_write_bio_##name##_i2d, str, bp, (void *)x, \ + enc, kstr, klen, cb, u); \ + } + +#define IMPLEMENT_PEM_write(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_read_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb(name, type, str, asn1) + +// These are the same except they are for the declarations + +#define DECLARE_PEM_read_fp(name, type) \ + OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **x, \ + pem_password_cb *cb, void *u); + +#define DECLARE_PEM_write_fp(name, type) \ + OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x); + +#define DECLARE_PEM_write_fp_const(name, type) \ + OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *x); + +#define DECLARE_PEM_write_cb_fp(name, type) \ + OPENSSL_EXPORT int PEM_write_##name( \ + FILE *fp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \ + pem_password_cb *cb, void *u); + +#define DECLARE_PEM_read_bio(name, type) \ + OPENSSL_EXPORT type *PEM_read_bio_##name(BIO *bp, type **x, \ + pem_password_cb *cb, void *u); + +#define DECLARE_PEM_write_bio(name, type) \ + OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x); + +#define DECLARE_PEM_write_bio_const(name, type) \ + OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, const type *x); + +#define DECLARE_PEM_write_cb_bio(name, type) \ + OPENSSL_EXPORT int PEM_write_bio_##name( \ + BIO *bp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \ + pem_password_cb *cb, void *u); + + +#define DECLARE_PEM_write(name, type) \ + DECLARE_PEM_write_bio(name, type) \ + DECLARE_PEM_write_fp(name, type) + +#define DECLARE_PEM_write_const(name, type) \ + DECLARE_PEM_write_bio_const(name, type) \ + DECLARE_PEM_write_fp_const(name, type) + +#define DECLARE_PEM_write_cb(name, type) \ + DECLARE_PEM_write_cb_bio(name, type) \ + DECLARE_PEM_write_cb_fp(name, type) + +#define DECLARE_PEM_read(name, type) \ + DECLARE_PEM_read_bio(name, type) \ + DECLARE_PEM_read_fp(name, type) + +#define DECLARE_PEM_rw(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write(name, type) + +#define DECLARE_PEM_rw_const(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_const(name, type) + +#define DECLARE_PEM_rw_cb(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_cb(name, type) + +// "userdata": new with OpenSSL 0.9.4 +typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata); + +OPENSSL_EXPORT int PEM_get_EVP_CIPHER_INFO(char *header, + EVP_CIPHER_INFO *cipher); +OPENSSL_EXPORT int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, + long *len, pem_password_cb *callback, void *u); + +// PEM_read_bio reads from |bp|, until the next PEM block. If one is found, it +// returns one and sets |*name|, |*header|, and |*data| to newly-allocated +// buffers containing the PEM type, the header block, and the decoded data, +// respectively. |*name| and |*header| are NUL-terminated C strings, while +// |*data| has |*len| bytes. The caller must release each of |*name|, |*header|, +// and |*data| with |OPENSSL_free| when done. If no PEM block is found, this +// function returns zero and pushes |PEM_R_NO_START_LINE| to the error queue. If +// one is found, but there is an error decoding it, it returns zero and pushes +// some other error to the error queue. +OPENSSL_EXPORT int PEM_read_bio(BIO *bp, char **name, char **header, + unsigned char **data, long *len); + +// PEM_write_bio writes a PEM block to |bp|, containing |len| bytes from |data| +// as data. |name| and |hdr| are NUL-terminated C strings containing the PEM +// type and header block, respectively. This function returns zero on error and +// the number of bytes written on success. +OPENSSL_EXPORT int PEM_write_bio(BIO *bp, const char *name, const char *hdr, + const unsigned char *data, long len); + +OPENSSL_EXPORT int PEM_bytes_read_bio(unsigned char **pdata, long *plen, + char **pnm, const char *name, BIO *bp, + pem_password_cb *cb, void *u); +OPENSSL_EXPORT void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, + BIO *bp, void **x, pem_password_cb *cb, + void *u); +OPENSSL_EXPORT int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, + BIO *bp, void *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); + +OPENSSL_EXPORT STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio( + BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u); + +OPENSSL_EXPORT int PEM_read(FILE *fp, char **name, char **header, + unsigned char **data, long *len); +OPENSSL_EXPORT int PEM_write(FILE *fp, const char *name, const char *hdr, + const unsigned char *data, long len); +OPENSSL_EXPORT void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, + void **x, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, + void *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *callback, void *u); +OPENSSL_EXPORT STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, + STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, + void *u); + +// PEM_def_callback treats |userdata| as a string and copies it into |buf|, +// assuming its |size| is sufficient. Returns the length of the string, or 0 +// if there is not enough room. If either |buf| or |userdata| is NULL, 0 is +// returned. Note that this is different from OpenSSL, which prompts for a +// password. +OPENSSL_EXPORT int PEM_def_callback(char *buf, int size, int rwflag, + void *userdata); + + +DECLARE_PEM_rw(X509, X509) + +DECLARE_PEM_rw(X509_AUX, X509) + +DECLARE_PEM_rw(X509_REQ, X509_REQ) +DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) + +DECLARE_PEM_rw(X509_CRL, X509_CRL) + +DECLARE_PEM_rw(PKCS7, PKCS7) +DECLARE_PEM_rw(PKCS8, X509_SIG) + +DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) + +DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) + +DECLARE_PEM_rw_const(RSAPublicKey, RSA) +DECLARE_PEM_rw(RSA_PUBKEY, RSA) + +#ifndef OPENSSL_NO_DSA + +DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) + +DECLARE_PEM_rw(DSA_PUBKEY, DSA) + +DECLARE_PEM_rw_const(DSAparams, DSA) + +#endif + +DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY) +DECLARE_PEM_rw(EC_PUBKEY, EC_KEY) + + +DECLARE_PEM_rw_const(DHparams, DH) + + +DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) + +DECLARE_PEM_rw(PUBKEY, EVP_PKEY) + +OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, const EVP_PKEY *x, + int nid, char *kstr, + int klen, + pem_password_cb *cb, + void *u); +OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey(BIO *, const EVP_PKEY *, + const EVP_CIPHER *, char *, + int, pem_password_cb *, + void *); +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_bio(BIO *bp, const EVP_PKEY *x, + const EVP_CIPHER *enc, char *kstr, + int klen, pem_password_cb *cb, + void *u); +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, const EVP_PKEY *x, + int nid, char *kstr, int klen, + pem_password_cb *cb, void *u); +OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, + pem_password_cb *cb, void *u); + +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_fp(FILE *fp, const EVP_PKEY *x, + const EVP_CIPHER *enc, char *kstr, + int klen, pem_password_cb *cb, + void *u); +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, const EVP_PKEY *x, + int nid, char *kstr, int klen, + pem_password_cb *cb, void *u); +OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey_nid(FILE *fp, const EVP_PKEY *x, + int nid, char *kstr, int klen, + pem_password_cb *cb, void *u); + +OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, + pem_password_cb *cb, void *u); + +OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey(FILE *fp, const EVP_PKEY *x, + const EVP_CIPHER *enc, char *kstr, + int klen, pem_password_cb *cd, + void *u); + + +#ifdef __cplusplus +} +#endif + +#define PEM_R_BAD_BASE64_DECODE 100 +#define PEM_R_BAD_DECRYPT 101 +#define PEM_R_BAD_END_LINE 102 +#define PEM_R_BAD_IV_CHARS 103 +#define PEM_R_BAD_PASSWORD_READ 104 +#define PEM_R_CIPHER_IS_NULL 105 +#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 106 +#define PEM_R_NOT_DEK_INFO 107 +#define PEM_R_NOT_ENCRYPTED 108 +#define PEM_R_NOT_PROC_TYPE 109 +#define PEM_R_NO_START_LINE 110 +#define PEM_R_READ_KEY 111 +#define PEM_R_SHORT_HEADER 112 +#define PEM_R_UNSUPPORTED_CIPHER 113 +#define PEM_R_UNSUPPORTED_ENCRYPTION 114 + +#endif // OPENSSL_HEADER_PEM_H diff --git a/lib/boringssl/include/openssl/pkcs12.h b/lib/boringssl/include/openssl/pkcs12.h new file mode 100644 index 00000000..b5e95163 --- /dev/null +++ b/lib/boringssl/include/openssl/pkcs12.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "pkcs8.h" diff --git a/lib/boringssl/include/openssl/pkcs7.h b/lib/boringssl/include/openssl/pkcs7.h new file mode 100644 index 00000000..85f2a4ec --- /dev/null +++ b/lib/boringssl/include/openssl/pkcs7.h @@ -0,0 +1,239 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_PKCS7_H +#define OPENSSL_HEADER_PKCS7_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// PKCS#7. +// +// This library contains functions for extracting information from PKCS#7 +// structures (RFC 2315). + +DECLARE_STACK_OF(CRYPTO_BUFFER) +DECLARE_STACK_OF(X509) +DECLARE_STACK_OF(X509_CRL) + +// PKCS7_get_raw_certificates parses a PKCS#7, SignedData structure from |cbs| +// and appends the included certificates to |out_certs|. It returns one on +// success and zero on error. |cbs| is advanced passed the structure. +// +// Note that a SignedData structure may contain no certificates, in which case +// this function succeeds but does not append any certificates. Additionally, +// certificates in SignedData structures are unordered. Callers should not +// assume a particular order in |*out_certs| and may need to search for matches +// or run path-building algorithms. +OPENSSL_EXPORT int PKCS7_get_raw_certificates( + STACK_OF(CRYPTO_BUFFER) *out_certs, CBS *cbs, CRYPTO_BUFFER_POOL *pool); + +// PKCS7_get_certificates behaves like |PKCS7_get_raw_certificates| but parses +// them into |X509| objects. +OPENSSL_EXPORT int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs); + +// PKCS7_bundle_raw_certificates appends a PKCS#7, SignedData structure +// containing |certs| to |out|. It returns one on success and zero on error. +// Note that certificates in SignedData structures are unordered. The order in +// |certs| will not be preserved. +OPENSSL_EXPORT int PKCS7_bundle_raw_certificates( + CBB *out, const STACK_OF(CRYPTO_BUFFER) *certs); + +// PKCS7_bundle_certificates behaves like |PKCS7_bundle_raw_certificates| but +// takes |X509| objects as input. +OPENSSL_EXPORT int PKCS7_bundle_certificates( + CBB *out, const STACK_OF(X509) *certs); + +// PKCS7_get_CRLs parses a PKCS#7, SignedData structure from |cbs| and appends +// the included CRLs to |out_crls|. It returns one on success and zero on error. +// |cbs| is advanced passed the structure. +// +// Note that a SignedData structure may contain no CRLs, in which case this +// function succeeds but does not append any CRLs. Additionally, CRLs in +// SignedData structures are unordered. Callers should not assume an order in +// |*out_crls| and may need to search for matches. +OPENSSL_EXPORT int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs); + +// PKCS7_bundle_CRLs appends a PKCS#7, SignedData structure containing +// |crls| to |out|. It returns one on success and zero on error. Note that CRLs +// in SignedData structures are unordered. The order in |crls| will not be +// preserved. +OPENSSL_EXPORT int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls); + +// PKCS7_get_PEM_certificates reads a PEM-encoded, PKCS#7, SignedData structure +// from |pem_bio| and appends the included certificates to |out_certs|. It +// returns one on success and zero on error. +// +// Note that a SignedData structure may contain no certificates, in which case +// this function succeeds but does not append any certificates. Additionally, +// certificates in SignedData structures are unordered. Callers should not +// assume a particular order in |*out_certs| and may need to search for matches +// or run path-building algorithms. +OPENSSL_EXPORT int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, + BIO *pem_bio); + +// PKCS7_get_PEM_CRLs reads a PEM-encoded, PKCS#7, SignedData structure from +// |pem_bio| and appends the included CRLs to |out_crls|. It returns one on +// success and zero on error. +// +// Note that a SignedData structure may contain no CRLs, in which case this +// function succeeds but does not append any CRLs. Additionally, CRLs in +// SignedData structures are unordered. Callers should not assume an order in +// |*out_crls| and may need to search for matches. +OPENSSL_EXPORT int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, + BIO *pem_bio); + + +// Deprecated functions. +// +// These functions are a compatibility layer over a subset of OpenSSL's PKCS#7 +// API. It intentionally does not implement the whole thing, only the minimum +// needed to build cryptography.io. + +typedef struct { + STACK_OF(X509) *cert; + STACK_OF(X509_CRL) *crl; +} PKCS7_SIGNED; + +typedef struct { + STACK_OF(X509) *cert; + STACK_OF(X509_CRL) *crl; +} PKCS7_SIGN_ENVELOPE; + +typedef void PKCS7_ENVELOPE; +typedef void PKCS7_DIGEST; +typedef void PKCS7_ENCRYPT; +typedef void PKCS7_SIGNER_INFO; + +typedef struct { + uint8_t *ber_bytes; + size_t ber_len; + + // Unlike OpenSSL, the following fields are immutable. They filled in when the + // object is parsed and ignored in serialization. + ASN1_OBJECT *type; + union { + char *ptr; + ASN1_OCTET_STRING *data; + PKCS7_SIGNED *sign; + PKCS7_ENVELOPE *enveloped; + PKCS7_SIGN_ENVELOPE *signed_and_enveloped; + PKCS7_DIGEST *digest; + PKCS7_ENCRYPT *encrypted; + ASN1_TYPE *other; + } d; +} PKCS7; + +// d2i_PKCS7 parses a BER-encoded, PKCS#7 signed data ContentInfo structure from +// |len| bytes at |*inp|, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp, + size_t len); + +// d2i_PKCS7_bio behaves like |d2i_PKCS7| but reads the input from |bio|. If +// the length of the object is indefinite the full contents of |bio| are read. +// +// If the function fails then some unknown amount of data may have been read +// from |bio|. +OPENSSL_EXPORT PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out); + +// i2d_PKCS7 marshals |p7| as a DER-encoded PKCS#7 ContentInfo structure, as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_PKCS7(const PKCS7 *p7, uint8_t **out); + +// i2d_PKCS7_bio writes |p7| to |bio|. It returns one on success and zero on +// error. +OPENSSL_EXPORT int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7); + +// PKCS7_free releases memory associated with |p7|. +OPENSSL_EXPORT void PKCS7_free(PKCS7 *p7); + +// PKCS7_type_is_data returns zero. +OPENSSL_EXPORT int PKCS7_type_is_data(const PKCS7 *p7); + +// PKCS7_type_is_digest returns zero. +OPENSSL_EXPORT int PKCS7_type_is_digest(const PKCS7 *p7); + +// PKCS7_type_is_encrypted returns zero. +OPENSSL_EXPORT int PKCS7_type_is_encrypted(const PKCS7 *p7); + +// PKCS7_type_is_enveloped returns zero. +OPENSSL_EXPORT int PKCS7_type_is_enveloped(const PKCS7 *p7); + +// PKCS7_type_is_signed returns one. (We only supporte signed data +// ContentInfos.) +OPENSSL_EXPORT int PKCS7_type_is_signed(const PKCS7 *p7); + +// PKCS7_type_is_signedAndEnveloped returns zero. +OPENSSL_EXPORT int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7); + +// PKCS7_DETACHED indicates that the PKCS#7 file specifies its data externally. +#define PKCS7_DETACHED 0x40 + +// The following flags cause |PKCS7_sign| to fail. +#define PKCS7_TEXT 0x1 +#define PKCS7_NOCERTS 0x2 +#define PKCS7_NOSIGS 0x4 +#define PKCS7_NOCHAIN 0x8 +#define PKCS7_NOINTERN 0x10 +#define PKCS7_NOVERIFY 0x20 +#define PKCS7_BINARY 0x80 +#define PKCS7_NOATTR 0x100 +#define PKCS7_NOSMIMECAP 0x200 +#define PKCS7_STREAM 0x1000 +#define PKCS7_PARTIAL 0x4000 + +// PKCS7_sign can operate in two modes to provide some backwards compatibility: +// +// The first mode assembles |certs| into a PKCS#7 signed data ContentInfo with +// external data and no signatures. It returns a newly-allocated |PKCS7| on +// success or NULL on error. |sign_cert| and |pkey| must be NULL. |data| is +// ignored. |flags| must be equal to |PKCS7_DETACHED|. Additionally, +// certificates in SignedData structures are unordered. The order of |certs| +// will not be preserved. +// +// The second mode generates a detached RSA SHA-256 signature of |data| using +// |pkey| and produces a PKCS#7 SignedData structure containing it. |certs| +// must be NULL and |flags| must be exactly |PKCS7_NOATTR | PKCS7_BINARY | +// PKCS7_NOCERTS | PKCS7_DETACHED|. +// +// Note this function only implements a subset of the corresponding OpenSSL +// function. It is provided for backwards compatibility only. +OPENSSL_EXPORT PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, BIO *data, int flags); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(PKCS7, PKCS7_free) + +BSSL_NAMESPACE_END +} // extern C++ +#endif + +#define PKCS7_R_BAD_PKCS7_VERSION 100 +#define PKCS7_R_NOT_PKCS7_SIGNED_DATA 101 +#define PKCS7_R_NO_CERTIFICATES_INCLUDED 102 +#define PKCS7_R_NO_CRLS_INCLUDED 103 + +#endif // OPENSSL_HEADER_PKCS7_H diff --git a/lib/boringssl/include/openssl/pkcs8.h b/lib/boringssl/include/openssl/pkcs8.h new file mode 100644 index 00000000..8774681e --- /dev/null +++ b/lib/boringssl/include/openssl/pkcs8.h @@ -0,0 +1,290 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + + +#ifndef OPENSSL_HEADER_PKCS8_H +#define OPENSSL_HEADER_PKCS8_H + +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +// PKCS8_encrypt serializes and encrypts a PKCS8_PRIV_KEY_INFO with PBES1 or +// PBES2 as defined in PKCS #5. Only pbeWithSHAAnd128BitRC4, +// pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, defined in PKCS +// #12, and PBES2, are supported. PBES2 is selected by setting |cipher| and +// passing -1 for |pbe_nid|. Otherwise, PBES1 is used and |cipher| is ignored. +// +// |pass| is used as the password. If a PBES1 scheme from PKCS #12 is used, this +// will be converted to a raw byte string as specified in B.1 of PKCS #12. If +// |pass| is NULL, it will be encoded as the empty byte string rather than two +// zero bytes, the PKCS #12 encoding of the empty string. +// +// If |salt| is NULL, a random salt of |salt_len| bytes is generated. If +// |salt_len| is zero, a default salt length is used instead. +// +// The resulting structure is stored in an |X509_SIG| which must be freed by the +// caller. +OPENSSL_EXPORT X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int pass_len, + const uint8_t *salt, size_t salt_len, + int iterations, + PKCS8_PRIV_KEY_INFO *p8inf); + +// PKCS8_marshal_encrypted_private_key behaves like |PKCS8_encrypt| but encrypts +// an |EVP_PKEY| and writes the serialized EncryptedPrivateKeyInfo to |out|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int PKCS8_marshal_encrypted_private_key( + CBB *out, int pbe_nid, const EVP_CIPHER *cipher, const char *pass, + size_t pass_len, const uint8_t *salt, size_t salt_len, int iterations, + const EVP_PKEY *pkey); + +// PKCS8_decrypt decrypts and decodes a PKCS8_PRIV_KEY_INFO with PBES1 or PBES2 +// as defined in PKCS #5. Only pbeWithSHAAnd128BitRC4, +// pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, and PBES2, +// defined in PKCS #12, are supported. +// +// |pass| is used as the password. If a PBES1 scheme from PKCS #12 is used, this +// will be converted to a raw byte string as specified in B.1 of PKCS #12. If +// |pass| is NULL, it will be encoded as the empty byte string rather than two +// zero bytes, the PKCS #12 encoding of the empty string. +// +// The resulting structure must be freed by the caller. +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, + const char *pass, + int pass_len); + +// PKCS8_parse_encrypted_private_key behaves like |PKCS8_decrypt| but it parses +// the EncryptedPrivateKeyInfo structure from |cbs| and advances |cbs|. It +// returns a newly-allocated |EVP_PKEY| on success and zero on error. +OPENSSL_EXPORT EVP_PKEY *PKCS8_parse_encrypted_private_key(CBS *cbs, + const char *pass, + size_t pass_len); + +// PKCS12_get_key_and_certs parses a PKCS#12 structure from |in|, authenticates +// and decrypts it using |password|, sets |*out_key| to the included private +// key and appends the included certificates to |out_certs|. It returns one on +// success and zero on error. The caller takes ownership of the outputs. +// Any friendlyName attributes (RFC 2985) in the PKCS#12 structure will be +// returned on the |X509| objects as aliases. See also |X509_alias_get0|. +OPENSSL_EXPORT int PKCS12_get_key_and_certs(EVP_PKEY **out_key, + STACK_OF(X509) *out_certs, + CBS *in, const char *password); + + +// Deprecated functions. + +// PKCS12_PBE_add does nothing. It exists for compatibility with OpenSSL. +OPENSSL_EXPORT void PKCS12_PBE_add(void); + +// d2i_PKCS12 is a dummy function that copies |*ber_bytes| into a +// |PKCS12| structure. The |out_p12| argument should be NULL(✝). On exit, +// |*ber_bytes| will be advanced by |ber_len|. It returns a fresh |PKCS12| +// structure or NULL on error. +// +// Note: unlike other d2i functions, |d2i_PKCS12| will always consume |ber_len| +// bytes. +// +// (✝) If |out_p12| is not NULL and the function is successful, |*out_p12| will +// be freed if not NULL itself and the result will be written to |*out_p12|. +// New code should not depend on this. +OPENSSL_EXPORT PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, + size_t ber_len); + +// d2i_PKCS12_bio acts like |d2i_PKCS12| but reads from a |BIO|. +OPENSSL_EXPORT PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12); + +// d2i_PKCS12_fp acts like |d2i_PKCS12| but reads from a |FILE|. +OPENSSL_EXPORT PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12); + +// i2d_PKCS12 is a dummy function which copies the contents of |p12|. If |out| +// is not NULL then the result is written to |*out| and |*out| is advanced just +// past the output. It returns the number of bytes in the result, whether +// written or not, or a negative value on error. +OPENSSL_EXPORT int i2d_PKCS12(const PKCS12 *p12, uint8_t **out); + +// i2d_PKCS12_bio writes the contents of |p12| to |bio|. It returns one on +// success and zero on error. +OPENSSL_EXPORT int i2d_PKCS12_bio(BIO *bio, const PKCS12 *p12); + +// i2d_PKCS12_fp writes the contents of |p12| to |fp|. It returns one on +// success and zero on error. +OPENSSL_EXPORT int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12); + +// PKCS12_parse calls |PKCS12_get_key_and_certs| on the ASN.1 data stored in +// |p12|. The |out_pkey| and |out_cert| arguments must not be NULL and, on +// successful exit, the private key and matching certificate will be stored in +// them. The |out_ca_certs| argument may be NULL but, if not, then any extra +// certificates will be appended to |*out_ca_certs|. If |*out_ca_certs| is NULL +// then it will be set to a freshly allocated stack containing the extra certs. +// +// Note if |p12| does not contain a private key, both |*out_pkey| and +// |*out_cert| will be set to NULL and all certificates will be returned via +// |*out_ca_certs|. Also note this function differs from OpenSSL in that extra +// certificates are returned in the order they appear in the file. OpenSSL 1.1.1 +// returns them in reverse order, but this will be fixed in OpenSSL 3.0. +// +// It returns one on success and zero on error. +// +// Use |PKCS12_get_key_and_certs| instead. +OPENSSL_EXPORT int PKCS12_parse(const PKCS12 *p12, const char *password, + EVP_PKEY **out_pkey, X509 **out_cert, + STACK_OF(X509) **out_ca_certs); + +// PKCS12_verify_mac returns one if |password| is a valid password for |p12| +// and zero otherwise. Since |PKCS12_parse| doesn't take a length parameter, +// it's not actually possible to use a non-NUL-terminated password to actually +// get anything from a |PKCS12|. Thus |password| and |password_len| may be +// |NULL| and zero, respectively, or else |password_len| may be -1, or else +// |password[password_len]| must be zero and no other NUL bytes may appear in +// |password|. If the |password_len| checks fail, zero is returned +// immediately. +OPENSSL_EXPORT int PKCS12_verify_mac(const PKCS12 *p12, const char *password, + int password_len); + +// PKCS12_DEFAULT_ITER is the default number of KDF iterations used when +// creating a |PKCS12| object. +#define PKCS12_DEFAULT_ITER 2048 + +// PKCS12_create returns a newly-allocated |PKCS12| object containing |pkey|, +// |cert|, and |chain|, encrypted with the specified password. |name|, if not +// NULL, specifies a user-friendly name to encode with the key and +// certificate. The key and certificates are encrypted with |key_nid| and +// |cert_nid|, respectively, using |iterations| iterations in the +// KDF. |mac_iterations| is the number of iterations when deriving the MAC +// key. |key_type| must be zero. |pkey| and |cert| may be NULL to omit them. +// +// Each of |key_nid|, |cert_nid|, |iterations|, and |mac_iterations| may be zero +// to use defaults, which are |NID_pbe_WithSHA1And3_Key_TripleDES_CBC|, +// |NID_pbe_WithSHA1And40BitRC2_CBC|, |PKCS12_DEFAULT_ITER|, and one, +// respectively. +// +// |key_nid| or |cert_nid| may also be -1 to disable encryption of the key or +// certificate, respectively. This option is not recommended and is only +// implemented for compatibility with external packages. Note the output still +// requires a password for the MAC. Unencrypted keys in PKCS#12 are also not +// widely supported and may not open in other implementations. +// +// If |cert| or |chain| have associated aliases (see |X509_alias_set1|), they +// will be included in the output as friendlyName attributes (RFC 2985). It is +// an error to specify both an alias on |cert| and a non-NULL |name| +// parameter. +OPENSSL_EXPORT PKCS12 *PKCS12_create(const char *password, const char *name, + const EVP_PKEY *pkey, X509 *cert, + const STACK_OF(X509) *chain, int key_nid, + int cert_nid, int iterations, + int mac_iterations, int key_type); + +// PKCS12_free frees |p12| and its contents. +OPENSSL_EXPORT void PKCS12_free(PKCS12 *p12); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(PKCS12, PKCS12_free) +BORINGSSL_MAKE_DELETER(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define PKCS8_R_BAD_PKCS12_DATA 100 +#define PKCS8_R_BAD_PKCS12_VERSION 101 +#define PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 102 +#define PKCS8_R_CRYPT_ERROR 103 +#define PKCS8_R_DECODE_ERROR 104 +#define PKCS8_R_ENCODE_ERROR 105 +#define PKCS8_R_ENCRYPT_ERROR 106 +#define PKCS8_R_ERROR_SETTING_CIPHER_PARAMS 107 +#define PKCS8_R_INCORRECT_PASSWORD 108 +#define PKCS8_R_KEYGEN_FAILURE 109 +#define PKCS8_R_KEY_GEN_ERROR 110 +#define PKCS8_R_METHOD_NOT_SUPPORTED 111 +#define PKCS8_R_MISSING_MAC 112 +#define PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12 113 +#define PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED 114 +#define PKCS8_R_PKCS12_TOO_DEEPLY_NESTED 115 +#define PKCS8_R_PRIVATE_KEY_DECODE_ERROR 116 +#define PKCS8_R_PRIVATE_KEY_ENCODE_ERROR 117 +#define PKCS8_R_TOO_LONG 118 +#define PKCS8_R_UNKNOWN_ALGORITHM 119 +#define PKCS8_R_UNKNOWN_CIPHER 120 +#define PKCS8_R_UNKNOWN_CIPHER_ALGORITHM 121 +#define PKCS8_R_UNKNOWN_DIGEST 122 +#define PKCS8_R_UNKNOWN_HASH 123 +#define PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 124 +#define PKCS8_R_UNSUPPORTED_KEYLENGTH 125 +#define PKCS8_R_UNSUPPORTED_SALT_TYPE 126 +#define PKCS8_R_UNSUPPORTED_CIPHER 127 +#define PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 128 +#define PKCS8_R_BAD_ITERATION_COUNT 129 +#define PKCS8_R_UNSUPPORTED_PRF 130 +#define PKCS8_R_INVALID_CHARACTERS 131 +#define PKCS8_R_UNSUPPORTED_OPTIONS 132 +#define PKCS8_R_AMBIGUOUS_FRIENDLY_NAME 133 + +#endif // OPENSSL_HEADER_PKCS8_H diff --git a/lib/boringssl/include/openssl/poly1305.h b/lib/boringssl/include/openssl/poly1305.h new file mode 100644 index 00000000..a38ef217 --- /dev/null +++ b/lib/boringssl/include/openssl/poly1305.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_POLY1305_H +#define OPENSSL_HEADER_POLY1305_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef uint8_t poly1305_state[512]; + +// CRYPTO_poly1305_init sets up |state| so that it can be used to calculate an +// authentication tag with the one-time key |key|. Note that |key| is a +// one-time key and therefore there is no `reset' method because that would +// enable several messages to be authenticated with the same key. +OPENSSL_EXPORT void CRYPTO_poly1305_init(poly1305_state *state, + const uint8_t key[32]); + +// CRYPTO_poly1305_update processes |in_len| bytes from |in|. It can be called +// zero or more times after poly1305_init. +OPENSSL_EXPORT void CRYPTO_poly1305_update(poly1305_state *state, + const uint8_t *in, size_t in_len); + +// CRYPTO_poly1305_finish completes the poly1305 calculation and writes a 16 +// byte authentication tag to |mac|. +OPENSSL_EXPORT void CRYPTO_poly1305_finish(poly1305_state *state, + uint8_t mac[16]); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_POLY1305_H diff --git a/lib/boringssl/include/openssl/pool.h b/lib/boringssl/include/openssl/pool.h new file mode 100644 index 00000000..c61a4bab --- /dev/null +++ b/lib/boringssl/include/openssl/pool.h @@ -0,0 +1,108 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_POOL_H +#define OPENSSL_HEADER_POOL_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Buffers and buffer pools. +// +// |CRYPTO_BUFFER|s are simply reference-counted blobs. A |CRYPTO_BUFFER_POOL| +// is an intern table for |CRYPTO_BUFFER|s. This allows for a single copy of a +// given blob to be kept in memory and referenced from multiple places. + + +DEFINE_STACK_OF(CRYPTO_BUFFER) + +// CRYPTO_BUFFER_POOL_new returns a freshly allocated |CRYPTO_BUFFER_POOL| or +// NULL on error. +OPENSSL_EXPORT CRYPTO_BUFFER_POOL* CRYPTO_BUFFER_POOL_new(void); + +// CRYPTO_BUFFER_POOL_free frees |pool|, which must be empty. +OPENSSL_EXPORT void CRYPTO_BUFFER_POOL_free(CRYPTO_BUFFER_POOL *pool); + +// CRYPTO_BUFFER_new returns a |CRYPTO_BUFFER| containing a copy of |data|, or +// else NULL on error. If |pool| is not NULL then the returned value may be a +// reference to a previously existing |CRYPTO_BUFFER| that contained the same +// data. Otherwise, the returned, fresh |CRYPTO_BUFFER| will be added to the +// pool. +OPENSSL_EXPORT CRYPTO_BUFFER *CRYPTO_BUFFER_new(const uint8_t *data, size_t len, + CRYPTO_BUFFER_POOL *pool); + +// CRYPTO_BUFFER_alloc creates an unpooled |CRYPTO_BUFFER| of the given size and +// writes the underlying data pointer to |*out_data|. It returns NULL on error. +// +// After calling this function, |len| bytes of contents must be written to +// |out_data| before passing the returned pointer to any other BoringSSL +// functions. Once initialized, the |CRYPTO_BUFFER| should be treated as +// immutable. +OPENSSL_EXPORT CRYPTO_BUFFER *CRYPTO_BUFFER_alloc(uint8_t **out_data, + size_t len); + +// CRYPTO_BUFFER_new_from_CBS acts the same as |CRYPTO_BUFFER_new|. +OPENSSL_EXPORT CRYPTO_BUFFER *CRYPTO_BUFFER_new_from_CBS( + const CBS *cbs, CRYPTO_BUFFER_POOL *pool); + +// CRYPTO_BUFFER_new_from_static_data_unsafe behaves like |CRYPTO_BUFFER_new| +// but does not copy |data|. |data| must be immutable and last for the lifetime +// of the address space. +OPENSSL_EXPORT CRYPTO_BUFFER *CRYPTO_BUFFER_new_from_static_data_unsafe( + const uint8_t *data, size_t len, CRYPTO_BUFFER_POOL *pool); + +// CRYPTO_BUFFER_free decrements the reference count of |buf|. If there are no +// other references, or if the only remaining reference is from a pool, then +// |buf| will be freed. +OPENSSL_EXPORT void CRYPTO_BUFFER_free(CRYPTO_BUFFER *buf); + +// CRYPTO_BUFFER_up_ref increments the reference count of |buf| and returns +// one. +OPENSSL_EXPORT int CRYPTO_BUFFER_up_ref(CRYPTO_BUFFER *buf); + +// CRYPTO_BUFFER_data returns a pointer to the data contained in |buf|. +OPENSSL_EXPORT const uint8_t *CRYPTO_BUFFER_data(const CRYPTO_BUFFER *buf); + +// CRYPTO_BUFFER_len returns the length, in bytes, of the data contained in +// |buf|. +OPENSSL_EXPORT size_t CRYPTO_BUFFER_len(const CRYPTO_BUFFER *buf); + +// CRYPTO_BUFFER_init_CBS initialises |out| to point at the data from |buf|. +OPENSSL_EXPORT void CRYPTO_BUFFER_init_CBS(const CRYPTO_BUFFER *buf, CBS *out); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(CRYPTO_BUFFER_POOL, CRYPTO_BUFFER_POOL_free) +BORINGSSL_MAKE_DELETER(CRYPTO_BUFFER, CRYPTO_BUFFER_free) +BORINGSSL_MAKE_UP_REF(CRYPTO_BUFFER, CRYPTO_BUFFER_up_ref) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#endif // OPENSSL_HEADER_POOL_H diff --git a/lib/boringssl/include/openssl/rand.h b/lib/boringssl/include/openssl/rand.h new file mode 100644 index 00000000..586274d1 --- /dev/null +++ b/lib/boringssl/include/openssl/rand.h @@ -0,0 +1,125 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_RAND_H +#define OPENSSL_HEADER_RAND_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Random number generation. + + +// RAND_bytes writes |len| bytes of random data to |buf| and returns one. In the +// event that sufficient random data can not be obtained, |abort| is called. +OPENSSL_EXPORT int RAND_bytes(uint8_t *buf, size_t len); + +// RAND_get_system_entropy_for_custom_prng writes |len| bytes of random data +// from a system entropy source to |buf|. The maximum length of entropy which +// may be requested is 256 bytes. If more than 256 bytes of data is requested, +// or if sufficient random data can not be obtained, |abort| is called. +// |RAND_bytes| should normally be used instead of this function. This function +// should only be used for seed values or where |malloc| should not be called +// from BoringSSL. This function is not FIPS compliant. +OPENSSL_EXPORT void RAND_get_system_entropy_for_custom_prng(uint8_t *buf, + size_t len); + +// RAND_cleanup frees any resources used by the RNG. This is not safe if other +// threads might still be calling |RAND_bytes|. +OPENSSL_EXPORT void RAND_cleanup(void); + + +// Obscure functions. + +#if !defined(OPENSSL_WINDOWS) +// RAND_enable_fork_unsafe_buffering enables efficient buffered reading of +// /dev/urandom. It adds an overhead of a few KB of memory per thread. It must +// be called before the first call to |RAND_bytes|. +// +// |fd| must be -1. We no longer support setting the file descriptor with this +// function. +// +// It has an unusual name because the buffer is unsafe across calls to |fork|. +// Hence, this function should never be called by libraries. +OPENSSL_EXPORT void RAND_enable_fork_unsafe_buffering(int fd); +#endif + +#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) +// RAND_reset_for_fuzzing resets the fuzzer-only deterministic RNG. This +// function is only defined in the fuzzer-only build configuration. +OPENSSL_EXPORT void RAND_reset_for_fuzzing(void); +#endif + + +// Deprecated functions + +// RAND_pseudo_bytes is a wrapper around |RAND_bytes|. +OPENSSL_EXPORT int RAND_pseudo_bytes(uint8_t *buf, size_t len); + +// RAND_seed reads a single byte of random data to ensure that any file +// descriptors etc are opened. +OPENSSL_EXPORT void RAND_seed(const void *buf, int num); + +// RAND_load_file returns a nonnegative number. +OPENSSL_EXPORT int RAND_load_file(const char *path, long num); + +// RAND_file_name returns NULL. +OPENSSL_EXPORT const char *RAND_file_name(char *buf, size_t num); + +// RAND_add does nothing. +OPENSSL_EXPORT void RAND_add(const void *buf, int num, double entropy); + +// RAND_egd returns 255. +OPENSSL_EXPORT int RAND_egd(const char *); + +// RAND_poll returns one. +OPENSSL_EXPORT int RAND_poll(void); + +// RAND_status returns one. +OPENSSL_EXPORT int RAND_status(void); + +// rand_meth_st is typedefed to |RAND_METHOD| in base.h. It isn't used; it +// exists only to be the return type of |RAND_SSLeay|. It's +// external so that variables of this type can be initialized. +struct rand_meth_st { + void (*seed) (const void *buf, int num); + int (*bytes) (uint8_t *buf, size_t num); + void (*cleanup) (void); + void (*add) (const void *buf, int num, double entropy); + int (*pseudorand) (uint8_t *buf, size_t num); + int (*status) (void); +}; + +// RAND_SSLeay returns a pointer to a dummy |RAND_METHOD|. +OPENSSL_EXPORT RAND_METHOD *RAND_SSLeay(void); + +// RAND_OpenSSL returns a pointer to a dummy |RAND_METHOD|. +OPENSSL_EXPORT RAND_METHOD *RAND_OpenSSL(void); + +// RAND_get_rand_method returns |RAND_SSLeay()|. +OPENSSL_EXPORT const RAND_METHOD *RAND_get_rand_method(void); + +// RAND_set_rand_method returns one. +OPENSSL_EXPORT int RAND_set_rand_method(const RAND_METHOD *); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_RAND_H diff --git a/lib/boringssl/include/openssl/rc4.h b/lib/boringssl/include/openssl/rc4.h new file mode 100644 index 00000000..acf56ae9 --- /dev/null +++ b/lib/boringssl/include/openssl/rc4.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_RC4_H +#define OPENSSL_HEADER_RC4_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// RC4. + + +struct rc4_key_st { + uint32_t x, y; + uint32_t data[256]; +} /* RC4_KEY */; + +// RC4_set_key performs an RC4 key schedule and initialises |rc4key| with |len| +// bytes of key material from |key|. +OPENSSL_EXPORT void RC4_set_key(RC4_KEY *rc4key, unsigned len, + const uint8_t *key); + +// RC4 encrypts (or decrypts, it's the same with RC4) |len| bytes from |in| to +// |out|. +OPENSSL_EXPORT void RC4(RC4_KEY *key, size_t len, const uint8_t *in, + uint8_t *out); + + +// Deprecated functions. + +// RC4_options returns the string "rc4(ptr,int)". +OPENSSL_EXPORT const char *RC4_options(void); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_RC4_H diff --git a/lib/boringssl/include/openssl/ripemd.h b/lib/boringssl/include/openssl/ripemd.h new file mode 100644 index 00000000..d859b1ff --- /dev/null +++ b/lib/boringssl/include/openssl/ripemd.h @@ -0,0 +1,108 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_RIPEMD_H +#define OPENSSL_HEADER_RIPEMD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +# define RIPEMD160_CBLOCK 64 +# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4) +# define RIPEMD160_DIGEST_LENGTH 20 + +struct RIPEMD160state_st { + uint32_t h[5]; + uint32_t Nl, Nh; + uint8_t data[RIPEMD160_CBLOCK]; + unsigned num; +}; + +// RIPEMD160_Init initialises |ctx| and returns one. +OPENSSL_EXPORT int RIPEMD160_Init(RIPEMD160_CTX *ctx); + +// RIPEMD160_Update adds |len| bytes from |data| to |ctx| and returns one. +OPENSSL_EXPORT int RIPEMD160_Update(RIPEMD160_CTX *ctx, const void *data, + size_t len); + +// RIPEMD160_Final adds the final padding to |ctx| and writes the resulting +// digest to |out|, which must have at least |RIPEMD160_DIGEST_LENGTH| bytes of +// space. It returns one. +OPENSSL_EXPORT int RIPEMD160_Final(uint8_t out[RIPEMD160_DIGEST_LENGTH], + RIPEMD160_CTX *ctx); + +// RIPEMD160 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |RIPEMD160_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *RIPEMD160(const uint8_t *data, size_t len, + uint8_t out[RIPEMD160_DIGEST_LENGTH]); + +// RIPEMD160_Transform is a low-level function that performs a single, +// RIPEMD160 block transformation using the state from |ctx| and 64 bytes from +// |block|. +OPENSSL_EXPORT void RIPEMD160_Transform(RIPEMD160_CTX *ctx, + const uint8_t block[RIPEMD160_CBLOCK]); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_RIPEMD_H diff --git a/lib/boringssl/include/openssl/rsa.h b/lib/boringssl/include/openssl/rsa.h new file mode 100644 index 00000000..9b21d831 --- /dev/null +++ b/lib/boringssl/include/openssl/rsa.h @@ -0,0 +1,948 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_RSA_H +#define OPENSSL_HEADER_RSA_H + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// rsa.h contains functions for handling encryption and signature using RSA. + + +// Allocation and destruction. +// +// An |RSA| object represents a public or private RSA key. A given object may be +// used concurrently on multiple threads by non-mutating functions, provided no +// other thread is concurrently calling a mutating function. Unless otherwise +// documented, functions which take a |const| pointer are non-mutating and +// functions which take a non-|const| pointer are mutating. + +// RSA_new_public_key returns a new |RSA| object containing a public key with +// the specified parameters, or NULL on error or invalid input. +OPENSSL_EXPORT RSA *RSA_new_public_key(const BIGNUM *n, const BIGNUM *e); + +// RSA_new_private_key returns a new |RSA| object containing a private key with +// the specified parameters, or NULL on error or invalid input. All parameters +// are mandatory and may not be NULL. +// +// This function creates standard RSA private keys with CRT parameters. +OPENSSL_EXPORT RSA *RSA_new_private_key(const BIGNUM *n, const BIGNUM *e, + const BIGNUM *d, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, + const BIGNUM *dmq1, const BIGNUM *iqmp); + +// RSA_new returns a new, empty |RSA| object or NULL on error. Prefer using +// |RSA_new_public_key| or |RSA_new_private_key| to import an RSA key. +OPENSSL_EXPORT RSA *RSA_new(void); + +// RSA_new_method acts the same as |RSA_new| but takes an explicit |ENGINE|. +OPENSSL_EXPORT RSA *RSA_new_method(const ENGINE *engine); + +// RSA_free decrements the reference count of |rsa| and frees it if the +// reference count drops to zero. +OPENSSL_EXPORT void RSA_free(RSA *rsa); + +// RSA_up_ref increments the reference count of |rsa| and returns one. It does +// not mutate |rsa| for thread-safety purposes and may be used concurrently. +OPENSSL_EXPORT int RSA_up_ref(RSA *rsa); + + +// Properties. + +// RSA_bits returns the size of |rsa|, in bits. +OPENSSL_EXPORT unsigned RSA_bits(const RSA *rsa); + +// RSA_get0_n returns |rsa|'s public modulus. +OPENSSL_EXPORT const BIGNUM *RSA_get0_n(const RSA *rsa); + +// RSA_get0_e returns |rsa|'s public exponent. +OPENSSL_EXPORT const BIGNUM *RSA_get0_e(const RSA *rsa); + +// RSA_get0_d returns |rsa|'s private exponent. If |rsa| is a public key, this +// value will be NULL. +OPENSSL_EXPORT const BIGNUM *RSA_get0_d(const RSA *rsa); + +// RSA_get0_p returns |rsa|'s first private prime factor. If |rsa| is a public +// key or lacks its prime factors, this value will be NULL. +OPENSSL_EXPORT const BIGNUM *RSA_get0_p(const RSA *rsa); + +// RSA_get0_q returns |rsa|'s second private prime factor. If |rsa| is a public +// key or lacks its prime factors, this value will be NULL. +OPENSSL_EXPORT const BIGNUM *RSA_get0_q(const RSA *rsa); + +// RSA_get0_dmp1 returns d (mod p-1) for |rsa|. If |rsa| is a public key or +// lacks CRT parameters, this value will be NULL. +OPENSSL_EXPORT const BIGNUM *RSA_get0_dmp1(const RSA *rsa); + +// RSA_get0_dmq1 returns d (mod q-1) for |rsa|. If |rsa| is a public key or +// lacks CRT parameters, this value will be NULL. +OPENSSL_EXPORT const BIGNUM *RSA_get0_dmq1(const RSA *rsa); + +// RSA_get0_iqmp returns q^-1 (mod p). If |rsa| is a public key or lacks CRT +// parameters, this value will be NULL. +OPENSSL_EXPORT const BIGNUM *RSA_get0_iqmp(const RSA *rsa); + +// RSA_get0_key sets |*out_n|, |*out_e|, and |*out_d|, if non-NULL, to |rsa|'s +// modulus, public exponent, and private exponent, respectively. If |rsa| is a +// public key, the private exponent will be set to NULL. +OPENSSL_EXPORT void RSA_get0_key(const RSA *rsa, const BIGNUM **out_n, + const BIGNUM **out_e, const BIGNUM **out_d); + +// RSA_get0_factors sets |*out_p| and |*out_q|, if non-NULL, to |rsa|'s prime +// factors. If |rsa| is a public key, they will be set to NULL. +OPENSSL_EXPORT void RSA_get0_factors(const RSA *rsa, const BIGNUM **out_p, + const BIGNUM **out_q); + +// RSA_get0_crt_params sets |*out_dmp1|, |*out_dmq1|, and |*out_iqmp|, if +// non-NULL, to |rsa|'s CRT parameters. These are d (mod p-1), d (mod q-1) and +// q^-1 (mod p), respectively. If |rsa| is a public key, each parameter will be +// set to NULL. +OPENSSL_EXPORT void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **out_dmp1, + const BIGNUM **out_dmq1, + const BIGNUM **out_iqmp); + + +// Setting individual properties. +// +// These functions allow setting individual properties of an |RSA| object. This +// is typically used with |RSA_new| to construct an RSA key field by field. +// Prefer instead to use |RSA_new_public_key| and |RSA_new_private_key|. These +// functions defer some initialization to the first use of an |RSA| object. This +// means invalid inputs may be caught late. +// +// TODO(crbug.com/boringssl/316): This deferred initialization also causes +// performance problems in multi-threaded applications. The preferred APIs +// currently have the same issues, but they will initialize eagerly in the +// future. + +// RSA_set0_key sets |rsa|'s modulus, public exponent, and private exponent to +// |n|, |e|, and |d| respectively, if non-NULL. On success, it takes ownership +// of each argument and returns one. Otherwise, it returns zero. +// +// |d| may be NULL, but |n| and |e| must either be non-NULL or already +// configured on |rsa|. +// +// It is an error to call this function after |rsa| has been used for a +// cryptographic operation. Construct a new |RSA| object instead. +OPENSSL_EXPORT int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d); + +// RSA_set0_factors sets |rsa|'s prime factors to |p| and |q|, if non-NULL, and +// takes ownership of them. On success, it takes ownership of each argument and +// returns one. Otherwise, it returns zero. +// +// Each argument must either be non-NULL or already configured on |rsa|. +// +// It is an error to call this function after |rsa| has been used for a +// cryptographic operation. Construct a new |RSA| object instead. +OPENSSL_EXPORT int RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q); + +// RSA_set0_crt_params sets |rsa|'s CRT parameters to |dmp1|, |dmq1|, and +// |iqmp|, if non-NULL, and takes ownership of them. On success, it takes +// ownership of its parameters and returns one. Otherwise, it returns zero. +// +// Each argument must either be non-NULL or already configured on |rsa|. +// +// It is an error to call this function after |rsa| has been used for a +// cryptographic operation. Construct a new |RSA| object instead. +OPENSSL_EXPORT int RSA_set0_crt_params(RSA *rsa, BIGNUM *dmp1, BIGNUM *dmq1, + BIGNUM *iqmp); + + +// Key generation. + +// RSA_generate_key_ex generates a new RSA key where the modulus has size +// |bits| and the public exponent is |e|. If unsure, |RSA_F4| is a good value +// for |e|. If |cb| is not NULL then it is called during the key generation +// process. In addition to the calls documented for |BN_generate_prime_ex|, it +// is called with event=2 when the n'th prime is rejected as unsuitable and +// with event=3 when a suitable value for |p| is found. +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int RSA_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, + BN_GENCB *cb); + +// RSA_generate_key_fips behaves like |RSA_generate_key_ex| but performs +// additional checks for FIPS compliance. The public exponent is always 65537 +// and |bits| must be either 2048 or 3072. +OPENSSL_EXPORT int RSA_generate_key_fips(RSA *rsa, int bits, BN_GENCB *cb); + + +// Encryption / Decryption +// +// These functions are considered non-mutating for thread-safety purposes and +// may be used concurrently. + +// RSA_PKCS1_PADDING denotes PKCS#1 v1.5 padding. When used with encryption, +// this is RSAES-PKCS1-v1_5. When used with signing, this is RSASSA-PKCS1-v1_5. +#define RSA_PKCS1_PADDING 1 + +// RSA_NO_PADDING denotes a raw RSA operation. +#define RSA_NO_PADDING 3 + +// RSA_PKCS1_OAEP_PADDING denotes the RSAES-OAEP encryption scheme. +#define RSA_PKCS1_OAEP_PADDING 4 + +// RSA_PKCS1_PSS_PADDING denotes the RSASSA-PSS signature scheme. This value may +// not be passed into |RSA_sign_raw|, only |EVP_PKEY_CTX_set_rsa_padding|. See +// also |RSA_sign_pss_mgf1| and |RSA_verify_pss_mgf1|. +#define RSA_PKCS1_PSS_PADDING 6 + +// RSA_encrypt encrypts |in_len| bytes from |in| to the public key from |rsa| +// and writes, at most, |max_out| bytes of encrypted data to |out|. The +// |max_out| argument must be, at least, |RSA_size| in order to ensure success. +// +// It returns 1 on success or zero on error. +// +// The |padding| argument must be one of the |RSA_*_PADDING| values. If in +// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols but +// |RSA_PKCS1_PADDING| is most common. +OPENSSL_EXPORT int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, size_t in_len, + int padding); + +// RSA_decrypt decrypts |in_len| bytes from |in| with the private key from +// |rsa| and writes, at most, |max_out| bytes of plaintext to |out|. The +// |max_out| argument must be, at least, |RSA_size| in order to ensure success. +// +// It returns 1 on success or zero on error. +// +// The |padding| argument must be one of the |RSA_*_PADDING| values. If in +// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. +// +// Passing |RSA_PKCS1_PADDING| into this function is deprecated and insecure. If +// implementing a protocol using RSAES-PKCS1-V1_5, use |RSA_NO_PADDING| and then +// check padding in constant-time combined with a swap to a random session key +// or other mitigation. See "Chosen Ciphertext Attacks Against Protocols Based +// on the RSA Encryption Standard PKCS #1", Daniel Bleichenbacher, Advances in +// Cryptology (Crypto '98). +OPENSSL_EXPORT int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, size_t in_len, + int padding); + +// RSA_public_encrypt encrypts |flen| bytes from |from| to the public key in +// |rsa| and writes the encrypted data to |to|. The |to| buffer must have at +// least |RSA_size| bytes of space. It returns the number of bytes written, or +// -1 on error. The |padding| argument must be one of the |RSA_*_PADDING| +// values. If in doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols but +// |RSA_PKCS1_PADDING| is most common. +// +// WARNING: this function is dangerous because it breaks the usual return value +// convention. Use |RSA_encrypt| instead. +OPENSSL_EXPORT int RSA_public_encrypt(size_t flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + +// RSA_private_decrypt decrypts |flen| bytes from |from| with the public key in +// |rsa| and writes the plaintext to |to|. The |to| buffer must have at least +// |RSA_size| bytes of space. It returns the number of bytes written, or -1 on +// error. The |padding| argument must be one of the |RSA_*_PADDING| values. If +// in doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. Passing +// |RSA_PKCS1_PADDING| into this function is deprecated and insecure. See +// |RSA_decrypt|. +// +// WARNING: this function is dangerous because it breaks the usual return value +// convention. Use |RSA_decrypt| instead. +OPENSSL_EXPORT int RSA_private_decrypt(size_t flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + + +// Signing / Verification +// +// These functions are considered non-mutating for thread-safety purposes and +// may be used concurrently. + +// RSA_sign signs |digest_len| bytes of digest from |digest| with |rsa| using +// RSASSA-PKCS1-v1_5. It writes, at most, |RSA_size(rsa)| bytes to |out|. On +// successful return, the actual number of bytes written is written to +// |*out_len|. +// +// The |hash_nid| argument identifies the hash function used to calculate +// |digest| and is embedded in the resulting signature. For example, it might be +// |NID_sha256|. +// +// It returns 1 on success and zero on error. +// +// WARNING: |digest| must be the result of hashing the data to be signed with +// |hash_nid|. Passing unhashed inputs will not result in a secure signature +// scheme. +OPENSSL_EXPORT int RSA_sign(int hash_nid, const uint8_t *digest, + size_t digest_len, uint8_t *out, unsigned *out_len, + RSA *rsa); + +// RSA_sign_pss_mgf1 signs |digest_len| bytes from |digest| with the public key +// from |rsa| using RSASSA-PSS with MGF1 as the mask generation function. It +// writes, at most, |max_out| bytes of signature data to |out|. The |max_out| +// argument must be, at least, |RSA_size| in order to ensure success. It returns +// 1 on success or zero on error. +// +// The |md| and |mgf1_md| arguments identify the hash used to calculate |digest| +// and the MGF1 hash, respectively. If |mgf1_md| is NULL, |md| is +// used. +// +// |salt_len| specifies the expected salt length in bytes. If |salt_len| is -1, +// then the salt length is the same as the hash length. If -2, then the salt +// length is maximal given the size of |rsa|. If unsure, use -1. +// +// WARNING: |digest| must be the result of hashing the data to be signed with +// |md|. Passing unhashed inputs will not result in a secure signature scheme. +OPENSSL_EXPORT int RSA_sign_pss_mgf1(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *digest, + size_t digest_len, const EVP_MD *md, + const EVP_MD *mgf1_md, int salt_len); + +// RSA_sign_raw performs the private key portion of computing a signature with +// |rsa|. It writes, at most, |max_out| bytes of signature data to |out|. The +// |max_out| argument must be, at least, |RSA_size| in order to ensure the +// output fits. It returns 1 on success or zero on error. +// +// If |padding| is |RSA_PKCS1_PADDING|, this function wraps |in| with the +// padding portion of RSASSA-PKCS1-v1_5 and then performs the raw private key +// operation. The caller is responsible for hashing the input and wrapping it in +// a DigestInfo structure. +// +// If |padding| is |RSA_NO_PADDING|, this function only performs the raw private +// key operation, interpreting |in| as a integer modulo n. The caller is +// responsible for hashing the input and encoding it for the signature scheme +// being implemented. +// +// WARNING: This function is a building block for a signature scheme, not a +// complete one. |in| must be the result of hashing and encoding the data as +// needed for the scheme being implemented. Passing in arbitrary inputs will not +// result in a secure signature scheme. +OPENSSL_EXPORT int RSA_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, + size_t in_len, int padding); + +// RSA_verify verifies that |sig_len| bytes from |sig| are a valid, +// RSASSA-PKCS1-v1_5 signature of |digest_len| bytes at |digest| by |rsa|. +// +// The |hash_nid| argument identifies the hash function used to calculate +// |digest| and is embedded in the resulting signature in order to prevent hash +// confusion attacks. For example, it might be |NID_sha256|. +// +// It returns one if the signature is valid and zero otherwise. +// +// WARNING: this differs from the original, OpenSSL function which additionally +// returned -1 on error. +// +// WARNING: |digest| must be the result of hashing the data to be verified with +// |hash_nid|. Passing unhashed input will not result in a secure signature +// scheme. +OPENSSL_EXPORT int RSA_verify(int hash_nid, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, + size_t sig_len, RSA *rsa); + +// RSA_verify_pss_mgf1 verifies that |sig_len| bytes from |sig| are a valid, +// RSASSA-PSS signature of |digest_len| bytes at |digest| by |rsa|. It returns +// one if the signature is valid and zero otherwise. MGF1 is used as the mask +// generation function. +// +// The |md| and |mgf1_md| arguments identify the hash used to calculate |digest| +// and the MGF1 hash, respectively. If |mgf1_md| is NULL, |md| is +// used. |salt_len| specifies the expected salt length in bytes. +// +// If |salt_len| is -1, then the salt length is the same as the hash length. If +// -2, then the salt length is recovered and all values accepted. If unsure, use +// -1. +// +// WARNING: |digest| must be the result of hashing the data to be verified with +// |md|. Passing unhashed input will not result in a secure signature scheme. +OPENSSL_EXPORT int RSA_verify_pss_mgf1(RSA *rsa, const uint8_t *digest, + size_t digest_len, const EVP_MD *md, + const EVP_MD *mgf1_md, int salt_len, + const uint8_t *sig, size_t sig_len); + +// RSA_verify_raw performs the public key portion of verifying |in_len| bytes of +// signature from |in| using the public key from |rsa|. On success, it returns +// one and writes, at most, |max_out| bytes of output to |out|. The |max_out| +// argument must be, at least, |RSA_size| in order to ensure the output fits. On +// failure or invalid input, it returns zero. +// +// If |padding| is |RSA_PKCS1_PADDING|, this function checks the padding portion +// of RSASSA-PKCS1-v1_5 and outputs the remainder of the encoded digest. The +// caller is responsible for checking the output is a DigestInfo-wrapped digest +// of the message. +// +// If |padding| is |RSA_NO_PADDING|, this function only performs the raw public +// key operation. The caller is responsible for checking the output is a valid +// result for the signature scheme being implemented. +// +// WARNING: This function is a building block for a signature scheme, not a +// complete one. Checking for arbitrary strings in |out| will not result in a +// secure signature scheme. +OPENSSL_EXPORT int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, + size_t in_len, int padding); + +// RSA_private_encrypt performs the private key portion of computing a signature +// with |rsa|. It takes |flen| bytes from |from| as input and writes the result +// to |to|. The |to| buffer must have at least |RSA_size| bytes of space. It +// returns the number of bytes written, or -1 on error. +// +// For the interpretation of |padding| and the input, see |RSA_sign_raw|. +// +// WARNING: This function is a building block for a signature scheme, not a +// complete one. See |RSA_sign_raw| for details. +// +// WARNING: This function is dangerous because it breaks the usual return value +// convention. Use |RSA_sign_raw| instead. +OPENSSL_EXPORT int RSA_private_encrypt(size_t flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + +// RSA_public_decrypt performs the public key portion of verifying |flen| bytes +// of signature from |from| using the public key from |rsa|. It writes the +// result to |to|, which must have at least |RSA_size| bytes of space. It +// returns the number of bytes written, or -1 on error. +// +// For the interpretation of |padding| and the result, see |RSA_verify_raw|. +// +// WARNING: This function is a building block for a signature scheme, not a +// complete one. See |RSA_verify_raw| for details. +// +// WARNING: This function is dangerous because it breaks the usual return value +// convention. Use |RSA_verify_raw| instead. +OPENSSL_EXPORT int RSA_public_decrypt(size_t flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + + +// Utility functions. + +// RSA_size returns the number of bytes in the modulus, which is also the size +// of a signature or encrypted value using |rsa|. +OPENSSL_EXPORT unsigned RSA_size(const RSA *rsa); + +// RSA_is_opaque returns one if |rsa| is opaque and doesn't expose its key +// material. Otherwise it returns zero. +OPENSSL_EXPORT int RSA_is_opaque(const RSA *rsa); + +// RSAPublicKey_dup allocates a fresh |RSA| and copies the public key from +// |rsa| into it. It returns the fresh |RSA| object, or NULL on error. +OPENSSL_EXPORT RSA *RSAPublicKey_dup(const RSA *rsa); + +// RSAPrivateKey_dup allocates a fresh |RSA| and copies the private key from +// |rsa| into it. It returns the fresh |RSA| object, or NULL on error. +OPENSSL_EXPORT RSA *RSAPrivateKey_dup(const RSA *rsa); + +// RSA_check_key performs basic validity tests on |rsa|. It returns one if +// they pass and zero otherwise. Opaque keys and public keys always pass. If it +// returns zero then a more detailed error is available on the error queue. +OPENSSL_EXPORT int RSA_check_key(const RSA *rsa); + +// RSA_check_fips performs public key validity tests on |key|. It returns one if +// they pass and zero otherwise. Opaque keys always fail. This function does not +// mutate |rsa| for thread-safety purposes and may be used concurrently. +OPENSSL_EXPORT int RSA_check_fips(RSA *key); + +// RSA_verify_PKCS1_PSS_mgf1 verifies that |EM| is a correct PSS padding of +// |mHash|, where |mHash| is a digest produced by |Hash|. |EM| must point to +// exactly |RSA_size(rsa)| bytes of data. The |mgf1Hash| argument specifies the +// hash function for generating the mask. If NULL, |Hash| is used. The |sLen| +// argument specifies the expected salt length in bytes. If |sLen| is -1 then +// the salt length is the same as the hash length. If -2, then the salt length +// is recovered and all values accepted. +// +// If unsure, use -1. +// +// It returns one on success or zero on error. +// +// This function implements only the low-level padding logic. Use +// |RSA_verify_pss_mgf1| instead. +OPENSSL_EXPORT int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, + const uint8_t *mHash, + const EVP_MD *Hash, + const EVP_MD *mgf1Hash, + const uint8_t *EM, int sLen); + +// RSA_padding_add_PKCS1_PSS_mgf1 writes a PSS padding of |mHash| to |EM|, +// where |mHash| is a digest produced by |Hash|. |RSA_size(rsa)| bytes of +// output will be written to |EM|. The |mgf1Hash| argument specifies the hash +// function for generating the mask. If NULL, |Hash| is used. The |sLen| +// argument specifies the expected salt length in bytes. If |sLen| is -1 then +// the salt length is the same as the hash length. If -2, then the salt length +// is maximal given the space in |EM|. +// +// It returns one on success or zero on error. +// +// This function implements only the low-level padding logic. Use +// |RSA_sign_pss_mgf1| instead. +OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS_mgf1(const RSA *rsa, uint8_t *EM, + const uint8_t *mHash, + const EVP_MD *Hash, + const EVP_MD *mgf1Hash, + int sLen); + +// RSA_padding_add_PKCS1_OAEP_mgf1 writes an OAEP padding of |from| to |to| +// with the given parameters and hash functions. If |md| is NULL then SHA-1 is +// used. If |mgf1md| is NULL then the value of |md| is used (which means SHA-1 +// if that, in turn, is NULL). +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int RSA_padding_add_PKCS1_OAEP_mgf1( + uint8_t *to, size_t to_len, const uint8_t *from, size_t from_len, + const uint8_t *param, size_t param_len, const EVP_MD *md, + const EVP_MD *mgf1md); + +// RSA_add_pkcs1_prefix builds a version of |digest| prefixed with the +// DigestInfo header for the given hash function and sets |out_msg| to point to +// it. On successful return, if |*is_alloced| is one, the caller must release +// |*out_msg| with |OPENSSL_free|. +OPENSSL_EXPORT int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len, + int *is_alloced, int hash_nid, + const uint8_t *digest, + size_t digest_len); + + +// ASN.1 functions. + +// RSA_parse_public_key parses a DER-encoded RSAPublicKey structure (RFC 8017) +// from |cbs| and advances |cbs|. It returns a newly-allocated |RSA| or NULL on +// error. +OPENSSL_EXPORT RSA *RSA_parse_public_key(CBS *cbs); + +// RSA_public_key_from_bytes parses |in| as a DER-encoded RSAPublicKey structure +// (RFC 8017). It returns a newly-allocated |RSA| or NULL on error. +OPENSSL_EXPORT RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len); + +// RSA_marshal_public_key marshals |rsa| as a DER-encoded RSAPublicKey structure +// (RFC 8017) and appends the result to |cbb|. It returns one on success and +// zero on failure. +OPENSSL_EXPORT int RSA_marshal_public_key(CBB *cbb, const RSA *rsa); + +// RSA_public_key_to_bytes marshals |rsa| as a DER-encoded RSAPublicKey +// structure (RFC 8017) and, on success, sets |*out_bytes| to a newly allocated +// buffer containing the result and returns one. Otherwise, it returns zero. The +// result should be freed with |OPENSSL_free|. +OPENSSL_EXPORT int RSA_public_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa); + +// RSA_parse_private_key parses a DER-encoded RSAPrivateKey structure (RFC 8017) +// from |cbs| and advances |cbs|. It returns a newly-allocated |RSA| or NULL on +// error. +OPENSSL_EXPORT RSA *RSA_parse_private_key(CBS *cbs); + +// RSA_private_key_from_bytes parses |in| as a DER-encoded RSAPrivateKey +// structure (RFC 8017). It returns a newly-allocated |RSA| or NULL on error. +OPENSSL_EXPORT RSA *RSA_private_key_from_bytes(const uint8_t *in, + size_t in_len); + +// RSA_marshal_private_key marshals |rsa| as a DER-encoded RSAPrivateKey +// structure (RFC 8017) and appends the result to |cbb|. It returns one on +// success and zero on failure. +OPENSSL_EXPORT int RSA_marshal_private_key(CBB *cbb, const RSA *rsa); + +// RSA_private_key_to_bytes marshals |rsa| as a DER-encoded RSAPrivateKey +// structure (RFC 8017) and, on success, sets |*out_bytes| to a newly allocated +// buffer containing the result and returns one. Otherwise, it returns zero. The +// result should be freed with |OPENSSL_free|. +OPENSSL_EXPORT int RSA_private_key_to_bytes(uint8_t **out_bytes, + size_t *out_len, const RSA *rsa); + + +// Obscure RSA variants. +// +// These functions allow creating RSA keys with obscure combinations of +// parameters. + +// RSA_new_private_key_no_crt behaves like |RSA_new_private_key| but constructs +// an RSA key without CRT coefficients. +// +// Keys created by this function will be less performant and cannot be +// serialized. +OPENSSL_EXPORT RSA *RSA_new_private_key_no_crt(const BIGNUM *n, const BIGNUM *e, + const BIGNUM *d); + +// RSA_new_private_key_no_e behaves like |RSA_new_private_key| but constructs an +// RSA key without CRT parameters or public exponent. +// +// Keys created by this function will be less performant, cannot be serialized, +// and lack hardening measures that protect against side channels and fault +// attacks. +OPENSSL_EXPORT RSA *RSA_new_private_key_no_e(const BIGNUM *n, const BIGNUM *d); + +// RSA_new_public_key_large_e behaves like |RSA_new_public_key| but allows any +// |e| up to |n|. +// +// BoringSSL typically bounds public exponents as a denial-of-service +// mitigation. Keys created by this function may perform worse than those +// created by |RSA_new_public_key|. +OPENSSL_EXPORT RSA *RSA_new_public_key_large_e(const BIGNUM *n, + const BIGNUM *e); + +// RSA_new_private_key_large_e behaves like |RSA_new_private_key| but allows any +// |e| up to |n|. +// +// BoringSSL typically bounds public exponents as a denial-of-service +// mitigation. Keys created by this function may perform worse than those +// created by |RSA_new_private_key|. +OPENSSL_EXPORT RSA *RSA_new_private_key_large_e( + const BIGNUM *n, const BIGNUM *e, const BIGNUM *d, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, + const BIGNUM *iqmp); + + +// ex_data functions. +// +// See |ex_data.h| for details. + +OPENSSL_EXPORT int RSA_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int RSA_set_ex_data(RSA *rsa, int idx, void *arg); +OPENSSL_EXPORT void *RSA_get_ex_data(const RSA *rsa, int idx); + + +// Flags. + +// RSA_FLAG_OPAQUE specifies that this RSA_METHOD does not expose its key +// material. This may be set if, for instance, it is wrapping some other crypto +// API, like a platform key store. +#define RSA_FLAG_OPAQUE 1 + +// RSA_FLAG_NO_BLINDING disables blinding of private operations, which is a +// dangerous thing to do. It is deprecated and should not be used. It will +// be ignored whenever possible. +// +// This flag must be used if a key without the public exponent |e| is used for +// private key operations; avoid using such keys whenever possible. +#define RSA_FLAG_NO_BLINDING 8 + +// RSA_FLAG_EXT_PKEY is deprecated and ignored. +#define RSA_FLAG_EXT_PKEY 0x20 + +// RSA_FLAG_NO_PUBLIC_EXPONENT indicates that private keys without a public +// exponent are allowed. This is an internal constant. Use +// |RSA_new_private_key_no_e| to construct such keys. +#define RSA_FLAG_NO_PUBLIC_EXPONENT 0x40 + +// RSA_FLAG_LARGE_PUBLIC_EXPONENT indicates that keys with a large public +// exponent are allowed. This is an internal constant. Use +// |RSA_new_public_key_large_e| and |RSA_new_private_key_large_e| to construct +// such keys. +#define RSA_FLAG_LARGE_PUBLIC_EXPONENT 0x80 + + +// RSA public exponent values. + +#define RSA_3 0x3 +#define RSA_F4 0x10001 + + +// Deprecated functions. + +#define RSA_METHOD_FLAG_NO_CHECK RSA_FLAG_OPAQUE + +// RSA_flags returns the flags for |rsa|. These are a bitwise OR of |RSA_FLAG_*| +// constants. +OPENSSL_EXPORT int RSA_flags(const RSA *rsa); + +// RSA_test_flags returns the subset of flags in |flags| which are set in |rsa|. +OPENSSL_EXPORT int RSA_test_flags(const RSA *rsa, int flags); + +// RSA_blinding_on returns one. +OPENSSL_EXPORT int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); + +// RSA_generate_key behaves like |RSA_generate_key_ex|, which is what you +// should use instead. It returns NULL on error, or a newly-allocated |RSA| on +// success. This function is provided for compatibility only. The |callback| +// and |cb_arg| parameters must be NULL. +OPENSSL_EXPORT RSA *RSA_generate_key(int bits, uint64_t e, void *callback, + void *cb_arg); + +// d2i_RSAPublicKey parses a DER-encoded RSAPublicKey structure (RFC 8017) from +// |len| bytes at |*inp|, as described in |d2i_SAMPLE|. +// +// Use |RSA_parse_public_key| instead. +OPENSSL_EXPORT RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len); + +// i2d_RSAPublicKey marshals |in| to a DER-encoded RSAPublicKey structure (RFC +// 8017), as described in |i2d_SAMPLE|. +// +// Use |RSA_marshal_public_key| instead. +OPENSSL_EXPORT int i2d_RSAPublicKey(const RSA *in, uint8_t **outp); + +// d2i_RSAPrivateKey parses a DER-encoded RSAPrivateKey structure (RFC 8017) +// from |len| bytes at |*inp|, as described in |d2i_SAMPLE|. +// +// Use |RSA_parse_private_key| instead. +OPENSSL_EXPORT RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len); + +// i2d_RSAPrivateKey marshals |in| to a DER-encoded RSAPrivateKey structure (RFC +// 8017), as described in |i2d_SAMPLE|. +// +// Use |RSA_marshal_private_key| instead. +OPENSSL_EXPORT int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp); + +// RSA_padding_add_PKCS1_PSS acts like |RSA_padding_add_PKCS1_PSS_mgf1| but the +// |mgf1Hash| parameter of the latter is implicitly set to |Hash|. +// +// This function implements only the low-level padding logic. Use +// |RSA_sign_pss_mgf1| instead. +OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS(const RSA *rsa, uint8_t *EM, + const uint8_t *mHash, + const EVP_MD *Hash, int sLen); + +// RSA_verify_PKCS1_PSS acts like |RSA_verify_PKCS1_PSS_mgf1| but the +// |mgf1Hash| parameter of the latter is implicitly set to |Hash|. +// +// This function implements only the low-level padding logic. Use +// |RSA_verify_pss_mgf1| instead. +OPENSSL_EXPORT int RSA_verify_PKCS1_PSS(const RSA *rsa, const uint8_t *mHash, + const EVP_MD *Hash, const uint8_t *EM, + int sLen); + +// RSA_padding_add_PKCS1_OAEP acts like |RSA_padding_add_PKCS1_OAEP_mgf1| but +// the |md| and |mgf1md| parameters of the latter are implicitly set to NULL, +// which means SHA-1. +OPENSSL_EXPORT int RSA_padding_add_PKCS1_OAEP(uint8_t *to, size_t to_len, + const uint8_t *from, + size_t from_len, + const uint8_t *param, + size_t param_len); + +// RSA_print prints a textual representation of |rsa| to |bio|. It returns one +// on success or zero otherwise. +OPENSSL_EXPORT int RSA_print(BIO *bio, const RSA *rsa, int indent); + +// RSA_get0_pss_params returns NULL. In OpenSSL, this function retries RSA-PSS +// parameters associated with |RSA| objects, but BoringSSL does not support +// the id-RSASSA-PSS key encoding. +OPENSSL_EXPORT const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *rsa); + +// RSA_new_method_no_e returns a newly-allocated |RSA| object backed by +// |engine|, with a public modulus of |n| and no known public exponent. +// +// Do not use this function. It exists only to support Conscrypt, whose use +// should be replaced with a more sound mechanism. See +// https://crbug.com/boringssl/602. +OPENSSL_EXPORT RSA *RSA_new_method_no_e(const ENGINE *engine, const BIGNUM *n); + + +struct rsa_meth_st { + struct openssl_method_common_st common; + + void *app_data; + + int (*init)(RSA *rsa); + int (*finish)(RSA *rsa); + + // size returns the size of the RSA modulus in bytes. + size_t (*size)(const RSA *rsa); + + int (*sign)(int type, const uint8_t *m, unsigned int m_length, + uint8_t *sigret, unsigned int *siglen, const RSA *rsa); + + // These functions mirror the |RSA_*| functions of the same name. + int (*sign_raw)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding); + int (*decrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding); + + // private_transform takes a big-endian integer from |in|, calculates the + // d'th power of it, modulo the RSA modulus and writes the result as a + // big-endian integer to |out|. Both |in| and |out| are |len| bytes long and + // |len| is always equal to |RSA_size(rsa)|. If the result of the transform + // can be represented in fewer than |len| bytes, then |out| must be zero + // padded on the left. + // + // It returns one on success and zero otherwise. + // + // RSA decrypt and sign operations will call this, thus an ENGINE might wish + // to override it in order to avoid having to implement the padding + // functionality demanded by those, higher level, operations. + int (*private_transform)(RSA *rsa, uint8_t *out, const uint8_t *in, + size_t len); + + int flags; +}; + + +// Private functions. + +typedef struct bn_blinding_st BN_BLINDING; + +struct rsa_st { + RSA_METHOD *meth; + + // Access to the following fields was historically allowed, but + // deprecated. Use |RSA_get0_*| and |RSA_set0_*| instead. Access to all other + // fields is forbidden and will cause threading errors. + BIGNUM *n; + BIGNUM *e; + BIGNUM *d; + BIGNUM *p; + BIGNUM *q; + BIGNUM *dmp1; + BIGNUM *dmq1; + BIGNUM *iqmp; + + // be careful using this if the RSA structure is shared + CRYPTO_EX_DATA ex_data; + CRYPTO_refcount_t references; + int flags; + + CRYPTO_MUTEX lock; + + // Used to cache montgomery values. The creation of these values is protected + // by |lock|. + BN_MONT_CTX *mont_n; + BN_MONT_CTX *mont_p; + BN_MONT_CTX *mont_q; + + // The following fields are copies of |d|, |dmp1|, and |dmq1|, respectively, + // but with the correct widths to prevent side channels. These must use + // separate copies due to threading concerns caused by OpenSSL's API + // mistakes. See https://github.com/openssl/openssl/issues/5158 and + // the |freeze_private_key| implementation. + BIGNUM *d_fixed, *dmp1_fixed, *dmq1_fixed; + + // inv_small_mod_large_mont is q^-1 mod p in Montgomery form, using |mont_p|, + // if |p| >= |q|. Otherwise, it is p^-1 mod q in Montgomery form, using + // |mont_q|. + BIGNUM *inv_small_mod_large_mont; + + // num_blindings contains the size of the |blindings| and |blindings_inuse| + // arrays. This member and the |blindings_inuse| array are protected by + // |lock|. + size_t num_blindings; + // blindings is an array of BN_BLINDING structures that can be reserved by a + // thread by locking |lock| and changing the corresponding element in + // |blindings_inuse| from 0 to 1. + BN_BLINDING **blindings; + unsigned char *blindings_inuse; + uint64_t blinding_fork_generation; + + // private_key_frozen is one if the key has been used for a private key + // operation and may no longer be mutated. + unsigned private_key_frozen:1; +}; + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(RSA, RSA_free) +BORINGSSL_MAKE_UP_REF(RSA, RSA_up_ref) + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif + +#define RSA_R_BAD_ENCODING 100 +#define RSA_R_BAD_E_VALUE 101 +#define RSA_R_BAD_FIXED_HEADER_DECRYPT 102 +#define RSA_R_BAD_PAD_BYTE_COUNT 103 +#define RSA_R_BAD_RSA_PARAMETERS 104 +#define RSA_R_BAD_SIGNATURE 105 +#define RSA_R_BAD_VERSION 106 +#define RSA_R_BLOCK_TYPE_IS_NOT_01 107 +#define RSA_R_BN_NOT_INITIALIZED 108 +#define RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY 109 +#define RSA_R_CRT_PARAMS_ALREADY_GIVEN 110 +#define RSA_R_CRT_VALUES_INCORRECT 111 +#define RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN 112 +#define RSA_R_DATA_TOO_LARGE 113 +#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 114 +#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 115 +#define RSA_R_DATA_TOO_SMALL 116 +#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 117 +#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 118 +#define RSA_R_D_E_NOT_CONGRUENT_TO_1 119 +#define RSA_R_EMPTY_PUBLIC_KEY 120 +#define RSA_R_ENCODE_ERROR 121 +#define RSA_R_FIRST_OCTET_INVALID 122 +#define RSA_R_INCONSISTENT_SET_OF_CRT_VALUES 123 +#define RSA_R_INTERNAL_ERROR 124 +#define RSA_R_INVALID_MESSAGE_LENGTH 125 +#define RSA_R_KEY_SIZE_TOO_SMALL 126 +#define RSA_R_LAST_OCTET_INVALID 127 +#define RSA_R_MODULUS_TOO_LARGE 128 +#define RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES 129 +#define RSA_R_NO_PUBLIC_EXPONENT 130 +#define RSA_R_NULL_BEFORE_BLOCK_MISSING 131 +#define RSA_R_N_NOT_EQUAL_P_Q 132 +#define RSA_R_OAEP_DECODING_ERROR 133 +#define RSA_R_ONLY_ONE_OF_P_Q_GIVEN 134 +#define RSA_R_OUTPUT_BUFFER_TOO_SMALL 135 +#define RSA_R_PADDING_CHECK_FAILED 136 +#define RSA_R_PKCS_DECODING_ERROR 137 +#define RSA_R_SLEN_CHECK_FAILED 138 +#define RSA_R_SLEN_RECOVERY_FAILED 139 +#define RSA_R_TOO_LONG 140 +#define RSA_R_TOO_MANY_ITERATIONS 141 +#define RSA_R_UNKNOWN_ALGORITHM_TYPE 142 +#define RSA_R_UNKNOWN_PADDING_TYPE 143 +#define RSA_R_VALUE_MISSING 144 +#define RSA_R_WRONG_SIGNATURE_LENGTH 145 +#define RSA_R_PUBLIC_KEY_VALIDATION_FAILED 146 +#define RSA_R_D_OUT_OF_RANGE 147 +#define RSA_R_BLOCK_TYPE_IS_NOT_02 148 + +#endif // OPENSSL_HEADER_RSA_H diff --git a/lib/boringssl/include/openssl/safestack.h b/lib/boringssl/include/openssl/safestack.h new file mode 100644 index 00000000..6e5e4330 --- /dev/null +++ b/lib/boringssl/include/openssl/safestack.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ diff --git a/lib/boringssl/include/openssl/service_indicator.h b/lib/boringssl/include/openssl/service_indicator.h new file mode 100644 index 00000000..33b38b23 --- /dev/null +++ b/lib/boringssl/include/openssl/service_indicator.h @@ -0,0 +1,96 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_SERVICE_INDICATOR_H +#define OPENSSL_HEADER_SERVICE_INDICATOR_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +// FIPS_service_indicator_before_call and |FIPS_service_indicator_after_call| +// both currently return the same local thread counter which is slowly +// incremented whenever approved services are called. The +// |CALL_SERVICE_AND_CHECK_APPROVED| macro is strongly recommended over calling +// these functions directly. +// +// |FIPS_service_indicator_before_call| is intended to be called immediately +// before an approved service, while |FIPS_service_indicator_after_call| should +// be called immediately after. If the values returned from these two functions +// are not equal, this means that the service called inbetween is deemed to be +// approved. If the values are still the same, this means the counter has not +// been incremented, and the service called is not approved for FIPS. +// +// In non-FIPS builds, |FIPS_service_indicator_before_call| always returns zero +// and |FIPS_service_indicator_after_call| always returns one. Thus calls always +// appear to be approved. This is intended to simplify testing. +OPENSSL_EXPORT uint64_t FIPS_service_indicator_before_call(void); +OPENSSL_EXPORT uint64_t FIPS_service_indicator_after_call(void); + +#if defined(__cplusplus) +} + +#if !defined(BORINGSSL_NO_CXX) + +extern "C++" { + +// CALL_SERVICE_AND_CHECK_APPROVED runs |func| and sets |approved| to one of the +// |FIPSStatus*| values, above, depending on whether |func| invoked an +// approved service. The result of |func| becomes the result of this macro. +#define CALL_SERVICE_AND_CHECK_APPROVED(approved, func) \ + [&] { \ + bssl::FIPSIndicatorHelper fips_indicator_helper(&approved); \ + return func; \ + }() + +namespace bssl { + +enum class FIPSStatus { + NOT_APPROVED = 0, + APPROVED = 1, +}; + +// FIPSIndicatorHelper records whether the service indicator counter advanced +// during its lifetime. +class FIPSIndicatorHelper { + public: + FIPSIndicatorHelper(FIPSStatus *result) + : result_(result), before_(FIPS_service_indicator_before_call()) { + *result_ = FIPSStatus::NOT_APPROVED; + } + + ~FIPSIndicatorHelper() { + uint64_t after = FIPS_service_indicator_after_call(); + if (after != before_) { + *result_ = FIPSStatus::APPROVED; + } + } + + FIPSIndicatorHelper(const FIPSIndicatorHelper&) = delete; + FIPSIndicatorHelper &operator=(const FIPSIndicatorHelper &) = delete; + + private: + FIPSStatus *const result_; + const uint64_t before_; +}; + +} // namespace bssl +} // extern "C++" + +#endif // !BORINGSSL_NO_CXX +#endif // __cplusplus + +#endif // OPENSSL_HEADER_SERVICE_INDICATOR_H diff --git a/lib/boringssl/include/openssl/sha.h b/lib/boringssl/include/openssl/sha.h new file mode 100644 index 00000000..b113798a --- /dev/null +++ b/lib/boringssl/include/openssl/sha.h @@ -0,0 +1,294 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_SHA_H +#define OPENSSL_HEADER_SHA_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// The SHA family of hash functions (SHA-1 and SHA-2). + + +// SHA_CBLOCK is the block size of SHA-1. +#define SHA_CBLOCK 64 + +// SHA_DIGEST_LENGTH is the length of a SHA-1 digest. +#define SHA_DIGEST_LENGTH 20 + +// SHA1_Init initialises |sha| and returns one. +OPENSSL_EXPORT int SHA1_Init(SHA_CTX *sha); + +// SHA1_Update adds |len| bytes from |data| to |sha| and returns one. +OPENSSL_EXPORT int SHA1_Update(SHA_CTX *sha, const void *data, size_t len); + +// SHA1_Final adds the final padding to |sha| and writes the resulting digest to +// |out|, which must have at least |SHA_DIGEST_LENGTH| bytes of space. It +// returns one. +OPENSSL_EXPORT int SHA1_Final(uint8_t out[SHA_DIGEST_LENGTH], SHA_CTX *sha); + +// SHA1 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA1(const uint8_t *data, size_t len, + uint8_t out[SHA_DIGEST_LENGTH]); + +// SHA1_Transform is a low-level function that performs a single, SHA-1 block +// transformation using the state from |sha| and |SHA_CBLOCK| bytes from +// |block|. +OPENSSL_EXPORT void SHA1_Transform(SHA_CTX *sha, + const uint8_t block[SHA_CBLOCK]); + +struct sha_state_st { +#if defined(OPENSSL_WINDOWS) + uint32_t h[5]; +#else + // wpa_supplicant accesses |h0|..|h4| so we must support those names + // for compatibility with it until it can be updated. + union { + uint32_t h[5]; + struct { + uint32_t h0; + uint32_t h1; + uint32_t h2; + uint32_t h3; + uint32_t h4; + }; + }; +#endif + uint32_t Nl, Nh; + uint8_t data[SHA_CBLOCK]; + unsigned num; +}; + + +// SHA-224. + +// SHA224_CBLOCK is the block size of SHA-224. +#define SHA224_CBLOCK 64 + +// SHA224_DIGEST_LENGTH is the length of a SHA-224 digest. +#define SHA224_DIGEST_LENGTH 28 + +// SHA224_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha); + +// SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len); + +// SHA224_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], + SHA256_CTX *sha); + +// SHA224 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA224_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, + uint8_t out[SHA224_DIGEST_LENGTH]); + + +// SHA-256. + +// SHA256_CBLOCK is the block size of SHA-256. +#define SHA256_CBLOCK 64 + +// SHA256_DIGEST_LENGTH is the length of a SHA-256 digest. +#define SHA256_DIGEST_LENGTH 32 + +// SHA256_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha); + +// SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len); + +// SHA256_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA256_Final(uint8_t out[SHA256_DIGEST_LENGTH], + SHA256_CTX *sha); + +// SHA256 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA256_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, + uint8_t out[SHA256_DIGEST_LENGTH]); + +// SHA256_Transform is a low-level function that performs a single, SHA-256 +// block transformation using the state from |sha| and |SHA256_CBLOCK| bytes +// from |block|. +OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, + const uint8_t block[SHA256_CBLOCK]); + +// SHA256_TransformBlocks is a low-level function that takes |num_blocks| * +// |SHA256_CBLOCK| bytes of data and performs SHA-256 transforms on it to update +// |state|. You should not use this function unless you are implementing a +// derivative of SHA-256. +OPENSSL_EXPORT void SHA256_TransformBlocks(uint32_t state[8], + const uint8_t *data, + size_t num_blocks); + +struct sha256_state_st { + uint32_t h[8]; + uint32_t Nl, Nh; + uint8_t data[SHA256_CBLOCK]; + unsigned num, md_len; +}; + + +// SHA-384. + +// SHA384_CBLOCK is the block size of SHA-384. +#define SHA384_CBLOCK 128 + +// SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. +#define SHA384_DIGEST_LENGTH 48 + +// SHA384_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha); + +// SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len); + +// SHA384_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA384 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA384_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, + uint8_t out[SHA384_DIGEST_LENGTH]); + + +// SHA-512. + +// SHA512_CBLOCK is the block size of SHA-512. +#define SHA512_CBLOCK 128 + +// SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. +#define SHA512_DIGEST_LENGTH 64 + +// SHA512_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha); + +// SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len); + +// SHA512_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA512 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA512_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, + uint8_t out[SHA512_DIGEST_LENGTH]); + +// SHA512_Transform is a low-level function that performs a single, SHA-512 +// block transformation using the state from |sha| and |SHA512_CBLOCK| bytes +// from |block|. +OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, + const uint8_t block[SHA512_CBLOCK]); + +struct sha512_state_st { + uint64_t h[8]; + uint64_t Nl, Nh; + uint8_t p[128]; + unsigned num, md_len; +}; + + +// SHA-512-256 +// +// See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf section 5.3.6 + +#define SHA512_256_DIGEST_LENGTH 32 + +// SHA512_256_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA512_256_Init(SHA512_CTX *sha); + +// SHA512_256_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA512_256_Update(SHA512_CTX *sha, const void *data, + size_t len); + +// SHA512_256_Final adds the final padding to |sha| and writes the resulting +// digest to |out|, which must have at least |SHA512_256_DIGEST_LENGTH| bytes of +// space. It returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA512_256 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA512_256_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA512_256(const uint8_t *data, size_t len, + uint8_t out[SHA512_256_DIGEST_LENGTH]); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_SHA_H diff --git a/lib/boringssl/include/openssl/siphash.h b/lib/boringssl/include/openssl/siphash.h new file mode 100644 index 00000000..fe08aa72 --- /dev/null +++ b/lib/boringssl/include/openssl/siphash.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2019, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_SIPHASH_H +#define OPENSSL_HEADER_SIPHASH_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// SipHash is a fast, secure PRF that is often used for hash tables. + + +// SIPHASH_24 implements SipHash-2-4. See https://131002.net/siphash/siphash.pdf +OPENSSL_EXPORT uint64_t SIPHASH_24(const uint64_t key[2], const uint8_t *input, + size_t input_len); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_SIPHASH_H diff --git a/lib/boringssl/include/openssl/span.h b/lib/boringssl/include/openssl/span.h new file mode 100644 index 00000000..67a1a5c5 --- /dev/null +++ b/lib/boringssl/include/openssl/span.h @@ -0,0 +1,214 @@ +/* Copyright (c) 2017, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_SSL_SPAN_H +#define OPENSSL_HEADER_SSL_SPAN_H + +#include + +#if !defined(BORINGSSL_NO_CXX) + +extern "C++" { + +#include + +#include +#include + +BSSL_NAMESPACE_BEGIN + +template +class Span; + +namespace internal { +template +class SpanBase { + // Put comparison operator implementations into a base class with const T, so + // they can be used with any type that implicitly converts into a Span. + static_assert(std::is_const::value, + "Span must be derived from SpanBase"); + + friend bool operator==(Span lhs, Span rhs) { + // MSVC issues warning C4996 because std::equal is unsafe. The pragma to + // suppress the warning mysteriously has no effect, hence this + // implementation. See + // https://msdn.microsoft.com/en-us/library/aa985974.aspx. + if (lhs.size() != rhs.size()) { + return false; + } + for (T *l = lhs.begin(), *r = rhs.begin(); l != lhs.end() && r != rhs.end(); + ++l, ++r) { + if (*l != *r) { + return false; + } + } + return true; + } + + friend bool operator!=(Span lhs, Span rhs) { return !(lhs == rhs); } +}; +} // namespace internal + +// A Span is a non-owning reference to a contiguous array of objects of type +// |T|. Conceptually, a Span is a simple a pointer to |T| and a count of +// elements accessible via that pointer. The elements referenced by the Span can +// be mutated if |T| is mutable. +// +// A Span can be constructed from container types implementing |data()| and +// |size()| methods. If |T| is constant, construction from a container type is +// implicit. This allows writing methods that accept data from some unspecified +// container type: +// +// // Foo views data referenced by v. +// void Foo(bssl::Span v) { ... } +// +// std::vector vec; +// Foo(vec); +// +// For mutable Spans, conversion is explicit: +// +// // FooMutate mutates data referenced by v. +// void FooMutate(bssl::Span v) { ... } +// +// FooMutate(bssl::Span(vec)); +// +// You can also use the |MakeSpan| and |MakeConstSpan| factory methods to +// construct Spans in order to deduce the type of the Span automatically. +// +// FooMutate(bssl::MakeSpan(vec)); +// +// Note that Spans have value type sematics. They are cheap to construct and +// copy, and should be passed by value whenever a method would otherwise accept +// a reference or pointer to a container or array. +template +class Span : private internal::SpanBase { + private: + static const size_t npos = static_cast(-1); + + // Heuristically test whether C is a container type that can be converted into + // a Span by checking for data() and size() member functions. + // + // TODO(davidben): Require C++17 support for std::is_convertible_v, etc. + template + using EnableIfContainer = std::enable_if_t< + std::is_convertible().data()), T *>::value && + std::is_integral().size())>::value>; + + public: + constexpr Span() : Span(nullptr, 0) {} + constexpr Span(T *ptr, size_t len) : data_(ptr), size_(len) {} + + template + constexpr Span(T (&array)[N]) : Span(array, N) {} + + template , + typename = std::enable_if_t::value, C>> + Span(const C &container) : data_(container.data()), size_(container.size()) {} + + template , + typename = std::enable_if_t::value, C>> + explicit Span(C &container) + : data_(container.data()), size_(container.size()) {} + + T *data() const { return data_; } + size_t size() const { return size_; } + bool empty() const { return size_ == 0; } + + T *begin() const { return data_; } + const T *cbegin() const { return data_; } + T *end() const { return data_ + size_; } + const T *cend() const { return end(); } + + T &front() const { + if (size_ == 0) { + abort(); + } + return data_[0]; + } + T &back() const { + if (size_ == 0) { + abort(); + } + return data_[size_ - 1]; + } + + T &operator[](size_t i) const { + if (i >= size_) { + abort(); + } + return data_[i]; + } + T &at(size_t i) const { return (*this)[i]; } + + Span subspan(size_t pos = 0, size_t len = npos) const { + if (pos > size_) { + // absl::Span throws an exception here. Note std::span and Chromium + // base::span additionally forbid pos + len being out of range, with a + // special case at npos/dynamic_extent, while absl::Span::subspan clips + // the span. For now, we align with absl::Span in case we switch to it in + // the future. + abort(); + } + return Span(data_ + pos, std::min(size_ - pos, len)); + } + + Span first(size_t len) { + if (len > size_) { + abort(); + } + return Span(data_, len); + } + + Span last(size_t len) { + if (len > size_) { + abort(); + } + return Span(data_ + size_ - len, len); + } + + private: + T *data_; + size_t size_; +}; + +template +const size_t Span::npos; + +template +Span MakeSpan(T *ptr, size_t size) { + return Span(ptr, size); +} + +template +auto MakeSpan(C &c) -> decltype(MakeSpan(c.data(), c.size())) { + return MakeSpan(c.data(), c.size()); +} + +template +Span MakeConstSpan(T *ptr, size_t size) { + return Span(ptr, size); +} + +template +auto MakeConstSpan(const C &c) -> decltype(MakeConstSpan(c.data(), c.size())) { + return MakeConstSpan(c.data(), c.size()); +} + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif // !defined(BORINGSSL_NO_CXX) + +#endif // OPENSSL_HEADER_SSL_SPAN_H diff --git a/lib/boringssl/include/openssl/srtp.h b/lib/boringssl/include/openssl/srtp.h new file mode 100644 index 00000000..39f6a855 --- /dev/null +++ b/lib/boringssl/include/openssl/srtp.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "ssl.h" diff --git a/lib/boringssl/include/openssl/ssl.h b/lib/boringssl/include/openssl/ssl.h new file mode 100644 index 00000000..53aa9b45 --- /dev/null +++ b/lib/boringssl/include/openssl/ssl.h @@ -0,0 +1,5817 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef OPENSSL_HEADER_SSL_H +#define OPENSSL_HEADER_SSL_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#endif + +// Forward-declare struct timeval. On Windows, it is defined in winsock2.h and +// Windows headers define too many macros to be included in public headers. +// However, only a forward declaration is needed. +struct timeval; + +#if defined(__cplusplus) +extern "C" { +#endif + + +// SSL implementation. + + +// SSL contexts. +// +// |SSL_CTX| objects manage shared state and configuration between multiple TLS +// or DTLS connections. Whether the connections are TLS or DTLS is selected by +// an |SSL_METHOD| on creation. +// +// |SSL_CTX| are reference-counted and may be shared by connections across +// multiple threads. Once shared, functions which change the |SSL_CTX|'s +// configuration may not be used. + +// TLS_method is the |SSL_METHOD| used for TLS connections. +OPENSSL_EXPORT const SSL_METHOD *TLS_method(void); + +// DTLS_method is the |SSL_METHOD| used for DTLS connections. +OPENSSL_EXPORT const SSL_METHOD *DTLS_method(void); + +// TLS_with_buffers_method is like |TLS_method|, but avoids all use of +// crypto/x509. All client connections created with |TLS_with_buffers_method| +// will fail unless a certificate verifier is installed with +// |SSL_set_custom_verify| or |SSL_CTX_set_custom_verify|. +OPENSSL_EXPORT const SSL_METHOD *TLS_with_buffers_method(void); + +// DTLS_with_buffers_method is like |DTLS_method|, but avoids all use of +// crypto/x509. +OPENSSL_EXPORT const SSL_METHOD *DTLS_with_buffers_method(void); + +// SSL_CTX_new returns a newly-allocated |SSL_CTX| with default settings or NULL +// on error. +OPENSSL_EXPORT SSL_CTX *SSL_CTX_new(const SSL_METHOD *method); + +// SSL_CTX_up_ref increments the reference count of |ctx|. It returns one. +OPENSSL_EXPORT int SSL_CTX_up_ref(SSL_CTX *ctx); + +// SSL_CTX_free releases memory associated with |ctx|. +OPENSSL_EXPORT void SSL_CTX_free(SSL_CTX *ctx); + + +// SSL connections. +// +// An |SSL| object represents a single TLS or DTLS connection. Although the +// shared |SSL_CTX| is thread-safe, an |SSL| is not thread-safe and may only be +// used on one thread at a time. + +// SSL_new returns a newly-allocated |SSL| using |ctx| or NULL on error. The new +// connection inherits settings from |ctx| at the time of creation. Settings may +// also be individually configured on the connection. +// +// On creation, an |SSL| is not configured to be either a client or server. Call +// |SSL_set_connect_state| or |SSL_set_accept_state| to set this. +OPENSSL_EXPORT SSL *SSL_new(SSL_CTX *ctx); + +// SSL_free releases memory associated with |ssl|. +OPENSSL_EXPORT void SSL_free(SSL *ssl); + +// SSL_get_SSL_CTX returns the |SSL_CTX| associated with |ssl|. If +// |SSL_set_SSL_CTX| is called, it returns the new |SSL_CTX|, not the initial +// one. +OPENSSL_EXPORT SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl); + +// SSL_set_connect_state configures |ssl| to be a client. +OPENSSL_EXPORT void SSL_set_connect_state(SSL *ssl); + +// SSL_set_accept_state configures |ssl| to be a server. +OPENSSL_EXPORT void SSL_set_accept_state(SSL *ssl); + +// SSL_is_server returns one if |ssl| is configured as a server and zero +// otherwise. +OPENSSL_EXPORT int SSL_is_server(const SSL *ssl); + +// SSL_is_dtls returns one if |ssl| is a DTLS connection and zero otherwise. +OPENSSL_EXPORT int SSL_is_dtls(const SSL *ssl); + +// SSL_set_bio configures |ssl| to read from |rbio| and write to |wbio|. |ssl| +// takes ownership of the two |BIO|s. If |rbio| and |wbio| are the same, |ssl| +// only takes ownership of one reference. +// +// In DTLS, |rbio| must be non-blocking to properly handle timeouts and +// retransmits. +// +// If |rbio| is the same as the currently configured |BIO| for reading, that +// side is left untouched and is not freed. +// +// If |wbio| is the same as the currently configured |BIO| for writing AND |ssl| +// is not currently configured to read from and write to the same |BIO|, that +// side is left untouched and is not freed. This asymmetry is present for +// historical reasons. +// +// Due to the very complex historical behavior of this function, calling this +// function if |ssl| already has |BIO|s configured is deprecated. Prefer +// |SSL_set0_rbio| and |SSL_set0_wbio| instead. +OPENSSL_EXPORT void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio); + +// SSL_set0_rbio configures |ssl| to read from |rbio|. It takes ownership of +// |rbio|. +// +// Note that, although this function and |SSL_set0_wbio| may be called on the +// same |BIO|, each call takes a reference. Use |BIO_up_ref| to balance this. +OPENSSL_EXPORT void SSL_set0_rbio(SSL *ssl, BIO *rbio); + +// SSL_set0_wbio configures |ssl| to write to |wbio|. It takes ownership of +// |wbio|. +// +// Note that, although this function and |SSL_set0_rbio| may be called on the +// same |BIO|, each call takes a reference. Use |BIO_up_ref| to balance this. +OPENSSL_EXPORT void SSL_set0_wbio(SSL *ssl, BIO *wbio); + +// SSL_get_rbio returns the |BIO| that |ssl| reads from. +OPENSSL_EXPORT BIO *SSL_get_rbio(const SSL *ssl); + +// SSL_get_wbio returns the |BIO| that |ssl| writes to. +OPENSSL_EXPORT BIO *SSL_get_wbio(const SSL *ssl); + +// SSL_get_fd calls |SSL_get_rfd|. +OPENSSL_EXPORT int SSL_get_fd(const SSL *ssl); + +// SSL_get_rfd returns the file descriptor that |ssl| is configured to read +// from. If |ssl|'s read |BIO| is not configured or doesn't wrap a file +// descriptor then it returns -1. +// +// Note: On Windows, this may return either a file descriptor or a socket (cast +// to int), depending on whether |ssl| was configured with a file descriptor or +// socket |BIO|. +OPENSSL_EXPORT int SSL_get_rfd(const SSL *ssl); + +// SSL_get_wfd returns the file descriptor that |ssl| is configured to write +// to. If |ssl|'s write |BIO| is not configured or doesn't wrap a file +// descriptor then it returns -1. +// +// Note: On Windows, this may return either a file descriptor or a socket (cast +// to int), depending on whether |ssl| was configured with a file descriptor or +// socket |BIO|. +OPENSSL_EXPORT int SSL_get_wfd(const SSL *ssl); + +// SSL_set_fd configures |ssl| to read from and write to |fd|. It returns one +// on success and zero on allocation error. The caller retains ownership of +// |fd|. +// +// On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. +OPENSSL_EXPORT int SSL_set_fd(SSL *ssl, int fd); + +// SSL_set_rfd configures |ssl| to read from |fd|. It returns one on success and +// zero on allocation error. The caller retains ownership of |fd|. +// +// On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. +OPENSSL_EXPORT int SSL_set_rfd(SSL *ssl, int fd); + +// SSL_set_wfd configures |ssl| to write to |fd|. It returns one on success and +// zero on allocation error. The caller retains ownership of |fd|. +// +// On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. +OPENSSL_EXPORT int SSL_set_wfd(SSL *ssl, int fd); + +// SSL_do_handshake continues the current handshake. If there is none or the +// handshake has completed or False Started, it returns one. Otherwise, it +// returns <= 0. The caller should pass the value into |SSL_get_error| to +// determine how to proceed. +// +// In DTLS, the caller must drive retransmissions. Whenever |SSL_get_error| +// signals |SSL_ERROR_WANT_READ|, use |DTLSv1_get_timeout| to determine the +// current timeout. If it expires before the next retry, call +// |DTLSv1_handle_timeout|. Note that DTLS handshake retransmissions use fresh +// sequence numbers, so it is not sufficient to replay packets at the transport. +// +// TODO(davidben): Ensure 0 is only returned on transport EOF. +// https://crbug.com/466303. +OPENSSL_EXPORT int SSL_do_handshake(SSL *ssl); + +// SSL_connect configures |ssl| as a client, if unconfigured, and calls +// |SSL_do_handshake|. +OPENSSL_EXPORT int SSL_connect(SSL *ssl); + +// SSL_accept configures |ssl| as a server, if unconfigured, and calls +// |SSL_do_handshake|. +OPENSSL_EXPORT int SSL_accept(SSL *ssl); + +// SSL_read reads up to |num| bytes from |ssl| into |buf|. It implicitly runs +// any pending handshakes, including renegotiations when enabled. On success, it +// returns the number of bytes read. Otherwise, it returns <= 0. The caller +// should pass the value into |SSL_get_error| to determine how to proceed. +// +// TODO(davidben): Ensure 0 is only returned on transport EOF. +// https://crbug.com/466303. +OPENSSL_EXPORT int SSL_read(SSL *ssl, void *buf, int num); + +// SSL_peek behaves like |SSL_read| but does not consume any bytes returned. +OPENSSL_EXPORT int SSL_peek(SSL *ssl, void *buf, int num); + +// SSL_pending returns the number of buffered, decrypted bytes available for +// read in |ssl|. It does not read from the transport. +// +// In DTLS, it is possible for this function to return zero while there is +// buffered, undecrypted data from the transport in |ssl|. For example, +// |SSL_read| may read a datagram with two records, decrypt the first, and leave +// the second buffered for a subsequent call to |SSL_read|. Callers that wish to +// detect this case can use |SSL_has_pending|. +OPENSSL_EXPORT int SSL_pending(const SSL *ssl); + +// SSL_has_pending returns one if |ssl| has buffered, decrypted bytes available +// for read, or if |ssl| has buffered data from the transport that has not yet +// been decrypted. If |ssl| has neither, this function returns zero. +// +// In TLS, BoringSSL does not implement read-ahead, so this function returns one +// if and only if |SSL_pending| would return a non-zero value. In DTLS, it is +// possible for this function to return one while |SSL_pending| returns zero. +// For example, |SSL_read| may read a datagram with two records, decrypt the +// first, and leave the second buffered for a subsequent call to |SSL_read|. +// +// As a result, if this function returns one, the next call to |SSL_read| may +// still fail, read from the transport, or both. The buffered, undecrypted data +// may be invalid or incomplete. +OPENSSL_EXPORT int SSL_has_pending(const SSL *ssl); + +// SSL_write writes up to |num| bytes from |buf| into |ssl|. It implicitly runs +// any pending handshakes, including renegotiations when enabled. On success, it +// returns the number of bytes written. Otherwise, it returns <= 0. The caller +// should pass the value into |SSL_get_error| to determine how to proceed. +// +// In TLS, a non-blocking |SSL_write| differs from non-blocking |write| in that +// a failed |SSL_write| still commits to the data passed in. When retrying, the +// caller must supply the original write buffer (or a larger one containing the +// original as a prefix). By default, retries will fail if they also do not +// reuse the same |buf| pointer. This may be relaxed with +// |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|, but the buffer contents still must be +// unchanged. +// +// By default, in TLS, |SSL_write| will not return success until all |num| bytes +// are written. This may be relaxed with |SSL_MODE_ENABLE_PARTIAL_WRITE|. It +// allows |SSL_write| to complete with a partial result when only part of the +// input was written in a single record. +// +// In DTLS, neither |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER| and +// |SSL_MODE_ENABLE_PARTIAL_WRITE| do anything. The caller may retry with a +// different buffer freely. A single call to |SSL_write| only ever writes a +// single record in a single packet, so |num| must be at most +// |SSL3_RT_MAX_PLAIN_LENGTH|. +// +// TODO(davidben): Ensure 0 is only returned on transport EOF. +// https://crbug.com/466303. +OPENSSL_EXPORT int SSL_write(SSL *ssl, const void *buf, int num); + +// SSL_KEY_UPDATE_REQUESTED indicates that the peer should reply to a KeyUpdate +// message with its own, thus updating traffic secrets for both directions on +// the connection. +#define SSL_KEY_UPDATE_REQUESTED 1 + +// SSL_KEY_UPDATE_NOT_REQUESTED indicates that the peer should not reply with +// it's own KeyUpdate message. +#define SSL_KEY_UPDATE_NOT_REQUESTED 0 + +// SSL_key_update queues a TLS 1.3 KeyUpdate message to be sent on |ssl| +// if one is not already queued. The |request_type| argument must one of the +// |SSL_KEY_UPDATE_*| values. This function requires that |ssl| have completed a +// TLS >= 1.3 handshake. It returns one on success or zero on error. +// +// Note that this function does not _send_ the message itself. The next call to +// |SSL_write| will cause the message to be sent. |SSL_write| may be called with +// a zero length to flush a KeyUpdate message when no application data is +// pending. +OPENSSL_EXPORT int SSL_key_update(SSL *ssl, int request_type); + +// SSL_shutdown shuts down |ssl|. It runs in two stages. First, it sends +// close_notify and returns zero or one on success or -1 on failure. Zero +// indicates that close_notify was sent, but not received, and one additionally +// indicates that the peer's close_notify had already been received. +// +// To then wait for the peer's close_notify, run |SSL_shutdown| to completion a +// second time. This returns 1 on success and -1 on failure. Application data +// is considered a fatal error at this point. To process or discard it, read +// until close_notify with |SSL_read| instead. +// +// In both cases, on failure, pass the return value into |SSL_get_error| to +// determine how to proceed. +// +// Most callers should stop at the first stage. Reading for close_notify is +// primarily used for uncommon protocols where the underlying transport is +// reused after TLS completes. Additionally, DTLS uses an unordered transport +// and is unordered, so the second stage is a no-op in DTLS. +OPENSSL_EXPORT int SSL_shutdown(SSL *ssl); + +// SSL_CTX_set_quiet_shutdown sets quiet shutdown on |ctx| to |mode|. If +// enabled, |SSL_shutdown| will not send a close_notify alert or wait for one +// from the peer. It will instead synchronously return one. +OPENSSL_EXPORT void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode); + +// SSL_CTX_get_quiet_shutdown returns whether quiet shutdown is enabled for +// |ctx|. +OPENSSL_EXPORT int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx); + +// SSL_set_quiet_shutdown sets quiet shutdown on |ssl| to |mode|. If enabled, +// |SSL_shutdown| will not send a close_notify alert or wait for one from the +// peer. It will instead synchronously return one. +OPENSSL_EXPORT void SSL_set_quiet_shutdown(SSL *ssl, int mode); + +// SSL_get_quiet_shutdown returns whether quiet shutdown is enabled for +// |ssl|. +OPENSSL_EXPORT int SSL_get_quiet_shutdown(const SSL *ssl); + +// SSL_get_error returns a |SSL_ERROR_*| value for the most recent operation on +// |ssl|. It should be called after an operation failed to determine whether the +// error was fatal and, if not, when to retry. +OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code); + +// SSL_ERROR_NONE indicates the operation succeeded. +#define SSL_ERROR_NONE 0 + +// SSL_ERROR_SSL indicates the operation failed within the library. The caller +// may inspect the error queue for more information. +#define SSL_ERROR_SSL 1 + +// SSL_ERROR_WANT_READ indicates the operation failed attempting to read from +// the transport. The caller may retry the operation when the transport is ready +// for reading. +// +// If signaled by a DTLS handshake, the caller must also call +// |DTLSv1_get_timeout| and |DTLSv1_handle_timeout| as appropriate. See +// |SSL_do_handshake|. +#define SSL_ERROR_WANT_READ 2 + +// SSL_ERROR_WANT_WRITE indicates the operation failed attempting to write to +// the transport. The caller may retry the operation when the transport is ready +// for writing. +#define SSL_ERROR_WANT_WRITE 3 + +// SSL_ERROR_WANT_X509_LOOKUP indicates the operation failed in calling the +// |cert_cb| or |client_cert_cb|. The caller may retry the operation when the +// callback is ready to return a certificate or one has been configured +// externally. +// +// See also |SSL_CTX_set_cert_cb| and |SSL_CTX_set_client_cert_cb|. +#define SSL_ERROR_WANT_X509_LOOKUP 4 + +// SSL_ERROR_SYSCALL indicates the operation failed externally to the library. +// The caller should consult the system-specific error mechanism. This is +// typically |errno| but may be something custom if using a custom |BIO|. It +// may also be signaled if the transport returned EOF, in which case the +// operation's return value will be zero. +#define SSL_ERROR_SYSCALL 5 + +// SSL_ERROR_ZERO_RETURN indicates the operation failed because the connection +// was cleanly shut down with a close_notify alert. +#define SSL_ERROR_ZERO_RETURN 6 + +// SSL_ERROR_WANT_CONNECT indicates the operation failed attempting to connect +// the transport (the |BIO| signaled |BIO_RR_CONNECT|). The caller may retry the +// operation when the transport is ready. +#define SSL_ERROR_WANT_CONNECT 7 + +// SSL_ERROR_WANT_ACCEPT indicates the operation failed attempting to accept a +// connection from the transport (the |BIO| signaled |BIO_RR_ACCEPT|). The +// caller may retry the operation when the transport is ready. +// +// TODO(davidben): Remove this. It's used by accept BIOs which are bizarre. +#define SSL_ERROR_WANT_ACCEPT 8 + +// SSL_ERROR_WANT_CHANNEL_ID_LOOKUP is never used. +// +// TODO(davidben): Remove this. Some callers reference it when stringifying +// errors. They should use |SSL_error_description| instead. +#define SSL_ERROR_WANT_CHANNEL_ID_LOOKUP 9 + +// SSL_ERROR_PENDING_SESSION indicates the operation failed because the session +// lookup callback indicated the session was unavailable. The caller may retry +// the operation when lookup has completed. +// +// See also |SSL_CTX_sess_set_get_cb| and |SSL_magic_pending_session_ptr|. +#define SSL_ERROR_PENDING_SESSION 11 + +// SSL_ERROR_PENDING_CERTIFICATE indicates the operation failed because the +// early callback indicated certificate lookup was incomplete. The caller may +// retry the operation when lookup has completed. +// +// See also |SSL_CTX_set_select_certificate_cb|. +#define SSL_ERROR_PENDING_CERTIFICATE 12 + +// SSL_ERROR_WANT_PRIVATE_KEY_OPERATION indicates the operation failed because +// a private key operation was unfinished. The caller may retry the operation +// when the private key operation is complete. +// +// See also |SSL_set_private_key_method| and +// |SSL_CTX_set_private_key_method|. +#define SSL_ERROR_WANT_PRIVATE_KEY_OPERATION 13 + +// SSL_ERROR_PENDING_TICKET indicates that a ticket decryption is pending. The +// caller may retry the operation when the decryption is ready. +// +// See also |SSL_CTX_set_ticket_aead_method|. +#define SSL_ERROR_PENDING_TICKET 14 + +// SSL_ERROR_EARLY_DATA_REJECTED indicates that early data was rejected. The +// caller should treat this as a connection failure and retry any operations +// associated with the rejected early data. |SSL_reset_early_data_reject| may be +// used to reuse the underlying connection for the retry. +#define SSL_ERROR_EARLY_DATA_REJECTED 15 + +// SSL_ERROR_WANT_CERTIFICATE_VERIFY indicates the operation failed because +// certificate verification was incomplete. The caller may retry the operation +// when certificate verification is complete. +// +// See also |SSL_CTX_set_custom_verify|. +#define SSL_ERROR_WANT_CERTIFICATE_VERIFY 16 + +#define SSL_ERROR_HANDOFF 17 +#define SSL_ERROR_HANDBACK 18 + +// SSL_ERROR_WANT_RENEGOTIATE indicates the operation is pending a response to +// a renegotiation request from the server. The caller may call +// |SSL_renegotiate| to schedule a renegotiation and retry the operation. +// +// See also |ssl_renegotiate_explicit|. +#define SSL_ERROR_WANT_RENEGOTIATE 19 + +// SSL_ERROR_HANDSHAKE_HINTS_READY indicates the handshake has progressed enough +// for |SSL_serialize_handshake_hints| to be called. See also +// |SSL_request_handshake_hints|. +#define SSL_ERROR_HANDSHAKE_HINTS_READY 20 + +// SSL_error_description returns a string representation of |err|, where |err| +// is one of the |SSL_ERROR_*| constants returned by |SSL_get_error|, or NULL +// if the value is unrecognized. +OPENSSL_EXPORT const char *SSL_error_description(int err); + +// SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success +// and zero on failure. +OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu); + +// DTLSv1_set_initial_timeout_duration sets the initial duration for a DTLS +// handshake timeout. +// +// This duration overrides the default of 1 second, which is the strong +// recommendation of RFC 6347 (see section 4.2.4.1). However, there may exist +// situations where a shorter timeout would be beneficial, such as for +// time-sensitive applications. +OPENSSL_EXPORT void DTLSv1_set_initial_timeout_duration(SSL *ssl, + unsigned duration_ms); + +// DTLSv1_get_timeout queries the next DTLS handshake timeout. If there is a +// timeout in progress, it sets |*out| to the time remaining and returns one. +// Otherwise, it returns zero. +// +// When the timeout expires, call |DTLSv1_handle_timeout| to handle the +// retransmit behavior. +// +// NOTE: This function must be queried again whenever the handshake state +// machine changes, including when |DTLSv1_handle_timeout| is called. +OPENSSL_EXPORT int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out); + +// DTLSv1_handle_timeout is called when a DTLS handshake timeout expires. If no +// timeout had expired, it returns 0. Otherwise, it retransmits the previous +// flight of handshake messages and returns 1. If too many timeouts had expired +// without progress or an error occurs, it returns -1. +// +// The caller's external timer should be compatible with the one |ssl| queries +// within some fudge factor. Otherwise, the call will be a no-op, but +// |DTLSv1_get_timeout| will return an updated timeout. +// +// If the function returns -1, checking if |SSL_get_error| returns +// |SSL_ERROR_WANT_WRITE| may be used to determine if the retransmit failed due +// to a non-fatal error at the write |BIO|. However, the operation may not be +// retried until the next timeout fires. +// +// WARNING: This function breaks the usual return value convention. +// +// TODO(davidben): This |SSL_ERROR_WANT_WRITE| behavior is kind of bizarre. +OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl); + + +// Protocol versions. + +#define DTLS1_VERSION_MAJOR 0xfe +#define SSL3_VERSION_MAJOR 0x03 + +#define SSL3_VERSION 0x0300 +#define TLS1_VERSION 0x0301 +#define TLS1_1_VERSION 0x0302 +#define TLS1_2_VERSION 0x0303 +#define TLS1_3_VERSION 0x0304 + +#define DTLS1_VERSION 0xfeff +#define DTLS1_2_VERSION 0xfefd + +// SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to +// |version|. If |version| is zero, the default minimum version is used. It +// returns one on success and zero if |version| is invalid. +OPENSSL_EXPORT int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, + uint16_t version); + +// SSL_CTX_set_max_proto_version sets the maximum protocol version for |ctx| to +// |version|. If |version| is zero, the default maximum version is used. It +// returns one on success and zero if |version| is invalid. +OPENSSL_EXPORT int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, + uint16_t version); + +// SSL_CTX_get_min_proto_version returns the minimum protocol version for |ctx| +OPENSSL_EXPORT uint16_t SSL_CTX_get_min_proto_version(const SSL_CTX *ctx); + +// SSL_CTX_get_max_proto_version returns the maximum protocol version for |ctx| +OPENSSL_EXPORT uint16_t SSL_CTX_get_max_proto_version(const SSL_CTX *ctx); + +// SSL_set_min_proto_version sets the minimum protocol version for |ssl| to +// |version|. If |version| is zero, the default minimum version is used. It +// returns one on success and zero if |version| is invalid. +OPENSSL_EXPORT int SSL_set_min_proto_version(SSL *ssl, uint16_t version); + +// SSL_set_max_proto_version sets the maximum protocol version for |ssl| to +// |version|. If |version| is zero, the default maximum version is used. It +// returns one on success and zero if |version| is invalid. +OPENSSL_EXPORT int SSL_set_max_proto_version(SSL *ssl, uint16_t version); + +// SSL_get_min_proto_version returns the minimum protocol version for |ssl|. If +// the connection's configuration has been shed, 0 is returned. +OPENSSL_EXPORT uint16_t SSL_get_min_proto_version(const SSL *ssl); + +// SSL_get_max_proto_version returns the maximum protocol version for |ssl|. If +// the connection's configuration has been shed, 0 is returned. +OPENSSL_EXPORT uint16_t SSL_get_max_proto_version(const SSL *ssl); + +// SSL_version returns the TLS or DTLS protocol version used by |ssl|, which is +// one of the |*_VERSION| values. (E.g. |TLS1_2_VERSION|.) Before the version +// is negotiated, the result is undefined. +OPENSSL_EXPORT int SSL_version(const SSL *ssl); + + +// Options. +// +// Options configure protocol behavior. + +// SSL_OP_NO_QUERY_MTU, in DTLS, disables querying the MTU from the underlying +// |BIO|. Instead, the MTU is configured with |SSL_set_mtu|. +#define SSL_OP_NO_QUERY_MTU 0x00001000L + +// SSL_OP_NO_TICKET disables session ticket support (RFC 5077). +#define SSL_OP_NO_TICKET 0x00004000L + +// SSL_OP_CIPHER_SERVER_PREFERENCE configures servers to select ciphers and +// ECDHE curves according to the server's preferences instead of the +// client's. +#define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L + +// The following flags toggle individual protocol versions. This is deprecated. +// Use |SSL_CTX_set_min_proto_version| and |SSL_CTX_set_max_proto_version| +// instead. +#define SSL_OP_NO_TLSv1 0x04000000L +#define SSL_OP_NO_TLSv1_2 0x08000000L +#define SSL_OP_NO_TLSv1_1 0x10000000L +#define SSL_OP_NO_TLSv1_3 0x20000000L +#define SSL_OP_NO_DTLSv1 SSL_OP_NO_TLSv1 +#define SSL_OP_NO_DTLSv1_2 SSL_OP_NO_TLSv1_2 + +// SSL_CTX_set_options enables all options set in |options| (which should be one +// or more of the |SSL_OP_*| values, ORed together) in |ctx|. It returns a +// bitmask representing the resulting enabled options. +OPENSSL_EXPORT uint32_t SSL_CTX_set_options(SSL_CTX *ctx, uint32_t options); + +// SSL_CTX_clear_options disables all options set in |options| (which should be +// one or more of the |SSL_OP_*| values, ORed together) in |ctx|. It returns a +// bitmask representing the resulting enabled options. +OPENSSL_EXPORT uint32_t SSL_CTX_clear_options(SSL_CTX *ctx, uint32_t options); + +// SSL_CTX_get_options returns a bitmask of |SSL_OP_*| values that represent all +// the options enabled for |ctx|. +OPENSSL_EXPORT uint32_t SSL_CTX_get_options(const SSL_CTX *ctx); + +// SSL_set_options enables all options set in |options| (which should be one or +// more of the |SSL_OP_*| values, ORed together) in |ssl|. It returns a bitmask +// representing the resulting enabled options. +OPENSSL_EXPORT uint32_t SSL_set_options(SSL *ssl, uint32_t options); + +// SSL_clear_options disables all options set in |options| (which should be one +// or more of the |SSL_OP_*| values, ORed together) in |ssl|. It returns a +// bitmask representing the resulting enabled options. +OPENSSL_EXPORT uint32_t SSL_clear_options(SSL *ssl, uint32_t options); + +// SSL_get_options returns a bitmask of |SSL_OP_*| values that represent all the +// options enabled for |ssl|. +OPENSSL_EXPORT uint32_t SSL_get_options(const SSL *ssl); + + +// Modes. +// +// Modes configure API behavior. + +// SSL_MODE_ENABLE_PARTIAL_WRITE, in TLS, allows |SSL_write| to complete with a +// partial result when the only part of the input was written in a single +// record. In DTLS, it does nothing. +#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L + +// SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, in TLS, allows retrying an incomplete +// |SSL_write| with a different buffer. However, |SSL_write| still assumes the +// buffer contents are unchanged. This is not the default to avoid the +// misconception that non-blocking |SSL_write| behaves like non-blocking +// |write|. In DTLS, it does nothing. +#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L + +// SSL_MODE_NO_AUTO_CHAIN disables automatically building a certificate chain +// before sending certificates to the peer. This flag is set (and the feature +// disabled) by default. +// TODO(davidben): Remove this behavior. https://crbug.com/boringssl/42. +#define SSL_MODE_NO_AUTO_CHAIN 0x00000008L + +// SSL_MODE_ENABLE_FALSE_START allows clients to send application data before +// receipt of ChangeCipherSpec and Finished. This mode enables full handshakes +// to 'complete' in one RTT. See RFC 7918. +// +// When False Start is enabled, |SSL_do_handshake| may succeed before the +// handshake has completely finished. |SSL_write| will function at this point, +// and |SSL_read| will transparently wait for the final handshake leg before +// returning application data. To determine if False Start occurred or when the +// handshake is completely finished, see |SSL_in_false_start|, |SSL_in_init|, +// and |SSL_CB_HANDSHAKE_DONE| from |SSL_CTX_set_info_callback|. +#define SSL_MODE_ENABLE_FALSE_START 0x00000080L + +// SSL_MODE_CBC_RECORD_SPLITTING causes multi-byte CBC records in TLS 1.0 to be +// split in two: the first record will contain a single byte and the second will +// contain the remainder. This effectively randomises the IV and prevents BEAST +// attacks. +#define SSL_MODE_CBC_RECORD_SPLITTING 0x00000100L + +// SSL_MODE_NO_SESSION_CREATION will cause any attempts to create a session to +// fail with SSL_R_SESSION_MAY_NOT_BE_CREATED. This can be used to enforce that +// session resumption is used for a given SSL*. +#define SSL_MODE_NO_SESSION_CREATION 0x00000200L + +// SSL_MODE_SEND_FALLBACK_SCSV sends TLS_FALLBACK_SCSV in the ClientHello. +// To be set only by applications that reconnect with a downgraded protocol +// version; see RFC 7507 for details. +// +// DO NOT ENABLE THIS if your application attempts a normal handshake. Only use +// this in explicit fallback retries, following the guidance in RFC 7507. +#define SSL_MODE_SEND_FALLBACK_SCSV 0x00000400L + +// SSL_CTX_set_mode enables all modes set in |mode| (which should be one or more +// of the |SSL_MODE_*| values, ORed together) in |ctx|. It returns a bitmask +// representing the resulting enabled modes. +OPENSSL_EXPORT uint32_t SSL_CTX_set_mode(SSL_CTX *ctx, uint32_t mode); + +// SSL_CTX_clear_mode disables all modes set in |mode| (which should be one or +// more of the |SSL_MODE_*| values, ORed together) in |ctx|. It returns a +// bitmask representing the resulting enabled modes. +OPENSSL_EXPORT uint32_t SSL_CTX_clear_mode(SSL_CTX *ctx, uint32_t mode); + +// SSL_CTX_get_mode returns a bitmask of |SSL_MODE_*| values that represent all +// the modes enabled for |ssl|. +OPENSSL_EXPORT uint32_t SSL_CTX_get_mode(const SSL_CTX *ctx); + +// SSL_set_mode enables all modes set in |mode| (which should be one or more of +// the |SSL_MODE_*| values, ORed together) in |ssl|. It returns a bitmask +// representing the resulting enabled modes. +OPENSSL_EXPORT uint32_t SSL_set_mode(SSL *ssl, uint32_t mode); + +// SSL_clear_mode disables all modes set in |mode| (which should be one or more +// of the |SSL_MODE_*| values, ORed together) in |ssl|. It returns a bitmask +// representing the resulting enabled modes. +OPENSSL_EXPORT uint32_t SSL_clear_mode(SSL *ssl, uint32_t mode); + +// SSL_get_mode returns a bitmask of |SSL_MODE_*| values that represent all the +// modes enabled for |ssl|. +OPENSSL_EXPORT uint32_t SSL_get_mode(const SSL *ssl); + +// SSL_CTX_set0_buffer_pool sets a |CRYPTO_BUFFER_POOL| that will be used to +// store certificates. This can allow multiple connections to share +// certificates and thus save memory. +// +// The SSL_CTX does not take ownership of |pool| and the caller must ensure +// that |pool| outlives |ctx| and all objects linked to it, including |SSL|, +// |X509| and |SSL_SESSION| objects. Basically, don't ever free |pool|. +OPENSSL_EXPORT void SSL_CTX_set0_buffer_pool(SSL_CTX *ctx, + CRYPTO_BUFFER_POOL *pool); + + +// Configuring certificates and private keys. +// +// These functions configure the connection's leaf certificate, private key, and +// certificate chain. The certificate chain is ordered leaf to root (as sent on +// the wire) but does not include the leaf. Both client and server certificates +// use these functions. +// +// Certificates and keys may be configured before the handshake or dynamically +// in the early callback and certificate callback. + +// SSL_CTX_use_certificate sets |ctx|'s leaf certificate to |x509|. It returns +// one on success and zero on failure. +OPENSSL_EXPORT int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x509); + +// SSL_use_certificate sets |ssl|'s leaf certificate to |x509|. It returns one +// on success and zero on failure. +OPENSSL_EXPORT int SSL_use_certificate(SSL *ssl, X509 *x509); + +// SSL_CTX_use_PrivateKey sets |ctx|'s private key to |pkey|. It returns one on +// success and zero on failure. +OPENSSL_EXPORT int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); + +// SSL_use_PrivateKey sets |ssl|'s private key to |pkey|. It returns one on +// success and zero on failure. +OPENSSL_EXPORT int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); + +// SSL_CTX_set0_chain sets |ctx|'s certificate chain, excluding the leaf, to +// |chain|. On success, it returns one and takes ownership of |chain|. +// Otherwise, it returns zero. +OPENSSL_EXPORT int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain); + +// SSL_CTX_set1_chain sets |ctx|'s certificate chain, excluding the leaf, to +// |chain|. It returns one on success and zero on failure. The caller retains +// ownership of |chain| and may release it freely. +OPENSSL_EXPORT int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain); + +// SSL_set0_chain sets |ssl|'s certificate chain, excluding the leaf, to +// |chain|. On success, it returns one and takes ownership of |chain|. +// Otherwise, it returns zero. +OPENSSL_EXPORT int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain); + +// SSL_set1_chain sets |ssl|'s certificate chain, excluding the leaf, to +// |chain|. It returns one on success and zero on failure. The caller retains +// ownership of |chain| and may release it freely. +OPENSSL_EXPORT int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain); + +// SSL_CTX_add0_chain_cert appends |x509| to |ctx|'s certificate chain. On +// success, it returns one and takes ownership of |x509|. Otherwise, it returns +// zero. +OPENSSL_EXPORT int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509); + +// SSL_CTX_add1_chain_cert appends |x509| to |ctx|'s certificate chain. It +// returns one on success and zero on failure. The caller retains ownership of +// |x509| and may release it freely. +OPENSSL_EXPORT int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509); + +// SSL_add0_chain_cert appends |x509| to |ctx|'s certificate chain. On success, +// it returns one and takes ownership of |x509|. Otherwise, it returns zero. +OPENSSL_EXPORT int SSL_add0_chain_cert(SSL *ssl, X509 *x509); + +// SSL_CTX_add_extra_chain_cert calls |SSL_CTX_add0_chain_cert|. +OPENSSL_EXPORT int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509); + +// SSL_add1_chain_cert appends |x509| to |ctx|'s certificate chain. It returns +// one on success and zero on failure. The caller retains ownership of |x509| +// and may release it freely. +OPENSSL_EXPORT int SSL_add1_chain_cert(SSL *ssl, X509 *x509); + +// SSL_CTX_clear_chain_certs clears |ctx|'s certificate chain and returns +// one. +OPENSSL_EXPORT int SSL_CTX_clear_chain_certs(SSL_CTX *ctx); + +// SSL_CTX_clear_extra_chain_certs calls |SSL_CTX_clear_chain_certs|. +OPENSSL_EXPORT int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx); + +// SSL_clear_chain_certs clears |ssl|'s certificate chain and returns one. +OPENSSL_EXPORT int SSL_clear_chain_certs(SSL *ssl); + +// SSL_CTX_set_cert_cb sets a callback that is called to select a certificate. +// The callback returns one on success, zero on internal error, and a negative +// number on failure or to pause the handshake. If the handshake is paused, +// |SSL_get_error| will return |SSL_ERROR_WANT_X509_LOOKUP|. +// +// On the client, the callback may call |SSL_get0_certificate_types| and +// |SSL_get_client_CA_list| for information on the server's certificate +// request. +// +// On the server, the callback will be called after extensions have been +// processed, but before the resumption decision has been made. This differs +// from OpenSSL which handles resumption before selecting the certificate. +OPENSSL_EXPORT void SSL_CTX_set_cert_cb(SSL_CTX *ctx, + int (*cb)(SSL *ssl, void *arg), + void *arg); + +// SSL_set_cert_cb sets a callback that is called to select a certificate. The +// callback returns one on success, zero on internal error, and a negative +// number on failure or to pause the handshake. If the handshake is paused, +// |SSL_get_error| will return |SSL_ERROR_WANT_X509_LOOKUP|. +// +// On the client, the callback may call |SSL_get0_certificate_types| and +// |SSL_get_client_CA_list| for information on the server's certificate +// request. +// +// On the server, the callback will be called after extensions have been +// processed, but before the resumption decision has been made. This differs +// from OpenSSL which handles resumption before selecting the certificate. +OPENSSL_EXPORT void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), + void *arg); + +// SSL_get0_certificate_types, for a client, sets |*out_types| to an array +// containing the client certificate types requested by a server. It returns the +// length of the array. Note this list is always empty in TLS 1.3. The server +// will instead send signature algorithms. See +// |SSL_get0_peer_verify_algorithms|. +// +// The behavior of this function is undefined except during the callbacks set by +// by |SSL_CTX_set_cert_cb| and |SSL_CTX_set_client_cert_cb| or when the +// handshake is paused because of them. +OPENSSL_EXPORT size_t SSL_get0_certificate_types(const SSL *ssl, + const uint8_t **out_types); + +// SSL_get0_peer_verify_algorithms sets |*out_sigalgs| to an array containing +// the signature algorithms the peer is able to verify. It returns the length of +// the array. Note these values are only sent starting TLS 1.2 and only +// mandatory starting TLS 1.3. If not sent, the empty array is returned. For the +// historical client certificate types list, see |SSL_get0_certificate_types|. +// +// The behavior of this function is undefined except during the callbacks set by +// by |SSL_CTX_set_cert_cb| and |SSL_CTX_set_client_cert_cb| or when the +// handshake is paused because of them. +OPENSSL_EXPORT size_t +SSL_get0_peer_verify_algorithms(const SSL *ssl, const uint16_t **out_sigalgs); + +// SSL_get0_peer_delegation_algorithms sets |*out_sigalgs| to an array +// containing the signature algorithms the peer is willing to use with delegated +// credentials. It returns the length of the array. If not sent, the empty +// array is returned. +// +// The behavior of this function is undefined except during the callbacks set by +// by |SSL_CTX_set_cert_cb| and |SSL_CTX_set_client_cert_cb| or when the +// handshake is paused because of them. +OPENSSL_EXPORT size_t +SSL_get0_peer_delegation_algorithms(const SSL *ssl, + const uint16_t **out_sigalgs); + +// SSL_certs_clear resets the private key, leaf certificate, and certificate +// chain of |ssl|. +OPENSSL_EXPORT void SSL_certs_clear(SSL *ssl); + +// SSL_CTX_check_private_key returns one if the certificate and private key +// configured in |ctx| are consistent and zero otherwise. +OPENSSL_EXPORT int SSL_CTX_check_private_key(const SSL_CTX *ctx); + +// SSL_check_private_key returns one if the certificate and private key +// configured in |ssl| are consistent and zero otherwise. +OPENSSL_EXPORT int SSL_check_private_key(const SSL *ssl); + +// SSL_CTX_get0_certificate returns |ctx|'s leaf certificate. +OPENSSL_EXPORT X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx); + +// SSL_get_certificate returns |ssl|'s leaf certificate. +OPENSSL_EXPORT X509 *SSL_get_certificate(const SSL *ssl); + +// SSL_CTX_get0_privatekey returns |ctx|'s private key. +OPENSSL_EXPORT EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx); + +// SSL_get_privatekey returns |ssl|'s private key. +OPENSSL_EXPORT EVP_PKEY *SSL_get_privatekey(const SSL *ssl); + +// SSL_CTX_get0_chain_certs sets |*out_chain| to |ctx|'s certificate chain and +// returns one. +OPENSSL_EXPORT int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, + STACK_OF(X509) **out_chain); + +// SSL_CTX_get_extra_chain_certs calls |SSL_CTX_get0_chain_certs|. +OPENSSL_EXPORT int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx, + STACK_OF(X509) **out_chain); + +// SSL_get0_chain_certs sets |*out_chain| to |ssl|'s certificate chain and +// returns one. +OPENSSL_EXPORT int SSL_get0_chain_certs(const SSL *ssl, + STACK_OF(X509) **out_chain); + +// SSL_CTX_set_signed_cert_timestamp_list sets the list of signed certificate +// timestamps that is sent to clients that request it. The |list| argument must +// contain one or more SCT structures serialised as a SignedCertificateTimestamp +// List (see https://tools.ietf.org/html/rfc6962#section-3.3) – i.e. each SCT +// is prefixed by a big-endian, uint16 length and the concatenation of one or +// more such prefixed SCTs are themselves also prefixed by a uint16 length. It +// returns one on success and zero on error. The caller retains ownership of +// |list|. +OPENSSL_EXPORT int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx, + const uint8_t *list, + size_t list_len); + +// SSL_set_signed_cert_timestamp_list sets the list of signed certificate +// timestamps that is sent to clients that request is. The same format as the +// one used for |SSL_CTX_set_signed_cert_timestamp_list| applies. The caller +// retains ownership of |list|. +OPENSSL_EXPORT int SSL_set_signed_cert_timestamp_list(SSL *ctx, + const uint8_t *list, + size_t list_len); + +// SSL_CTX_set_ocsp_response sets the OCSP response that is sent to clients +// which request it. It returns one on success and zero on error. The caller +// retains ownership of |response|. +OPENSSL_EXPORT int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, + const uint8_t *response, + size_t response_len); + +// SSL_set_ocsp_response sets the OCSP response that is sent to clients which +// request it. It returns one on success and zero on error. The caller retains +// ownership of |response|. +OPENSSL_EXPORT int SSL_set_ocsp_response(SSL *ssl, + const uint8_t *response, + size_t response_len); + +// SSL_SIGN_* are signature algorithm values as defined in TLS 1.3. +#define SSL_SIGN_RSA_PKCS1_SHA1 0x0201 +#define SSL_SIGN_RSA_PKCS1_SHA256 0x0401 +#define SSL_SIGN_RSA_PKCS1_SHA384 0x0501 +#define SSL_SIGN_RSA_PKCS1_SHA512 0x0601 +#define SSL_SIGN_ECDSA_SHA1 0x0203 +#define SSL_SIGN_ECDSA_SECP256R1_SHA256 0x0403 +#define SSL_SIGN_ECDSA_SECP384R1_SHA384 0x0503 +#define SSL_SIGN_ECDSA_SECP521R1_SHA512 0x0603 +#define SSL_SIGN_RSA_PSS_RSAE_SHA256 0x0804 +#define SSL_SIGN_RSA_PSS_RSAE_SHA384 0x0805 +#define SSL_SIGN_RSA_PSS_RSAE_SHA512 0x0806 +#define SSL_SIGN_ED25519 0x0807 + +// SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal signature algorithm used to +// specify raw RSASSA-PKCS1-v1_5 with an MD5/SHA-1 concatenation, as used in TLS +// before TLS 1.2. +#define SSL_SIGN_RSA_PKCS1_MD5_SHA1 0xff01 + +// SSL_get_signature_algorithm_name returns a human-readable name for |sigalg|, +// or NULL if unknown. If |include_curve| is one, the curve for ECDSA algorithms +// is included as in TLS 1.3. Otherwise, it is excluded as in TLS 1.2. +OPENSSL_EXPORT const char *SSL_get_signature_algorithm_name(uint16_t sigalg, + int include_curve); + +// SSL_get_all_signature_algorithm_names outputs a list of possible strings +// |SSL_get_signature_algorithm_name| may return in this version of BoringSSL. +// It writes at most |max_out| entries to |out| and returns the total number it +// would have written, if |max_out| had been large enough. |max_out| may be +// initially set to zero to size the output. +// +// This function is only intended to help initialize tables in callers that want +// possible strings pre-declared. This list would not be suitable to set a list +// of supported features. It is in no particular order, and may contain +// placeholder, experimental, or deprecated values that do not apply to every +// caller. Future versions of BoringSSL may also return strings not in this +// list, so this does not apply if, say, sending strings across services. +OPENSSL_EXPORT size_t SSL_get_all_signature_algorithm_names(const char **out, + size_t max_out); + +// SSL_get_signature_algorithm_key_type returns the key type associated with +// |sigalg| as an |EVP_PKEY_*| constant or |EVP_PKEY_NONE| if unknown. +OPENSSL_EXPORT int SSL_get_signature_algorithm_key_type(uint16_t sigalg); + +// SSL_get_signature_algorithm_digest returns the digest function associated +// with |sigalg| or |NULL| if |sigalg| has no prehash (Ed25519) or is unknown. +OPENSSL_EXPORT const EVP_MD *SSL_get_signature_algorithm_digest( + uint16_t sigalg); + +// SSL_is_signature_algorithm_rsa_pss returns one if |sigalg| is an RSA-PSS +// signature algorithm and zero otherwise. +OPENSSL_EXPORT int SSL_is_signature_algorithm_rsa_pss(uint16_t sigalg); + +// SSL_CTX_set_signing_algorithm_prefs configures |ctx| to use |prefs| as the +// preference list when signing with |ctx|'s private key. It returns one on +// success and zero on error. |prefs| should not include the internal-only value +// |SSL_SIGN_RSA_PKCS1_MD5_SHA1|. +OPENSSL_EXPORT int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, + const uint16_t *prefs, + size_t num_prefs); + +// SSL_set_signing_algorithm_prefs configures |ssl| to use |prefs| as the +// preference list when signing with |ssl|'s private key. It returns one on +// success and zero on error. |prefs| should not include the internal-only value +// |SSL_SIGN_RSA_PKCS1_MD5_SHA1|. +OPENSSL_EXPORT int SSL_set_signing_algorithm_prefs(SSL *ssl, + const uint16_t *prefs, + size_t num_prefs); + + +// Certificate and private key convenience functions. + +// SSL_CTX_set_chain_and_key sets the certificate chain and private key for a +// TLS client or server. References to the given |CRYPTO_BUFFER| and |EVP_PKEY| +// objects are added as needed. Exactly one of |privkey| or |privkey_method| +// may be non-NULL. Returns one on success and zero on error. +OPENSSL_EXPORT int SSL_CTX_set_chain_and_key( + SSL_CTX *ctx, CRYPTO_BUFFER *const *certs, size_t num_certs, + EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method); + +// SSL_set_chain_and_key sets the certificate chain and private key for a TLS +// client or server. References to the given |CRYPTO_BUFFER| and |EVP_PKEY| +// objects are added as needed. Exactly one of |privkey| or |privkey_method| +// may be non-NULL. Returns one on success and zero on error. +OPENSSL_EXPORT int SSL_set_chain_and_key( + SSL *ssl, CRYPTO_BUFFER *const *certs, size_t num_certs, EVP_PKEY *privkey, + const SSL_PRIVATE_KEY_METHOD *privkey_method); + +// SSL_CTX_get0_chain returns the list of |CRYPTO_BUFFER|s that were set by +// |SSL_CTX_set_chain_and_key|. Reference counts are not incremented by this +// call. The return value may be |NULL| if no chain has been set. +// +// (Note: if a chain was configured by non-|CRYPTO_BUFFER|-based functions then +// the return value is undefined and, even if not NULL, the stack itself may +// contain nullptrs. Thus you shouldn't mix this function with +// non-|CRYPTO_BUFFER| functions for manipulating the chain.) +// +// There is no |SSL*| version of this function because connections discard +// configuration after handshaking, thus making it of questionable utility. +OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER)* + SSL_CTX_get0_chain(const SSL_CTX *ctx); + +// SSL_CTX_use_RSAPrivateKey sets |ctx|'s private key to |rsa|. It returns one +// on success and zero on failure. +OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); + +// SSL_use_RSAPrivateKey sets |ctx|'s private key to |rsa|. It returns one on +// success and zero on failure. +OPENSSL_EXPORT int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); + +// The following functions configure certificates or private keys but take as +// input DER-encoded structures. They return one on success and zero on +// failure. + +OPENSSL_EXPORT int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len, + const uint8_t *der); +OPENSSL_EXPORT int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, + size_t der_len); + +OPENSSL_EXPORT int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, + const uint8_t *der, + size_t der_len); +OPENSSL_EXPORT int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, + const uint8_t *der, size_t der_len); + +OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, + const uint8_t *der, + size_t der_len); +OPENSSL_EXPORT int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, + size_t der_len); + +// The following functions configure certificates or private keys but take as +// input files to read from. They return one on success and zero on failure. The +// |type| parameter is one of the |SSL_FILETYPE_*| values and determines whether +// the file's contents are read as PEM or DER. + +#define SSL_FILETYPE_PEM 1 +#define SSL_FILETYPE_ASN1 2 + +OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, + const char *file, + int type); +OPENSSL_EXPORT int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, + int type); + +OPENSSL_EXPORT int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, + int type); +OPENSSL_EXPORT int SSL_use_certificate_file(SSL *ssl, const char *file, + int type); + +OPENSSL_EXPORT int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, + int type); +OPENSSL_EXPORT int SSL_use_PrivateKey_file(SSL *ssl, const char *file, + int type); + +// SSL_CTX_use_certificate_chain_file configures certificates for |ctx|. It +// reads the contents of |file| as a PEM-encoded leaf certificate followed +// optionally by the certificate chain to send to the peer. It returns one on +// success and zero on failure. +OPENSSL_EXPORT int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, + const char *file); + +// SSL_CTX_set_default_passwd_cb sets the password callback for PEM-based +// convenience functions called on |ctx|. +OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, + pem_password_cb *cb); + +// SSL_CTX_get_default_passwd_cb returns the callback set by +// |SSL_CTX_set_default_passwd_cb|. +OPENSSL_EXPORT pem_password_cb *SSL_CTX_get_default_passwd_cb( + const SSL_CTX *ctx); + +// SSL_CTX_set_default_passwd_cb_userdata sets the userdata parameter for +// |ctx|'s password callback. +OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, + void *data); + +// SSL_CTX_get_default_passwd_cb_userdata returns the userdata parameter set by +// |SSL_CTX_set_default_passwd_cb_userdata|. +OPENSSL_EXPORT void *SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX *ctx); + + +// Custom private keys. + +enum ssl_private_key_result_t BORINGSSL_ENUM_INT { + ssl_private_key_success, + ssl_private_key_retry, + ssl_private_key_failure, +}; + +// ssl_private_key_method_st (aka |SSL_PRIVATE_KEY_METHOD|) describes private +// key hooks. This is used to off-load signing operations to a custom, +// potentially asynchronous, backend. Metadata about the key such as the type +// and size are parsed out of the certificate. +// +// Callers that use this structure should additionally call +// |SSL_set_signing_algorithm_prefs| or |SSL_CTX_set_signing_algorithm_prefs| +// with the private key's capabilities. This ensures BoringSSL will select a +// suitable signature algorithm for the private key. +struct ssl_private_key_method_st { + // sign signs the message |in| in using the specified signature algorithm. On + // success, it returns |ssl_private_key_success| and writes at most |max_out| + // bytes of signature data to |out| and sets |*out_len| to the number of bytes + // written. On failure, it returns |ssl_private_key_failure|. If the operation + // has not completed, it returns |ssl_private_key_retry|. |sign| should + // arrange for the high-level operation on |ssl| to be retried when the + // operation is completed. This will result in a call to |complete|. + // + // |signature_algorithm| is one of the |SSL_SIGN_*| values, as defined in TLS + // 1.3. Note that, in TLS 1.2, ECDSA algorithms do not require that curve + // sizes match hash sizes, so the curve portion of |SSL_SIGN_ECDSA_*| values + // must be ignored. BoringSSL will internally handle the curve matching logic + // where appropriate. + // + // It is an error to call |sign| while another private key operation is in + // progress on |ssl|. + enum ssl_private_key_result_t (*sign)(SSL *ssl, uint8_t *out, size_t *out_len, + size_t max_out, + uint16_t signature_algorithm, + const uint8_t *in, size_t in_len); + + // decrypt decrypts |in_len| bytes of encrypted data from |in|. On success it + // returns |ssl_private_key_success|, writes at most |max_out| bytes of + // decrypted data to |out| and sets |*out_len| to the actual number of bytes + // written. On failure it returns |ssl_private_key_failure|. If the operation + // has not completed, it returns |ssl_private_key_retry|. The caller should + // arrange for the high-level operation on |ssl| to be retried when the + // operation is completed, which will result in a call to |complete|. This + // function only works with RSA keys and should perform a raw RSA decryption + // operation with no padding. + // + // It is an error to call |decrypt| while another private key operation is in + // progress on |ssl|. + enum ssl_private_key_result_t (*decrypt)(SSL *ssl, uint8_t *out, + size_t *out_len, size_t max_out, + const uint8_t *in, size_t in_len); + + // complete completes a pending operation. If the operation has completed, it + // returns |ssl_private_key_success| and writes the result to |out| as in + // |sign|. Otherwise, it returns |ssl_private_key_failure| on failure and + // |ssl_private_key_retry| if the operation is still in progress. + // + // |complete| may be called arbitrarily many times before completion, but it + // is an error to call |complete| if there is no pending operation in progress + // on |ssl|. + enum ssl_private_key_result_t (*complete)(SSL *ssl, uint8_t *out, + size_t *out_len, size_t max_out); +}; + +// SSL_set_private_key_method configures a custom private key on |ssl|. +// |key_method| must remain valid for the lifetime of |ssl|. +OPENSSL_EXPORT void SSL_set_private_key_method( + SSL *ssl, const SSL_PRIVATE_KEY_METHOD *key_method); + +// SSL_CTX_set_private_key_method configures a custom private key on |ctx|. +// |key_method| must remain valid for the lifetime of |ctx|. +OPENSSL_EXPORT void SSL_CTX_set_private_key_method( + SSL_CTX *ctx, const SSL_PRIVATE_KEY_METHOD *key_method); + +// SSL_can_release_private_key returns one if |ssl| will no longer call into the +// private key and zero otherwise. If the function returns one, the caller can +// release state associated with the private key. +// +// NOTE: This function assumes the caller does not use |SSL_clear| to reuse +// |ssl| for a second connection. If |SSL_clear| is used, BoringSSL may still +// use the private key on the second connection. +OPENSSL_EXPORT int SSL_can_release_private_key(const SSL *ssl); + + +// Cipher suites. +// +// |SSL_CIPHER| objects represent cipher suites. + +DEFINE_CONST_STACK_OF(SSL_CIPHER) + +// SSL_get_cipher_by_value returns the structure representing a TLS cipher +// suite based on its assigned number, or NULL if unknown. See +// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4. +OPENSSL_EXPORT const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value); + +// SSL_CIPHER_get_id returns |cipher|'s non-IANA id. This is not its +// IANA-assigned number, which is called the "value" here, although it may be +// cast to a |uint16_t| to get it. +OPENSSL_EXPORT uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_protocol_id returns |cipher|'s IANA-assigned number. +OPENSSL_EXPORT uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *cipher); + +// SSL_CIPHER_is_aead returns one if |cipher| uses an AEAD cipher. +OPENSSL_EXPORT int SSL_CIPHER_is_aead(const SSL_CIPHER *cipher); + +// SSL_CIPHER_is_block_cipher returns one if |cipher| is a block cipher. +OPENSSL_EXPORT int SSL_CIPHER_is_block_cipher(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_cipher_nid returns the NID for |cipher|'s bulk +// cipher. Possible values are |NID_aes_128_gcm|, |NID_aes_256_gcm|, +// |NID_chacha20_poly1305|, |NID_aes_128_cbc|, |NID_aes_256_cbc|, and +// |NID_des_ede3_cbc|. +OPENSSL_EXPORT int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_digest_nid returns the NID for |cipher|'s HMAC if it is a +// legacy cipher suite. For modern AEAD-based ciphers (see +// |SSL_CIPHER_is_aead|), it returns |NID_undef|. +// +// Note this function only returns the legacy HMAC digest, not the PRF hash. +OPENSSL_EXPORT int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_kx_nid returns the NID for |cipher|'s key exchange. This may +// be |NID_kx_rsa|, |NID_kx_ecdhe|, or |NID_kx_psk| for TLS 1.2. In TLS 1.3, +// cipher suites do not specify the key exchange, so this function returns +// |NID_kx_any|. +OPENSSL_EXPORT int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_auth_nid returns the NID for |cipher|'s authentication +// type. This may be |NID_auth_rsa|, |NID_auth_ecdsa|, or |NID_auth_psk| for TLS +// 1.2. In TLS 1.3, cipher suites do not specify authentication, so this +// function returns |NID_auth_any|. +OPENSSL_EXPORT int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_prf_nid retuns the NID for |cipher|'s PRF hash. If |cipher| is +// a pre-TLS-1.2 cipher, it returns |NID_md5_sha1| but note these ciphers use +// SHA-256 in TLS 1.2. Other return values may be treated uniformly in all +// applicable versions. +OPENSSL_EXPORT int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_min_version returns the minimum protocol version required +// for |cipher|. +OPENSSL_EXPORT uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_max_version returns the maximum protocol version that +// supports |cipher|. +OPENSSL_EXPORT uint16_t SSL_CIPHER_get_max_version(const SSL_CIPHER *cipher); + +// SSL_CIPHER_standard_name returns the standard IETF name for |cipher|. For +// example, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256". +OPENSSL_EXPORT const char *SSL_CIPHER_standard_name(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_name returns the OpenSSL name of |cipher|. For example, +// "ECDHE-RSA-AES128-GCM-SHA256". Callers are recommended to use +// |SSL_CIPHER_standard_name| instead. +OPENSSL_EXPORT const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_kx_name returns a string that describes the key-exchange +// method used by |cipher|. For example, "ECDHE_ECDSA". TLS 1.3 AEAD-only +// ciphers return the string "GENERIC". +OPENSSL_EXPORT const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher); + +// SSL_CIPHER_get_bits returns the strength, in bits, of |cipher|. If +// |out_alg_bits| is not NULL, it writes the number of bits consumed by the +// symmetric algorithm to |*out_alg_bits|. +OPENSSL_EXPORT int SSL_CIPHER_get_bits(const SSL_CIPHER *cipher, + int *out_alg_bits); + +// SSL_get_all_cipher_names outputs a list of possible strings +// |SSL_CIPHER_get_name| may return in this version of BoringSSL. It writes at +// most |max_out| entries to |out| and returns the total number it would have +// written, if |max_out| had been large enough. |max_out| may be initially set +// to zero to size the output. +// +// This function is only intended to help initialize tables in callers that want +// possible strings pre-declared. This list would not be suitable to set a list +// of supported features. It is in no particular order, and may contain +// placeholder, experimental, or deprecated values that do not apply to every +// caller. Future versions of BoringSSL may also return strings not in this +// list, so this does not apply if, say, sending strings across services. +OPENSSL_EXPORT size_t SSL_get_all_cipher_names(const char **out, + size_t max_out); + + +// SSL_get_all_standard_cipher_names outputs a list of possible strings +// |SSL_CIPHER_standard_name| may return in this version of BoringSSL. It writes +// at most |max_out| entries to |out| and returns the total number it would have +// written, if |max_out| had been large enough. |max_out| may be initially set +// to zero to size the output. +// +// This function is only intended to help initialize tables in callers that want +// possible strings pre-declared. This list would not be suitable to set a list +// of supported features. It is in no particular order, and may contain +// placeholder, experimental, or deprecated values that do not apply to every +// caller. Future versions of BoringSSL may also return strings not in this +// list, so this does not apply if, say, sending strings across services. +OPENSSL_EXPORT size_t SSL_get_all_standard_cipher_names(const char **out, + size_t max_out); + + +// Cipher suite configuration. +// +// OpenSSL uses a mini-language to configure cipher suites. The language +// maintains an ordered list of enabled ciphers, along with an ordered list of +// disabled but available ciphers. Initially, all ciphers are disabled with a +// default ordering. The cipher string is then interpreted as a sequence of +// directives, separated by colons, each of which modifies this state. +// +// Most directives consist of a one character or empty opcode followed by a +// selector which matches a subset of available ciphers. +// +// Available opcodes are: +// +// The empty opcode enables and appends all matching disabled ciphers to the +// end of the enabled list. The newly appended ciphers are ordered relative to +// each other matching their order in the disabled list. +// +// |-| disables all matching enabled ciphers and prepends them to the disabled +// list, with relative order from the enabled list preserved. This means the +// most recently disabled ciphers get highest preference relative to other +// disabled ciphers if re-enabled. +// +// |+| moves all matching enabled ciphers to the end of the enabled list, with +// relative order preserved. +// +// |!| deletes all matching ciphers, enabled or not, from either list. Deleted +// ciphers will not matched by future operations. +// +// A selector may be a specific cipher (using either the standard or OpenSSL +// name for the cipher) or one or more rules separated by |+|. The final +// selector matches the intersection of each rule. For instance, |AESGCM+aECDSA| +// matches ECDSA-authenticated AES-GCM ciphers. +// +// Available cipher rules are: +// +// |ALL| matches all ciphers, except for deprecated ciphers which must be +// named explicitly. +// +// |kRSA|, |kDHE|, |kECDHE|, and |kPSK| match ciphers using plain RSA, DHE, +// ECDHE, and plain PSK key exchanges, respectively. Note that ECDHE_PSK is +// matched by |kECDHE| and not |kPSK|. +// +// |aRSA|, |aECDSA|, and |aPSK| match ciphers authenticated by RSA, ECDSA, and +// a pre-shared key, respectively. +// +// |RSA|, |DHE|, |ECDHE|, |PSK|, |ECDSA|, and |PSK| are aliases for the +// corresponding |k*| or |a*| cipher rule. |RSA| is an alias for |kRSA|, not +// |aRSA|. +// +// |3DES|, |AES128|, |AES256|, |AES|, |AESGCM|, |CHACHA20| match ciphers +// whose bulk cipher use the corresponding encryption scheme. Note that +// |AES|, |AES128|, and |AES256| match both CBC and GCM ciphers. +// +// |SHA1|, and its alias |SHA|, match legacy cipher suites using HMAC-SHA1. +// +// Deprecated cipher rules: +// +// |kEDH|, |EDH|, |kEECDH|, and |EECDH| are legacy aliases for |kDHE|, |DHE|, +// |kECDHE|, and |ECDHE|, respectively. +// +// |HIGH| is an alias for |ALL|. +// +// |FIPS| is an alias for |HIGH|. +// +// |SSLv3| and |TLSv1| match ciphers available in TLS 1.1 or earlier. +// |TLSv1_2| matches ciphers new in TLS 1.2. This is confusing and should not +// be used. +// +// Unknown rules are silently ignored by legacy APIs, and rejected by APIs with +// "strict" in the name, which should be preferred. Cipher lists can be long +// and it's easy to commit typos. Strict functions will also reject the use of +// spaces, semi-colons and commas as alternative separators. +// +// The special |@STRENGTH| directive will sort all enabled ciphers by strength. +// +// The |DEFAULT| directive, when appearing at the front of the string, expands +// to the default ordering of available ciphers. +// +// If configuring a server, one may also configure equal-preference groups to +// partially respect the client's preferences when +// |SSL_OP_CIPHER_SERVER_PREFERENCE| is enabled. Ciphers in an equal-preference +// group have equal priority and use the client order. This may be used to +// enforce that AEADs are preferred but select AES-GCM vs. ChaCha20-Poly1305 +// based on client preferences. An equal-preference is specified with square +// brackets, combining multiple selectors separated by |. For example: +// +// [TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256|TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] +// +// Once an equal-preference group is used, future directives must be +// opcode-less. Inside an equal-preference group, spaces are not allowed. +// +// TLS 1.3 ciphers do not participate in this mechanism and instead have a +// built-in preference order. Functions to set cipher lists do not affect TLS +// 1.3, and functions to query the cipher list do not include TLS 1.3 ciphers. + +// SSL_DEFAULT_CIPHER_LIST is the default cipher suite configuration. It is +// substituted when a cipher string starts with 'DEFAULT'. +#define SSL_DEFAULT_CIPHER_LIST "ALL" + +// SSL_CTX_set_strict_cipher_list configures the cipher list for |ctx|, +// evaluating |str| as a cipher string and returning error if |str| contains +// anything meaningless. It returns one on success and zero on failure. +OPENSSL_EXPORT int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx, + const char *str); + +// SSL_CTX_set_cipher_list configures the cipher list for |ctx|, evaluating +// |str| as a cipher string. It returns one on success and zero on failure. +// +// Prefer to use |SSL_CTX_set_strict_cipher_list|. This function tolerates +// garbage inputs, unless an empty cipher list results. +OPENSSL_EXPORT int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str); + +// SSL_set_strict_cipher_list configures the cipher list for |ssl|, evaluating +// |str| as a cipher string and returning error if |str| contains anything +// meaningless. It returns one on success and zero on failure. +OPENSSL_EXPORT int SSL_set_strict_cipher_list(SSL *ssl, const char *str); + +// SSL_set_cipher_list configures the cipher list for |ssl|, evaluating |str| as +// a cipher string. It returns one on success and zero on failure. +// +// Prefer to use |SSL_set_strict_cipher_list|. This function tolerates garbage +// inputs, unless an empty cipher list results. +OPENSSL_EXPORT int SSL_set_cipher_list(SSL *ssl, const char *str); + +// SSL_CTX_get_ciphers returns the cipher list for |ctx|, in order of +// preference. +OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx); + +// SSL_CTX_cipher_in_group returns one if the |i|th cipher (see +// |SSL_CTX_get_ciphers|) is in the same equipreference group as the one +// following it and zero otherwise. +OPENSSL_EXPORT int SSL_CTX_cipher_in_group(const SSL_CTX *ctx, size_t i); + +// SSL_get_ciphers returns the cipher list for |ssl|, in order of preference. +OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl); + + +// Connection information. + +// SSL_is_init_finished returns one if |ssl| has completed its initial handshake +// and has no pending handshake. It returns zero otherwise. +OPENSSL_EXPORT int SSL_is_init_finished(const SSL *ssl); + +// SSL_in_init returns one if |ssl| has a pending handshake and zero +// otherwise. +OPENSSL_EXPORT int SSL_in_init(const SSL *ssl); + +// SSL_in_false_start returns one if |ssl| has a pending handshake that is in +// False Start. |SSL_write| may be called at this point without waiting for the +// peer, but |SSL_read| will complete the handshake before accepting application +// data. +// +// See also |SSL_MODE_ENABLE_FALSE_START|. +OPENSSL_EXPORT int SSL_in_false_start(const SSL *ssl); + +// SSL_get_peer_certificate returns the peer's leaf certificate or NULL if the +// peer did not use certificates. The caller must call |X509_free| on the +// result to release it. +OPENSSL_EXPORT X509 *SSL_get_peer_certificate(const SSL *ssl); + +// SSL_get_peer_cert_chain returns the peer's certificate chain or NULL if +// unavailable or the peer did not use certificates. This is the unverified list +// of certificates as sent by the peer, not the final chain built during +// verification. The caller does not take ownership of the result. +// +// WARNING: This function behaves differently between client and server. If +// |ssl| is a server, the returned chain does not include the leaf certificate. +// If a client, it does. +OPENSSL_EXPORT STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl); + +// SSL_get_peer_full_cert_chain returns the peer's certificate chain, or NULL if +// unavailable or the peer did not use certificates. This is the unverified list +// of certificates as sent by the peer, not the final chain built during +// verification. The caller does not take ownership of the result. +// +// This is the same as |SSL_get_peer_cert_chain| except that this function +// always returns the full chain, i.e. the first element of the return value +// (if any) will be the leaf certificate. In constrast, +// |SSL_get_peer_cert_chain| returns only the intermediate certificates if the +// |ssl| is a server. +OPENSSL_EXPORT STACK_OF(X509) *SSL_get_peer_full_cert_chain(const SSL *ssl); + +// SSL_get0_peer_certificates returns the peer's certificate chain, or NULL if +// unavailable or the peer did not use certificates. This is the unverified list +// of certificates as sent by the peer, not the final chain built during +// verification. The caller does not take ownership of the result. +// +// This is the |CRYPTO_BUFFER| variant of |SSL_get_peer_full_cert_chain|. +OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) * + SSL_get0_peer_certificates(const SSL *ssl); + +// SSL_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to point to +// |*out_len| bytes of SCT information from the server. This is only valid if +// |ssl| is a client. The SCT information is a SignedCertificateTimestampList +// (including the two leading length bytes). +// See https://tools.ietf.org/html/rfc6962#section-3.3 +// If no SCT was received then |*out_len| will be zero on return. +// +// WARNING: the returned data is not guaranteed to be well formed. +OPENSSL_EXPORT void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, + const uint8_t **out, + size_t *out_len); + +// SSL_get0_ocsp_response sets |*out| and |*out_len| to point to |*out_len| +// bytes of an OCSP response from the server. This is the DER encoding of an +// OCSPResponse type as defined in RFC 2560. +// +// WARNING: the returned data is not guaranteed to be well formed. +OPENSSL_EXPORT void SSL_get0_ocsp_response(const SSL *ssl, const uint8_t **out, + size_t *out_len); + +// SSL_get_tls_unique writes at most |max_out| bytes of the tls-unique value +// for |ssl| to |out| and sets |*out_len| to the number of bytes written. It +// returns one on success or zero on error. In general |max_out| should be at +// least 12. +// +// This function will always fail if the initial handshake has not completed. +// The tls-unique value will change after a renegotiation but, since +// renegotiations can be initiated by the server at any point, the higher-level +// protocol must either leave them disabled or define states in which the +// tls-unique value can be read. +// +// The tls-unique value is defined by +// https://tools.ietf.org/html/rfc5929#section-3.1. Due to a weakness in the +// TLS protocol, tls-unique is broken for resumed connections unless the +// Extended Master Secret extension is negotiated. Thus this function will +// return zero if |ssl| performed session resumption unless EMS was used when +// negotiating the original session. +OPENSSL_EXPORT int SSL_get_tls_unique(const SSL *ssl, uint8_t *out, + size_t *out_len, size_t max_out); + +// SSL_get_extms_support returns one if the Extended Master Secret extension or +// TLS 1.3 was negotiated. Otherwise, it returns zero. +OPENSSL_EXPORT int SSL_get_extms_support(const SSL *ssl); + +// SSL_get_current_cipher returns cipher suite used by |ssl|, or NULL if it has +// not been negotiated yet. +OPENSSL_EXPORT const SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl); + +// SSL_session_reused returns one if |ssl| performed an abbreviated handshake +// and zero otherwise. +// +// TODO(davidben): Hammer down the semantics of this API while a handshake, +// initial or renego, is in progress. +OPENSSL_EXPORT int SSL_session_reused(const SSL *ssl); + +// SSL_get_secure_renegotiation_support returns one if the peer supports secure +// renegotiation (RFC 5746) or TLS 1.3. Otherwise, it returns zero. +OPENSSL_EXPORT int SSL_get_secure_renegotiation_support(const SSL *ssl); + +// SSL_export_keying_material exports a value derived from the master secret, as +// specified in RFC 5705. It writes |out_len| bytes to |out| given a label and +// optional context. (Since a zero length context is allowed, the |use_context| +// flag controls whether a context is included.) +// +// It returns one on success and zero otherwise. +OPENSSL_EXPORT int SSL_export_keying_material( + SSL *ssl, uint8_t *out, size_t out_len, const char *label, size_t label_len, + const uint8_t *context, size_t context_len, int use_context); + + +// Sessions. +// +// An |SSL_SESSION| represents an SSL session that may be resumed in an +// abbreviated handshake. It is reference-counted and immutable. Once +// established, an |SSL_SESSION| may be shared by multiple |SSL| objects on +// different threads and must not be modified. +// +// Note the TLS notion of "session" is not suitable for application-level +// session state. It is an optional caching mechanism for the handshake. Not all +// connections within an application-level session will reuse TLS sessions. TLS +// sessions may be dropped by the client or ignored by the server at any time. + +DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) + +// SSL_SESSION_new returns a newly-allocated blank |SSL_SESSION| or NULL on +// error. This may be useful when writing tests but should otherwise not be +// used. +OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx); + +// SSL_SESSION_up_ref increments the reference count of |session| and returns +// one. +OPENSSL_EXPORT int SSL_SESSION_up_ref(SSL_SESSION *session); + +// SSL_SESSION_free decrements the reference count of |session|. If it reaches +// zero, all data referenced by |session| and |session| itself are released. +OPENSSL_EXPORT void SSL_SESSION_free(SSL_SESSION *session); + +// SSL_SESSION_to_bytes serializes |in| into a newly allocated buffer and sets +// |*out_data| to that buffer and |*out_len| to its length. The caller takes +// ownership of the buffer and must call |OPENSSL_free| when done. It returns +// one on success and zero on error. +OPENSSL_EXPORT int SSL_SESSION_to_bytes(const SSL_SESSION *in, + uint8_t **out_data, size_t *out_len); + +// SSL_SESSION_to_bytes_for_ticket serializes |in|, but excludes the session +// identification information, namely the session ID and ticket. +OPENSSL_EXPORT int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, + uint8_t **out_data, + size_t *out_len); + +// SSL_SESSION_from_bytes parses |in_len| bytes from |in| as an SSL_SESSION. It +// returns a newly-allocated |SSL_SESSION| on success or NULL on error. +OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes( + const uint8_t *in, size_t in_len, const SSL_CTX *ctx); + +// SSL_SESSION_get_version returns a string describing the TLS or DTLS version +// |session| was established at. For example, "TLSv1.2" or "DTLSv1". +OPENSSL_EXPORT const char *SSL_SESSION_get_version(const SSL_SESSION *session); + +// SSL_SESSION_get_protocol_version returns the TLS or DTLS version |session| +// was established at. +OPENSSL_EXPORT uint16_t +SSL_SESSION_get_protocol_version(const SSL_SESSION *session); + +// SSL_SESSION_set_protocol_version sets |session|'s TLS or DTLS version to +// |version|. This may be useful when writing tests but should otherwise not be +// used. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_SESSION_set_protocol_version(SSL_SESSION *session, + uint16_t version); + +// SSL_MAX_SSL_SESSION_ID_LENGTH is the maximum length of an SSL session ID. +#define SSL_MAX_SSL_SESSION_ID_LENGTH 32 + +// SSL_SESSION_get_id returns a pointer to a buffer containing |session|'s +// session ID and sets |*out_len| to its length. +// +// This function should only be used for implementing a TLS session cache. TLS +// sessions are not suitable for application-level session state, and a session +// ID is an implementation detail of the TLS resumption handshake mechanism. Not +// all resumption flows use session IDs, and not all connections within an +// application-level session will reuse TLS sessions. +// +// To determine if resumption occurred, use |SSL_session_reused| instead. +// Comparing session IDs will not give the right result in all cases. +// +// As a workaround for some broken applications, BoringSSL sometimes synthesizes +// arbitrary session IDs for non-ID-based sessions. This behavior may be +// removed in the future. +OPENSSL_EXPORT const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session, + unsigned *out_len); + +// SSL_SESSION_set1_id sets |session|'s session ID to |sid|, It returns one on +// success and zero on error. This function may be useful in writing tests but +// otherwise should not be used. +OPENSSL_EXPORT int SSL_SESSION_set1_id(SSL_SESSION *session, const uint8_t *sid, + size_t sid_len); + +// SSL_SESSION_get_time returns the time at which |session| was established in +// seconds since the UNIX epoch. +OPENSSL_EXPORT uint64_t SSL_SESSION_get_time(const SSL_SESSION *session); + +// SSL_SESSION_get_timeout returns the lifetime of |session| in seconds. +OPENSSL_EXPORT uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session); + +// SSL_SESSION_get0_peer returns the peer leaf certificate stored in +// |session|. +// +// TODO(davidben): This should return a const X509 *. +OPENSSL_EXPORT X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session); + +// SSL_SESSION_get0_peer_certificates returns the peer certificate chain stored +// in |session|, or NULL if the peer did not use certificates. This is the +// unverified list of certificates as sent by the peer, not the final chain +// built during verification. The caller does not take ownership of the result. +OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) * + SSL_SESSION_get0_peer_certificates(const SSL_SESSION *session); + +// SSL_SESSION_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to +// point to |*out_len| bytes of SCT information stored in |session|. This is +// only valid for client sessions. The SCT information is a +// SignedCertificateTimestampList (including the two leading length bytes). See +// https://tools.ietf.org/html/rfc6962#section-3.3 If no SCT was received then +// |*out_len| will be zero on return. +// +// WARNING: the returned data is not guaranteed to be well formed. +OPENSSL_EXPORT void SSL_SESSION_get0_signed_cert_timestamp_list( + const SSL_SESSION *session, const uint8_t **out, size_t *out_len); + +// SSL_SESSION_get0_ocsp_response sets |*out| and |*out_len| to point to +// |*out_len| bytes of an OCSP response from the server. This is the DER +// encoding of an OCSPResponse type as defined in RFC 2560. +// +// WARNING: the returned data is not guaranteed to be well formed. +OPENSSL_EXPORT void SSL_SESSION_get0_ocsp_response(const SSL_SESSION *session, + const uint8_t **out, + size_t *out_len); + +// SSL_MAX_MASTER_KEY_LENGTH is the maximum length of a master secret. +#define SSL_MAX_MASTER_KEY_LENGTH 48 + +// SSL_SESSION_get_master_key writes up to |max_out| bytes of |session|'s secret +// to |out| and returns the number of bytes written. If |max_out| is zero, it +// returns the size of the secret. +OPENSSL_EXPORT size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, + uint8_t *out, size_t max_out); + +// SSL_SESSION_set_time sets |session|'s creation time to |time| and returns +// |time|. This function may be useful in writing tests but otherwise should not +// be used. +OPENSSL_EXPORT uint64_t SSL_SESSION_set_time(SSL_SESSION *session, + uint64_t time); + +// SSL_SESSION_set_timeout sets |session|'s timeout to |timeout| and returns +// one. This function may be useful in writing tests but otherwise should not +// be used. +OPENSSL_EXPORT uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, + uint32_t timeout); + +// SSL_SESSION_get0_id_context returns a pointer to a buffer containing +// |session|'s session ID context (see |SSL_CTX_set_session_id_context|) and +// sets |*out_len| to its length. +OPENSSL_EXPORT const uint8_t *SSL_SESSION_get0_id_context( + const SSL_SESSION *session, unsigned *out_len); + +// SSL_SESSION_set1_id_context sets |session|'s session ID context (see +// |SSL_CTX_set_session_id_context|) to |sid_ctx|. It returns one on success and +// zero on error. This function may be useful in writing tests but otherwise +// should not be used. +OPENSSL_EXPORT int SSL_SESSION_set1_id_context(SSL_SESSION *session, + const uint8_t *sid_ctx, + size_t sid_ctx_len); + +// SSL_SESSION_should_be_single_use returns one if |session| should be +// single-use (TLS 1.3 and later) and zero otherwise. +// +// If this function returns one, clients retain multiple sessions and use each +// only once. This prevents passive observers from correlating connections with +// tickets. See RFC 8446, appendix C.4. If it returns zero, |session| cannot be +// used without leaking a correlator. +OPENSSL_EXPORT int SSL_SESSION_should_be_single_use(const SSL_SESSION *session); + +// SSL_SESSION_is_resumable returns one if |session| is complete and contains a +// session ID or ticket. It returns zero otherwise. Note this function does not +// ensure |session| will be resumed. It may be expired, dropped by the server, +// or associated with incompatible parameters. +OPENSSL_EXPORT int SSL_SESSION_is_resumable(const SSL_SESSION *session); + +// SSL_SESSION_has_ticket returns one if |session| has a ticket and zero +// otherwise. +OPENSSL_EXPORT int SSL_SESSION_has_ticket(const SSL_SESSION *session); + +// SSL_SESSION_get0_ticket sets |*out_ticket| and |*out_len| to |session|'s +// ticket, or NULL and zero if it does not have one. |out_ticket| may be NULL +// if only the ticket length is needed. +OPENSSL_EXPORT void SSL_SESSION_get0_ticket(const SSL_SESSION *session, + const uint8_t **out_ticket, + size_t *out_len); + +// SSL_SESSION_set_ticket sets |session|'s ticket to |ticket|. It returns one on +// success and zero on error. This function may be useful in writing tests but +// otherwise should not be used. +OPENSSL_EXPORT int SSL_SESSION_set_ticket(SSL_SESSION *session, + const uint8_t *ticket, + size_t ticket_len); + +// SSL_SESSION_get_ticket_lifetime_hint returns ticket lifetime hint of +// |session| in seconds or zero if none was set. +OPENSSL_EXPORT uint32_t +SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session); + +// SSL_SESSION_get0_cipher returns the cipher negotiated by the connection which +// established |session|. +// +// Note that, in TLS 1.3, there is no guarantee that resumptions with |session| +// will use that cipher. Prefer calling |SSL_get_current_cipher| on the |SSL| +// instead. +OPENSSL_EXPORT const SSL_CIPHER *SSL_SESSION_get0_cipher( + const SSL_SESSION *session); + +// SSL_SESSION_has_peer_sha256 returns one if |session| has a SHA-256 hash of +// the peer's certificate retained and zero if the peer did not present a +// certificate or if this was not enabled when |session| was created. See also +// |SSL_CTX_set_retain_only_sha256_of_client_certs|. +OPENSSL_EXPORT int SSL_SESSION_has_peer_sha256(const SSL_SESSION *session); + +// SSL_SESSION_get0_peer_sha256 sets |*out_ptr| and |*out_len| to the SHA-256 +// hash of the peer certificate retained in |session|, or NULL and zero if it +// does not have one. See also |SSL_CTX_set_retain_only_sha256_of_client_certs|. +OPENSSL_EXPORT void SSL_SESSION_get0_peer_sha256(const SSL_SESSION *session, + const uint8_t **out_ptr, + size_t *out_len); + + +// Session caching. +// +// Session caching allows connections to be established more efficiently based +// on saved parameters from a previous connection, called a session (see +// |SSL_SESSION|). The client offers a saved session, using an opaque identifier +// from a previous connection. The server may accept the session, if it has the +// parameters available. Otherwise, it will decline and continue with a full +// handshake. +// +// This requires both the client and the server to retain session state. A +// client does so with a stateful session cache. A server may do the same or, if +// supported by both sides, statelessly using session tickets. For more +// information on the latter, see the next section. +// +// For a server, the library implements a built-in internal session cache as an +// in-memory hash table. Servers may also use |SSL_CTX_sess_set_get_cb| and +// |SSL_CTX_sess_set_new_cb| to implement a custom external session cache. In +// particular, this may be used to share a session cache between multiple +// servers in a large deployment. An external cache may be used in addition to +// or instead of the internal one. Use |SSL_CTX_set_session_cache_mode| to +// toggle the internal cache. +// +// For a client, the only option is an external session cache. Clients may use +// |SSL_CTX_sess_set_new_cb| to register a callback for when new sessions are +// available. These may be cached and, in subsequent compatible connections, +// configured with |SSL_set_session|. +// +// Note that offering or accepting a session short-circuits certificate +// verification and most parameter negotiation. Resuming sessions across +// different contexts may result in security failures and surprising +// behavior. For a typical client, this means sessions for different hosts must +// be cached under different keys. A client that connects to the same host with, +// e.g., different cipher suite settings or client certificates should also use +// separate session caches between those contexts. Servers should also partition +// session caches between SNI hosts with |SSL_CTX_set_session_id_context|. +// +// Note also, in TLS 1.2 and earlier, offering sessions allows passive observers +// to correlate different client connections. TLS 1.3 and later fix this, +// provided clients use sessions at most once. Session caches are managed by the +// caller in BoringSSL, so this must be implemented externally. See +// |SSL_SESSION_should_be_single_use| for details. + +// SSL_SESS_CACHE_OFF disables all session caching. +#define SSL_SESS_CACHE_OFF 0x0000 + +// SSL_SESS_CACHE_CLIENT enables session caching for a client. The internal +// cache is never used on a client, so this only enables the callbacks. +#define SSL_SESS_CACHE_CLIENT 0x0001 + +// SSL_SESS_CACHE_SERVER enables session caching for a server. +#define SSL_SESS_CACHE_SERVER 0x0002 + +// SSL_SESS_CACHE_BOTH enables session caching for both client and server. +#define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_SERVER) + +// SSL_SESS_CACHE_NO_AUTO_CLEAR disables automatically calling +// |SSL_CTX_flush_sessions| every 255 connections. +#define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080 + +// SSL_SESS_CACHE_NO_INTERNAL_LOOKUP, on a server, disables looking up a session +// from the internal session cache. +#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100 + +// SSL_SESS_CACHE_NO_INTERNAL_STORE, on a server, disables storing sessions in +// the internal session cache. +#define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200 + +// SSL_SESS_CACHE_NO_INTERNAL, on a server, disables the internal session +// cache. +#define SSL_SESS_CACHE_NO_INTERNAL \ + (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | SSL_SESS_CACHE_NO_INTERNAL_STORE) + +// SSL_CTX_set_session_cache_mode sets the session cache mode bits for |ctx| to +// |mode|. It returns the previous value. +OPENSSL_EXPORT int SSL_CTX_set_session_cache_mode(SSL_CTX *ctx, int mode); + +// SSL_CTX_get_session_cache_mode returns the session cache mode bits for +// |ctx| +OPENSSL_EXPORT int SSL_CTX_get_session_cache_mode(const SSL_CTX *ctx); + +// SSL_set_session, for a client, configures |ssl| to offer to resume |session| +// in the initial handshake and returns one. The caller retains ownership of +// |session|. Note that configuring a session assumes the authentication in the +// session is valid. For callers that wish to revalidate the session before +// offering, see |SSL_SESSION_get0_peer_certificates|, +// |SSL_SESSION_get0_signed_cert_timestamp_list|, and +// |SSL_SESSION_get0_ocsp_response|. +// +// It is an error to call this function after the handshake has begun. +OPENSSL_EXPORT int SSL_set_session(SSL *ssl, SSL_SESSION *session); + +// SSL_DEFAULT_SESSION_TIMEOUT is the default lifetime, in seconds, of a +// session in TLS 1.2 or earlier. This is how long we are willing to use the +// secret to encrypt traffic without fresh key material. +#define SSL_DEFAULT_SESSION_TIMEOUT (2 * 60 * 60) + +// SSL_DEFAULT_SESSION_PSK_DHE_TIMEOUT is the default lifetime, in seconds, of a +// session for TLS 1.3 psk_dhe_ke. This is how long we are willing to use the +// secret as an authenticator. +#define SSL_DEFAULT_SESSION_PSK_DHE_TIMEOUT (2 * 24 * 60 * 60) + +// SSL_DEFAULT_SESSION_AUTH_TIMEOUT is the default non-renewable lifetime, in +// seconds, of a TLS 1.3 session. This is how long we are willing to trust the +// signature in the initial handshake. +#define SSL_DEFAULT_SESSION_AUTH_TIMEOUT (7 * 24 * 60 * 60) + +// SSL_CTX_set_timeout sets the lifetime, in seconds, of TLS 1.2 (or earlier) +// sessions created in |ctx| to |timeout|. +OPENSSL_EXPORT uint32_t SSL_CTX_set_timeout(SSL_CTX *ctx, uint32_t timeout); + +// SSL_CTX_set_session_psk_dhe_timeout sets the lifetime, in seconds, of TLS 1.3 +// sessions created in |ctx| to |timeout|. +OPENSSL_EXPORT void SSL_CTX_set_session_psk_dhe_timeout(SSL_CTX *ctx, + uint32_t timeout); + +// SSL_CTX_get_timeout returns the lifetime, in seconds, of TLS 1.2 (or earlier) +// sessions created in |ctx|. +OPENSSL_EXPORT uint32_t SSL_CTX_get_timeout(const SSL_CTX *ctx); + +// SSL_MAX_SID_CTX_LENGTH is the maximum length of a session ID context. +#define SSL_MAX_SID_CTX_LENGTH 32 + +// SSL_CTX_set_session_id_context sets |ctx|'s session ID context to |sid_ctx|. +// It returns one on success and zero on error. The session ID context is an +// application-defined opaque byte string. A session will not be used in a +// connection without a matching session ID context. +// +// For a server, if |SSL_VERIFY_PEER| is enabled, it is an error to not set a +// session ID context. +OPENSSL_EXPORT int SSL_CTX_set_session_id_context(SSL_CTX *ctx, + const uint8_t *sid_ctx, + size_t sid_ctx_len); + +// SSL_set_session_id_context sets |ssl|'s session ID context to |sid_ctx|. It +// returns one on success and zero on error. See also +// |SSL_CTX_set_session_id_context|. +OPENSSL_EXPORT int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx, + size_t sid_ctx_len); + +// SSL_get0_session_id_context returns a pointer to |ssl|'s session ID context +// and sets |*out_len| to its length. It returns NULL on error. +OPENSSL_EXPORT const uint8_t *SSL_get0_session_id_context(const SSL *ssl, + size_t *out_len); + +// SSL_SESSION_CACHE_MAX_SIZE_DEFAULT is the default maximum size of a session +// cache. +#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024 * 20) + +// SSL_CTX_sess_set_cache_size sets the maximum size of |ctx|'s internal session +// cache to |size|. It returns the previous value. +OPENSSL_EXPORT unsigned long SSL_CTX_sess_set_cache_size(SSL_CTX *ctx, + unsigned long size); + +// SSL_CTX_sess_get_cache_size returns the maximum size of |ctx|'s internal +// session cache. +OPENSSL_EXPORT unsigned long SSL_CTX_sess_get_cache_size(const SSL_CTX *ctx); + +// SSL_CTX_sess_number returns the number of sessions in |ctx|'s internal +// session cache. +OPENSSL_EXPORT size_t SSL_CTX_sess_number(const SSL_CTX *ctx); + +// SSL_CTX_add_session inserts |session| into |ctx|'s internal session cache. It +// returns one on success and zero on error or if |session| is already in the +// cache. The caller retains its reference to |session|. +OPENSSL_EXPORT int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session); + +// SSL_CTX_remove_session removes |session| from |ctx|'s internal session cache. +// It returns one on success and zero if |session| was not in the cache. +OPENSSL_EXPORT int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session); + +// SSL_CTX_flush_sessions removes all sessions from |ctx| which have expired as +// of time |time|. If |time| is zero, all sessions are removed. +OPENSSL_EXPORT void SSL_CTX_flush_sessions(SSL_CTX *ctx, uint64_t time); + +// SSL_CTX_sess_set_new_cb sets the callback to be called when a new session is +// established and ready to be cached. If the session cache is disabled (the +// appropriate one of |SSL_SESS_CACHE_CLIENT| or |SSL_SESS_CACHE_SERVER| is +// unset), the callback is not called. +// +// The callback is passed a reference to |session|. It returns one if it takes +// ownership (and then calls |SSL_SESSION_free| when done) and zero otherwise. A +// consumer which places |session| into an in-memory cache will likely return +// one, with the cache calling |SSL_SESSION_free|. A consumer which serializes +// |session| with |SSL_SESSION_to_bytes| may not need to retain |session| and +// will likely return zero. Returning one is equivalent to calling +// |SSL_SESSION_up_ref| and then returning zero. +// +// Note: For a client, the callback may be called on abbreviated handshakes if a +// ticket is renewed. Further, it may not be called until some time after +// |SSL_do_handshake| or |SSL_connect| completes if False Start is enabled. Thus +// it's recommended to use this callback over calling |SSL_get_session| on +// handshake completion. +OPENSSL_EXPORT void SSL_CTX_sess_set_new_cb( + SSL_CTX *ctx, int (*new_session_cb)(SSL *ssl, SSL_SESSION *session)); + +// SSL_CTX_sess_get_new_cb returns the callback set by +// |SSL_CTX_sess_set_new_cb|. +OPENSSL_EXPORT int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))( + SSL *ssl, SSL_SESSION *session); + +// SSL_CTX_sess_set_remove_cb sets a callback which is called when a session is +// removed from the internal session cache. +// +// TODO(davidben): What is the point of this callback? It seems useless since it +// only fires on sessions in the internal cache. +OPENSSL_EXPORT void SSL_CTX_sess_set_remove_cb( + SSL_CTX *ctx, + void (*remove_session_cb)(SSL_CTX *ctx, SSL_SESSION *session)); + +// SSL_CTX_sess_get_remove_cb returns the callback set by +// |SSL_CTX_sess_set_remove_cb|. +OPENSSL_EXPORT void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))( + SSL_CTX *ctx, SSL_SESSION *session); + +// SSL_CTX_sess_set_get_cb sets a callback to look up a session by ID for a +// server. The callback is passed the session ID and should return a matching +// |SSL_SESSION| or NULL if not found. It should set |*out_copy| to zero and +// return a new reference to the session. This callback is not used for a +// client. +// +// For historical reasons, if |*out_copy| is set to one (default), the SSL +// library will take a new reference to the returned |SSL_SESSION|, expecting +// the callback to return a non-owning pointer. This is not recommended. If +// |ctx| and thus the callback is used on multiple threads, the session may be +// removed and invalidated before the SSL library calls |SSL_SESSION_up_ref|, +// whereas the callback may synchronize internally. +// +// To look up a session asynchronously, the callback may return +// |SSL_magic_pending_session_ptr|. See the documentation for that function and +// |SSL_ERROR_PENDING_SESSION|. +// +// If the internal session cache is enabled, the callback is only consulted if +// the internal cache does not return a match. +OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb( + SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(SSL *ssl, const uint8_t *id, + int id_len, int *out_copy)); + +// SSL_CTX_sess_get_get_cb returns the callback set by +// |SSL_CTX_sess_set_get_cb|. +OPENSSL_EXPORT SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))( + SSL *ssl, const uint8_t *id, int id_len, int *out_copy); + +// SSL_magic_pending_session_ptr returns a magic |SSL_SESSION|* which indicates +// that the session isn't currently unavailable. |SSL_get_error| will then +// return |SSL_ERROR_PENDING_SESSION| and the handshake can be retried later +// when the lookup has completed. +OPENSSL_EXPORT SSL_SESSION *SSL_magic_pending_session_ptr(void); + + +// Session tickets. +// +// Session tickets, from RFC 5077, allow session resumption without server-side +// state. The server maintains a secret ticket key and sends the client opaque +// encrypted session parameters, called a ticket. When offering the session, the +// client sends the ticket which the server decrypts to recover session state. +// Session tickets are enabled by default but may be disabled with +// |SSL_OP_NO_TICKET|. +// +// On the client, ticket-based sessions use the same APIs as ID-based tickets. +// Callers do not need to handle them differently. +// +// On the server, tickets are encrypted and authenticated with a secret key. +// By default, an |SSL_CTX| will manage session ticket encryption keys by +// generating them internally and rotating every 48 hours. Tickets are minted +// and processed transparently. The following functions may be used to configure +// a persistent key or implement more custom behavior, including key rotation +// and sharing keys between multiple servers in a large deployment. There are +// three levels of customisation possible: +// +// 1) One can simply set the keys with |SSL_CTX_set_tlsext_ticket_keys|. +// 2) One can configure an |EVP_CIPHER_CTX| and |HMAC_CTX| directly for +// encryption and authentication. +// 3) One can configure an |SSL_TICKET_AEAD_METHOD| to have more control +// and the option of asynchronous decryption. +// +// An attacker that compromises a server's session ticket key can impersonate +// the server and, prior to TLS 1.3, retroactively decrypt all application +// traffic from sessions using that ticket key. Thus ticket keys must be +// regularly rotated for forward secrecy. Note the default key is rotated +// automatically once every 48 hours but manually configured keys are not. + +// SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL is the interval with which the +// default session ticket encryption key is rotated, if in use. If any +// non-default ticket encryption mechanism is configured, automatic rotation is +// disabled. +#define SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL (2 * 24 * 60 * 60) + +// SSL_CTX_get_tlsext_ticket_keys writes |ctx|'s session ticket key material to +// |len| bytes of |out|. It returns one on success and zero if |len| is not +// 48. If |out| is NULL, it returns 48 instead. +OPENSSL_EXPORT int SSL_CTX_get_tlsext_ticket_keys(SSL_CTX *ctx, void *out, + size_t len); + +// SSL_CTX_set_tlsext_ticket_keys sets |ctx|'s session ticket key material to +// |len| bytes of |in|. It returns one on success and zero if |len| is not +// 48. If |in| is NULL, it returns 48 instead. +OPENSSL_EXPORT int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in, + size_t len); + +// SSL_TICKET_KEY_NAME_LEN is the length of the key name prefix of a session +// ticket. +#define SSL_TICKET_KEY_NAME_LEN 16 + +// SSL_CTX_set_tlsext_ticket_key_cb sets the ticket callback to |callback| and +// returns one. |callback| will be called when encrypting a new ticket and when +// decrypting a ticket from the client. +// +// In both modes, |ctx| and |hmac_ctx| will already have been initialized with +// |EVP_CIPHER_CTX_init| and |HMAC_CTX_init|, respectively. |callback| +// configures |hmac_ctx| with an HMAC digest and key, and configures |ctx| +// for encryption or decryption, based on the mode. +// +// When encrypting a new ticket, |encrypt| will be one. It writes a public +// 16-byte key name to |key_name| and a fresh IV to |iv|. The output IV length +// must match |EVP_CIPHER_CTX_iv_length| of the cipher selected. In this mode, +// |callback| returns 1 on success and -1 on error. +// +// When decrypting a ticket, |encrypt| will be zero. |key_name| will point to a +// 16-byte key name and |iv| points to an IV. The length of the IV consumed must +// match |EVP_CIPHER_CTX_iv_length| of the cipher selected. In this mode, +// |callback| returns -1 to abort the handshake, 0 if decrypting the ticket +// failed, and 1 or 2 on success. If it returns 2, the ticket will be renewed. +// This may be used to re-key the ticket. +// +// WARNING: |callback| wildly breaks the usual return value convention and is +// called in two different modes. +OPENSSL_EXPORT int SSL_CTX_set_tlsext_ticket_key_cb( + SSL_CTX *ctx, int (*callback)(SSL *ssl, uint8_t *key_name, uint8_t *iv, + EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx, + int encrypt)); + +// ssl_ticket_aead_result_t enumerates the possible results from decrypting a +// ticket with an |SSL_TICKET_AEAD_METHOD|. +enum ssl_ticket_aead_result_t BORINGSSL_ENUM_INT { + // ssl_ticket_aead_success indicates that the ticket was successfully + // decrypted. + ssl_ticket_aead_success, + // ssl_ticket_aead_retry indicates that the operation could not be + // immediately completed and must be reattempted, via |open|, at a later + // point. + ssl_ticket_aead_retry, + // ssl_ticket_aead_ignore_ticket indicates that the ticket should be ignored + // (i.e. is corrupt or otherwise undecryptable). + ssl_ticket_aead_ignore_ticket, + // ssl_ticket_aead_error indicates that a fatal error occured and the + // handshake should be terminated. + ssl_ticket_aead_error, +}; + +// ssl_ticket_aead_method_st (aka |SSL_TICKET_AEAD_METHOD|) contains methods +// for encrypting and decrypting session tickets. +struct ssl_ticket_aead_method_st { + // max_overhead returns the maximum number of bytes of overhead that |seal| + // may add. + size_t (*max_overhead)(SSL *ssl); + + // seal encrypts and authenticates |in_len| bytes from |in|, writes, at most, + // |max_out_len| bytes to |out|, and puts the number of bytes written in + // |*out_len|. The |in| and |out| buffers may be equal but will not otherwise + // alias. It returns one on success or zero on error. + int (*seal)(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out_len, + const uint8_t *in, size_t in_len); + + // open authenticates and decrypts |in_len| bytes from |in|, writes, at most, + // |max_out_len| bytes of plaintext to |out|, and puts the number of bytes + // written in |*out_len|. The |in| and |out| buffers may be equal but will + // not otherwise alias. See |ssl_ticket_aead_result_t| for details of the + // return values. In the case that a retry is indicated, the caller should + // arrange for the high-level operation on |ssl| to be retried when the + // operation is completed, which will result in another call to |open|. + enum ssl_ticket_aead_result_t (*open)(SSL *ssl, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t *in, + size_t in_len); +}; + +// SSL_CTX_set_ticket_aead_method configures a custom ticket AEAD method table +// on |ctx|. |aead_method| must remain valid for the lifetime of |ctx|. +OPENSSL_EXPORT void SSL_CTX_set_ticket_aead_method( + SSL_CTX *ctx, const SSL_TICKET_AEAD_METHOD *aead_method); + +// SSL_process_tls13_new_session_ticket processes an unencrypted TLS 1.3 +// NewSessionTicket message from |buf| and returns a resumable |SSL_SESSION|, +// or NULL on error. The caller takes ownership of the returned session and +// must call |SSL_SESSION_free| to free it. +// +// |buf| contains |buf_len| bytes that represents a complete NewSessionTicket +// message including its header, i.e., one byte for the type (0x04) and three +// bytes for the length. |buf| must contain only one such message. +// +// This function may be used to process NewSessionTicket messages in TLS 1.3 +// clients that are handling the record layer externally. +OPENSSL_EXPORT SSL_SESSION *SSL_process_tls13_new_session_ticket( + SSL *ssl, const uint8_t *buf, size_t buf_len); + +// SSL_CTX_set_num_tickets configures |ctx| to send |num_tickets| immediately +// after a successful TLS 1.3 handshake as a server. It returns one. Large +// values of |num_tickets| will be capped within the library. +// +// By default, BoringSSL sends two tickets. +OPENSSL_EXPORT int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets); + +// SSL_CTX_get_num_tickets returns the number of tickets |ctx| will send +// immediately after a successful TLS 1.3 handshake as a server. +OPENSSL_EXPORT size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx); + + +// Elliptic curve Diffie-Hellman. +// +// Cipher suites using an ECDHE key exchange perform Diffie-Hellman over an +// elliptic curve negotiated by both endpoints. See RFC 4492. Only named curves +// are supported. ECDHE is always enabled, but the curve preferences may be +// configured with these functions. +// +// Note that TLS 1.3 renames these from curves to groups. For consistency, we +// currently use the TLS 1.2 name in the API. + +// SSL_CTX_set1_curves sets the preferred curves for |ctx| to be |curves|. Each +// element of |curves| should be a curve nid. It returns one on success and +// zero on failure. +// +// Note that this API uses nid values from nid.h and not the |SSL_CURVE_*| +// values defined below. +OPENSSL_EXPORT int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves, + size_t curves_len); + +// SSL_set1_curves sets the preferred curves for |ssl| to be |curves|. Each +// element of |curves| should be a curve nid. It returns one on success and +// zero on failure. +// +// Note that this API uses nid values from nid.h and not the |SSL_CURVE_*| +// values defined below. +OPENSSL_EXPORT int SSL_set1_curves(SSL *ssl, const int *curves, + size_t curves_len); + +// SSL_CTX_set1_curves_list sets the preferred curves for |ctx| to be the +// colon-separated list |curves|. Each element of |curves| should be a curve +// name (e.g. P-256, X25519, ...). It returns one on success and zero on +// failure. +OPENSSL_EXPORT int SSL_CTX_set1_curves_list(SSL_CTX *ctx, const char *curves); + +// SSL_set1_curves_list sets the preferred curves for |ssl| to be the +// colon-separated list |curves|. Each element of |curves| should be a curve +// name (e.g. P-256, X25519, ...). It returns one on success and zero on +// failure. +OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves); + +// SSL_CURVE_* define TLS curve IDs. +#define SSL_CURVE_SECP224R1 21 +#define SSL_CURVE_SECP256R1 23 +#define SSL_CURVE_SECP384R1 24 +#define SSL_CURVE_SECP521R1 25 +#define SSL_CURVE_X25519 29 +#define SSL_CURVE_X25519_KYBER768_DRAFT00 0x6399 + +// SSL_get_curve_id returns the ID of the curve used by |ssl|'s most recently +// completed handshake or 0 if not applicable. +// +// TODO(davidben): This API currently does not work correctly if there is a +// renegotiation in progress. Fix this. +OPENSSL_EXPORT uint16_t SSL_get_curve_id(const SSL *ssl); + +// SSL_get_curve_name returns a human-readable name for the curve specified by +// the given TLS curve id, or NULL if the curve is unknown. +OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t curve_id); + +// SSL_get_all_curve_names outputs a list of possible strings +// |SSL_get_curve_name| may return in this version of BoringSSL. It writes at +// most |max_out| entries to |out| and returns the total number it would have +// written, if |max_out| had been large enough. |max_out| may be initially set +// to zero to size the output. +// +// This function is only intended to help initialize tables in callers that want +// possible strings pre-declared. This list would not be suitable to set a list +// of supported features. It is in no particular order, and may contain +// placeholder, experimental, or deprecated values that do not apply to every +// caller. Future versions of BoringSSL may also return strings not in this +// list, so this does not apply if, say, sending strings across services. +OPENSSL_EXPORT size_t SSL_get_all_curve_names(const char **out, size_t max_out); + +// SSL_CTX_set1_groups calls |SSL_CTX_set1_curves|. +OPENSSL_EXPORT int SSL_CTX_set1_groups(SSL_CTX *ctx, const int *groups, + size_t groups_len); + +// SSL_set1_groups calls |SSL_set1_curves|. +OPENSSL_EXPORT int SSL_set1_groups(SSL *ssl, const int *groups, + size_t groups_len); + +// SSL_CTX_set1_groups_list calls |SSL_CTX_set1_curves_list|. +OPENSSL_EXPORT int SSL_CTX_set1_groups_list(SSL_CTX *ctx, const char *groups); + +// SSL_set1_groups_list calls |SSL_set1_curves_list|. +OPENSSL_EXPORT int SSL_set1_groups_list(SSL *ssl, const char *groups); + + +// Certificate verification. +// +// SSL may authenticate either endpoint with an X.509 certificate. Typically +// this is used to authenticate the server to the client. These functions +// configure certificate verification. +// +// WARNING: By default, certificate verification errors on a client are not +// fatal. See |SSL_VERIFY_NONE| This may be configured with +// |SSL_CTX_set_verify|. +// +// By default clients are anonymous but a server may request a certificate from +// the client by setting |SSL_VERIFY_PEER|. +// +// Many of these functions use OpenSSL's legacy X.509 stack which is +// underdocumented and deprecated, but the replacement isn't ready yet. For +// now, consumers may use the existing stack or bypass it by performing +// certificate verification externally. This may be done with +// |SSL_CTX_set_cert_verify_callback| or by extracting the chain with +// |SSL_get_peer_cert_chain| after the handshake. In the future, functions will +// be added to use the SSL stack without dependency on any part of the legacy +// X.509 and ASN.1 stack. +// +// To augment certificate verification, a client may also enable OCSP stapling +// (RFC 6066) and Certificate Transparency (RFC 6962) extensions. + +// SSL_VERIFY_NONE, on a client, verifies the server certificate but does not +// make errors fatal. The result may be checked with |SSL_get_verify_result|. On +// a server it does not request a client certificate. This is the default. +#define SSL_VERIFY_NONE 0x00 + +// SSL_VERIFY_PEER, on a client, makes server certificate errors fatal. On a +// server it requests a client certificate and makes errors fatal. However, +// anonymous clients are still allowed. See +// |SSL_VERIFY_FAIL_IF_NO_PEER_CERT|. +#define SSL_VERIFY_PEER 0x01 + +// SSL_VERIFY_FAIL_IF_NO_PEER_CERT configures a server to reject connections if +// the client declines to send a certificate. This flag must be used together +// with |SSL_VERIFY_PEER|, otherwise it won't work. +#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 + +// SSL_VERIFY_PEER_IF_NO_OBC configures a server to request a client certificate +// if and only if Channel ID is not negotiated. +#define SSL_VERIFY_PEER_IF_NO_OBC 0x04 + +// SSL_CTX_set_verify configures certificate verification behavior. |mode| is +// one of the |SSL_VERIFY_*| values defined above. |callback|, if not NULL, is +// used to customize certificate verification, but is deprecated. See +// |X509_STORE_CTX_set_verify_cb| for details. +// +// The callback may use |SSL_get_ex_data_X509_STORE_CTX_idx| with +// |X509_STORE_CTX_get_ex_data| to look up the |SSL| from |store_ctx|. +// +// WARNING: |callback| should be NULL. This callback does not replace the +// default certificate verification process and is, instead, called multiple +// times in the course of that process. It is very difficult to implement this +// callback safely, without inadvertently relying on implementation details or +// making incorrect assumptions about when the callback is called. +// +// Instead, use |SSL_CTX_set_custom_verify| or +// |SSL_CTX_set_cert_verify_callback| to customize certificate verification. +// Those callbacks can inspect the peer-sent chain, call |X509_verify_cert| and +// inspect the result, or perform other operations more straightforwardly. +// +// TODO(crbug.com/boringssl/426): We cite |X509_STORE_CTX_set_verify_cb| but +// haven't documented it yet. Later that will have a more detailed warning about +// why one should not use this callback. +OPENSSL_EXPORT void SSL_CTX_set_verify( + SSL_CTX *ctx, int mode, int (*callback)(int ok, X509_STORE_CTX *store_ctx)); + +// SSL_set_verify configures certificate verification behavior. |mode| is one of +// the |SSL_VERIFY_*| values defined above. |callback|, if not NULL, is used to +// customize certificate verification, but is deprecated. See the behavior of +// |X509_STORE_CTX_set_verify_cb|. +// +// The callback may use |SSL_get_ex_data_X509_STORE_CTX_idx| with +// |X509_STORE_CTX_get_ex_data| to look up the |SSL| from |store_ctx|. +// +// WARNING: |callback| should be NULL. This callback does not replace the +// default certificate verification process and is, instead, called multiple +// times in the course of that process. It is very difficult to implement this +// callback safely, without inadvertently relying on implementation details or +// making incorrect assumptions about when the callback is called. +// +// Instead, use |SSL_set_custom_verify| or |SSL_CTX_set_cert_verify_callback| to +// customize certificate verification. Those callbacks can inspect the peer-sent +// chain, call |X509_verify_cert| and inspect the result, or perform other +// operations more straightforwardly. +// +// TODO(crbug.com/boringssl/426): We cite |X509_STORE_CTX_set_verify_cb| but +// haven't documented it yet. Later that will have a more detailed warning about +// why one should not use this callback. +OPENSSL_EXPORT void SSL_set_verify(SSL *ssl, int mode, + int (*callback)(int ok, + X509_STORE_CTX *store_ctx)); + +enum ssl_verify_result_t BORINGSSL_ENUM_INT { + ssl_verify_ok, + ssl_verify_invalid, + ssl_verify_retry, +}; + +// SSL_CTX_set_custom_verify configures certificate verification. |mode| is one +// of the |SSL_VERIFY_*| values defined above. |callback| performs the +// certificate verification. +// +// The callback may call |SSL_get0_peer_certificates| for the certificate chain +// to validate. The callback should return |ssl_verify_ok| if the certificate is +// valid. If the certificate is invalid, the callback should return +// |ssl_verify_invalid| and optionally set |*out_alert| to an alert to send to +// the peer. Some useful alerts include |SSL_AD_CERTIFICATE_EXPIRED|, +// |SSL_AD_CERTIFICATE_REVOKED|, |SSL_AD_UNKNOWN_CA|, |SSL_AD_BAD_CERTIFICATE|, +// |SSL_AD_CERTIFICATE_UNKNOWN|, and |SSL_AD_INTERNAL_ERROR|. See RFC 5246 +// section 7.2.2 for their precise meanings. If unspecified, +// |SSL_AD_CERTIFICATE_UNKNOWN| will be sent by default. +// +// To verify a certificate asynchronously, the callback may return +// |ssl_verify_retry|. The handshake will then pause with |SSL_get_error| +// returning |SSL_ERROR_WANT_CERTIFICATE_VERIFY|. +OPENSSL_EXPORT void SSL_CTX_set_custom_verify( + SSL_CTX *ctx, int mode, + enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert)); + +// SSL_set_custom_verify behaves like |SSL_CTX_set_custom_verify| but configures +// an individual |SSL|. +OPENSSL_EXPORT void SSL_set_custom_verify( + SSL *ssl, int mode, + enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert)); + +// SSL_CTX_get_verify_mode returns |ctx|'s verify mode, set by +// |SSL_CTX_set_verify|. +OPENSSL_EXPORT int SSL_CTX_get_verify_mode(const SSL_CTX *ctx); + +// SSL_get_verify_mode returns |ssl|'s verify mode, set by |SSL_CTX_set_verify| +// or |SSL_set_verify|. It returns -1 on error. +OPENSSL_EXPORT int SSL_get_verify_mode(const SSL *ssl); + +// SSL_CTX_get_verify_callback returns the callback set by +// |SSL_CTX_set_verify|. +OPENSSL_EXPORT int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))( + int ok, X509_STORE_CTX *store_ctx); + +// SSL_get_verify_callback returns the callback set by |SSL_CTX_set_verify| or +// |SSL_set_verify|. +OPENSSL_EXPORT int (*SSL_get_verify_callback(const SSL *ssl))( + int ok, X509_STORE_CTX *store_ctx); + +// SSL_set1_host sets a DNS name that will be required to be present in the +// verified leaf certificate. It returns one on success and zero on error. +// +// Note: unless _some_ name checking is performed, certificate validation is +// ineffective. Simply checking that a host has some certificate from a CA is +// rarely meaningful—you have to check that the CA believed that the host was +// who you expect to be talking to. +OPENSSL_EXPORT int SSL_set1_host(SSL *ssl, const char *hostname); + +// SSL_CTX_set_verify_depth sets the maximum depth of a certificate chain +// accepted in verification. This number does not include the leaf, so a depth +// of 1 allows the leaf and one CA certificate. +OPENSSL_EXPORT void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); + +// SSL_set_verify_depth sets the maximum depth of a certificate chain accepted +// in verification. This number does not include the leaf, so a depth of 1 +// allows the leaf and one CA certificate. +OPENSSL_EXPORT void SSL_set_verify_depth(SSL *ssl, int depth); + +// SSL_CTX_get_verify_depth returns the maximum depth of a certificate accepted +// in verification. +OPENSSL_EXPORT int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); + +// SSL_get_verify_depth returns the maximum depth of a certificate accepted in +// verification. +OPENSSL_EXPORT int SSL_get_verify_depth(const SSL *ssl); + +// SSL_CTX_set1_param sets verification parameters from |param|. It returns one +// on success and zero on failure. The caller retains ownership of |param|. +OPENSSL_EXPORT int SSL_CTX_set1_param(SSL_CTX *ctx, + const X509_VERIFY_PARAM *param); + +// SSL_set1_param sets verification parameters from |param|. It returns one on +// success and zero on failure. The caller retains ownership of |param|. +OPENSSL_EXPORT int SSL_set1_param(SSL *ssl, + const X509_VERIFY_PARAM *param); + +// SSL_CTX_get0_param returns |ctx|'s |X509_VERIFY_PARAM| for certificate +// verification. The caller must not release the returned pointer but may call +// functions on it to configure it. +OPENSSL_EXPORT X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx); + +// SSL_get0_param returns |ssl|'s |X509_VERIFY_PARAM| for certificate +// verification. The caller must not release the returned pointer but may call +// functions on it to configure it. +OPENSSL_EXPORT X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); + +// SSL_CTX_set_purpose sets |ctx|'s |X509_VERIFY_PARAM|'s 'purpose' parameter to +// |purpose|. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose); + +// SSL_set_purpose sets |ssl|'s |X509_VERIFY_PARAM|'s 'purpose' parameter to +// |purpose|. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_set_purpose(SSL *ssl, int purpose); + +// SSL_CTX_set_trust sets |ctx|'s |X509_VERIFY_PARAM|'s 'trust' parameter to +// |trust|. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_CTX_set_trust(SSL_CTX *ctx, int trust); + +// SSL_set_trust sets |ssl|'s |X509_VERIFY_PARAM|'s 'trust' parameter to +// |trust|. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_set_trust(SSL *ssl, int trust); + +// SSL_CTX_set_cert_store sets |ctx|'s certificate store to |store|. It takes +// ownership of |store|. The store is used for certificate verification. +// +// The store is also used for the auto-chaining feature, but this is deprecated. +// See also |SSL_MODE_NO_AUTO_CHAIN|. +OPENSSL_EXPORT void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store); + +// SSL_CTX_get_cert_store returns |ctx|'s certificate store. +OPENSSL_EXPORT X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx); + +// SSL_CTX_set_default_verify_paths loads the OpenSSL system-default trust +// anchors into |ctx|'s store. It returns one on success and zero on failure. +OPENSSL_EXPORT int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); + +// SSL_CTX_load_verify_locations loads trust anchors into |ctx|'s store from +// |ca_file| and |ca_dir|, either of which may be NULL. If |ca_file| is passed, +// it is opened and PEM-encoded CA certificates are read. If |ca_dir| is passed, +// it is treated as a directory in OpenSSL's hashed directory format. It returns +// one on success and zero on failure. +// +// See +// https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_load_verify_locations.html +// for documentation on the directory format. +OPENSSL_EXPORT int SSL_CTX_load_verify_locations(SSL_CTX *ctx, + const char *ca_file, + const char *ca_dir); + +// SSL_get_verify_result returns the result of certificate verification. It is +// either |X509_V_OK| or a |X509_V_ERR_*| value. +OPENSSL_EXPORT long SSL_get_verify_result(const SSL *ssl); + +// SSL_alert_from_verify_result returns the SSL alert code, such as +// |SSL_AD_CERTIFICATE_EXPIRED|, that corresponds to an |X509_V_ERR_*| value. +// The return value is always an alert, even when |result| is |X509_V_OK|. +OPENSSL_EXPORT int SSL_alert_from_verify_result(long result); + +// SSL_get_ex_data_X509_STORE_CTX_idx returns the ex_data index used to look up +// the |SSL| associated with an |X509_STORE_CTX| in the verify callback. +OPENSSL_EXPORT int SSL_get_ex_data_X509_STORE_CTX_idx(void); + +// SSL_CTX_set_cert_verify_callback sets a custom callback to be called on +// certificate verification rather than |X509_verify_cert|. |store_ctx| contains +// the verification parameters. The callback should return one on success and +// zero on fatal error. It may use |X509_STORE_CTX_set_error| to set a +// verification result. +// +// The callback may use |SSL_get_ex_data_X509_STORE_CTX_idx| to recover the +// |SSL| object from |store_ctx|. +OPENSSL_EXPORT void SSL_CTX_set_cert_verify_callback( + SSL_CTX *ctx, int (*callback)(X509_STORE_CTX *store_ctx, void *arg), + void *arg); + +// SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end +// of a connection) to request SCTs from the server. See +// https://tools.ietf.org/html/rfc6962. +// +// Call |SSL_get0_signed_cert_timestamp_list| to recover the SCT after the +// handshake. +OPENSSL_EXPORT void SSL_enable_signed_cert_timestamps(SSL *ssl); + +// SSL_CTX_enable_signed_cert_timestamps enables SCT requests on all client SSL +// objects created from |ctx|. +// +// Call |SSL_get0_signed_cert_timestamp_list| to recover the SCT after the +// handshake. +OPENSSL_EXPORT void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx); + +// SSL_enable_ocsp_stapling causes |ssl| (which must be the client end of a +// connection) to request a stapled OCSP response from the server. +// +// Call |SSL_get0_ocsp_response| to recover the OCSP response after the +// handshake. +OPENSSL_EXPORT void SSL_enable_ocsp_stapling(SSL *ssl); + +// SSL_CTX_enable_ocsp_stapling enables OCSP stapling on all client SSL objects +// created from |ctx|. +// +// Call |SSL_get0_ocsp_response| to recover the OCSP response after the +// handshake. +OPENSSL_EXPORT void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx); + +// SSL_CTX_set0_verify_cert_store sets an |X509_STORE| that will be used +// exclusively for certificate verification and returns one. Ownership of +// |store| is transferred to the |SSL_CTX|. +OPENSSL_EXPORT int SSL_CTX_set0_verify_cert_store(SSL_CTX *ctx, + X509_STORE *store); + +// SSL_CTX_set1_verify_cert_store sets an |X509_STORE| that will be used +// exclusively for certificate verification and returns one. An additional +// reference to |store| will be taken. +OPENSSL_EXPORT int SSL_CTX_set1_verify_cert_store(SSL_CTX *ctx, + X509_STORE *store); + +// SSL_set0_verify_cert_store sets an |X509_STORE| that will be used +// exclusively for certificate verification and returns one. Ownership of +// |store| is transferred to the |SSL|. +OPENSSL_EXPORT int SSL_set0_verify_cert_store(SSL *ssl, X509_STORE *store); + +// SSL_set1_verify_cert_store sets an |X509_STORE| that will be used +// exclusively for certificate verification and returns one. An additional +// reference to |store| will be taken. +OPENSSL_EXPORT int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store); + +// SSL_CTX_set_verify_algorithm_prefs configures |ctx| to use |prefs| as the +// preference list when verifying signatures from the peer's long-term key. It +// returns one on zero on error. |prefs| should not include the internal-only +// value |SSL_SIGN_RSA_PKCS1_MD5_SHA1|. +OPENSSL_EXPORT int SSL_CTX_set_verify_algorithm_prefs(SSL_CTX *ctx, + const uint16_t *prefs, + size_t num_prefs); + +// SSL_set_verify_algorithm_prefs configures |ssl| to use |prefs| as the +// preference list when verifying signatures from the peer's long-term key. It +// returns one on zero on error. |prefs| should not include the internal-only +// value |SSL_SIGN_RSA_PKCS1_MD5_SHA1|. +OPENSSL_EXPORT int SSL_set_verify_algorithm_prefs(SSL *ssl, + const uint16_t *prefs, + size_t num_prefs); + +// SSL_set_hostflags calls |X509_VERIFY_PARAM_set_hostflags| on the +// |X509_VERIFY_PARAM| associated with this |SSL*|. The |flags| argument +// should be one of the |X509_CHECK_*| constants. +OPENSSL_EXPORT void SSL_set_hostflags(SSL *ssl, unsigned flags); + + +// Client certificate CA list. +// +// When requesting a client certificate, a server may advertise a list of +// certificate authorities which are accepted. These functions may be used to +// configure this list. + +// SSL_set_client_CA_list sets |ssl|'s client certificate CA list to +// |name_list|. It takes ownership of |name_list|. +OPENSSL_EXPORT void SSL_set_client_CA_list(SSL *ssl, + STACK_OF(X509_NAME) *name_list); + +// SSL_CTX_set_client_CA_list sets |ctx|'s client certificate CA list to +// |name_list|. It takes ownership of |name_list|. +OPENSSL_EXPORT void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, + STACK_OF(X509_NAME) *name_list); + +// SSL_set0_client_CAs sets |ssl|'s client certificate CA list to |name_list|, +// which should contain DER-encoded distinguished names (RFC 5280). It takes +// ownership of |name_list|. +OPENSSL_EXPORT void SSL_set0_client_CAs(SSL *ssl, + STACK_OF(CRYPTO_BUFFER) *name_list); + +// SSL_CTX_set0_client_CAs sets |ctx|'s client certificate CA list to +// |name_list|, which should contain DER-encoded distinguished names (RFC 5280). +// It takes ownership of |name_list|. +OPENSSL_EXPORT void SSL_CTX_set0_client_CAs(SSL_CTX *ctx, + STACK_OF(CRYPTO_BUFFER) *name_list); + +// SSL_get_client_CA_list returns |ssl|'s client certificate CA list. If |ssl| +// has not been configured as a client, this is the list configured by +// |SSL_CTX_set_client_CA_list|. +// +// If configured as a client, it returns the client certificate CA list sent by +// the server. In this mode, the behavior is undefined except during the +// callbacks set by |SSL_CTX_set_cert_cb| and |SSL_CTX_set_client_cert_cb| or +// when the handshake is paused because of them. +OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl); + +// SSL_get0_server_requested_CAs returns the CAs sent by a server to guide a +// client in certificate selection. They are a series of DER-encoded X.509 +// names. This function may only be called during a callback set by +// |SSL_CTX_set_cert_cb| or when the handshake is paused because of it. +// +// The returned stack is owned by |ssl|, as are its contents. It should not be +// used past the point where the handshake is restarted after the callback. +OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) * + SSL_get0_server_requested_CAs(const SSL *ssl); + +// SSL_CTX_get_client_CA_list returns |ctx|'s client certificate CA list. +OPENSSL_EXPORT STACK_OF(X509_NAME) * + SSL_CTX_get_client_CA_list(const SSL_CTX *ctx); + +// SSL_add_client_CA appends |x509|'s subject to the client certificate CA list. +// It returns one on success or zero on error. The caller retains ownership of +// |x509|. +OPENSSL_EXPORT int SSL_add_client_CA(SSL *ssl, X509 *x509); + +// SSL_CTX_add_client_CA appends |x509|'s subject to the client certificate CA +// list. It returns one on success or zero on error. The caller retains +// ownership of |x509|. +OPENSSL_EXPORT int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x509); + +// SSL_load_client_CA_file opens |file| and reads PEM-encoded certificates from +// it. It returns a newly-allocated stack of the certificate subjects or NULL +// on error. Duplicates in |file| are ignored. +OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); + +// SSL_dup_CA_list makes a deep copy of |list|. It returns the new list on +// success or NULL on allocation error. +OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *list); + +// SSL_add_file_cert_subjects_to_stack behaves like |SSL_load_client_CA_file| +// but appends the result to |out|. It returns one on success or zero on +// error. +OPENSSL_EXPORT int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *out, + const char *file); + +// SSL_add_bio_cert_subjects_to_stack behaves like +// |SSL_add_file_cert_subjects_to_stack| but reads from |bio|. +OPENSSL_EXPORT int SSL_add_bio_cert_subjects_to_stack(STACK_OF(X509_NAME) *out, + BIO *bio); + + +// Server name indication. +// +// The server_name extension (RFC 3546) allows the client to advertise the name +// of the server it is connecting to. This is used in virtual hosting +// deployments to select one of a several certificates on a single IP. Only the +// host_name name type is supported. + +#define TLSEXT_NAMETYPE_host_name 0 + +// SSL_set_tlsext_host_name, for a client, configures |ssl| to advertise |name| +// in the server_name extension. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_set_tlsext_host_name(SSL *ssl, const char *name); + +// SSL_get_servername, for a server, returns the hostname supplied by the +// client or NULL if there was none. The |type| argument must be +// |TLSEXT_NAMETYPE_host_name|. +OPENSSL_EXPORT const char *SSL_get_servername(const SSL *ssl, const int type); + +// SSL_get_servername_type, for a server, returns |TLSEXT_NAMETYPE_host_name| +// if the client sent a hostname and -1 otherwise. +OPENSSL_EXPORT int SSL_get_servername_type(const SSL *ssl); + +// SSL_CTX_set_tlsext_servername_callback configures |callback| to be called on +// the server after ClientHello extensions have been parsed and returns one. +// The callback may use |SSL_get_servername| to examine the server_name +// extension and returns a |SSL_TLSEXT_ERR_*| value. The value of |arg| may be +// set by calling |SSL_CTX_set_tlsext_servername_arg|. +// +// If the callback returns |SSL_TLSEXT_ERR_NOACK|, the server_name extension is +// not acknowledged in the ServerHello. If the return value is +// |SSL_TLSEXT_ERR_ALERT_FATAL|, then |*out_alert| is the alert to send, +// defaulting to |SSL_AD_UNRECOGNIZED_NAME|. |SSL_TLSEXT_ERR_ALERT_WARNING| is +// ignored and treated as |SSL_TLSEXT_ERR_OK|. +OPENSSL_EXPORT int SSL_CTX_set_tlsext_servername_callback( + SSL_CTX *ctx, int (*callback)(SSL *ssl, int *out_alert, void *arg)); + +// SSL_CTX_set_tlsext_servername_arg sets the argument to the servername +// callback and returns one. See |SSL_CTX_set_tlsext_servername_callback|. +OPENSSL_EXPORT int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg); + +// SSL_TLSEXT_ERR_* are values returned by some extension-related callbacks. +#define SSL_TLSEXT_ERR_OK 0 +#define SSL_TLSEXT_ERR_ALERT_WARNING 1 +#define SSL_TLSEXT_ERR_ALERT_FATAL 2 +#define SSL_TLSEXT_ERR_NOACK 3 + +// SSL_set_SSL_CTX changes |ssl|'s |SSL_CTX|. |ssl| will use the +// certificate-related settings from |ctx|, and |SSL_get_SSL_CTX| will report +// |ctx|. This function may be used during the callbacks registered by +// |SSL_CTX_set_select_certificate_cb|, +// |SSL_CTX_set_tlsext_servername_callback|, and |SSL_CTX_set_cert_cb| or when +// the handshake is paused from them. It is typically used to switch +// certificates based on SNI. +// +// Note the session cache and related settings will continue to use the initial +// |SSL_CTX|. Callers should use |SSL_CTX_set_session_id_context| to partition +// the session cache between different domains. +// +// TODO(davidben): Should other settings change after this call? +OPENSSL_EXPORT SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx); + + +// Application-layer protocol negotiation. +// +// The ALPN extension (RFC 7301) allows negotiating different application-layer +// protocols over a single port. This is used, for example, to negotiate +// HTTP/2. + +// SSL_CTX_set_alpn_protos sets the client ALPN protocol list on |ctx| to +// |protos|. |protos| must be in wire-format (i.e. a series of non-empty, 8-bit +// length-prefixed strings), or the empty string to disable ALPN. It returns +// zero on success and one on failure. Configuring a non-empty string enables +// ALPN on a client. +// +// WARNING: this function is dangerous because it breaks the usual return value +// convention. +OPENSSL_EXPORT int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, + size_t protos_len); + +// SSL_set_alpn_protos sets the client ALPN protocol list on |ssl| to |protos|. +// |protos| must be in wire-format (i.e. a series of non-empty, 8-bit +// length-prefixed strings), or the empty string to disable ALPN. It returns +// zero on success and one on failure. Configuring a non-empty string enables +// ALPN on a client. +// +// WARNING: this function is dangerous because it breaks the usual return value +// convention. +OPENSSL_EXPORT int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, + size_t protos_len); + +// SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is called +// during ClientHello processing in order to select an ALPN protocol from the +// client's list of offered protocols. +// +// The callback is passed a wire-format (i.e. a series of non-empty, 8-bit +// length-prefixed strings) ALPN protocol list in |in|. To select a protocol, +// the callback should set |*out| and |*out_len| to the selected protocol and +// return |SSL_TLSEXT_ERR_OK| on success. It does not pass ownership of the +// buffer, so |*out| should point to a static string, a buffer that outlives the +// callback call, or the corresponding entry in |in|. +// +// If the server supports ALPN, but there are no protocols in common, the +// callback should return |SSL_TLSEXT_ERR_ALERT_FATAL| to abort the connection +// with a no_application_protocol alert. +// +// If the server does not support ALPN, it can return |SSL_TLSEXT_ERR_NOACK| to +// continue the handshake without negotiating a protocol. This may be useful if +// multiple server configurations share an |SSL_CTX|, only some of which have +// ALPN protocols configured. +// +// |SSL_TLSEXT_ERR_ALERT_WARNING| is ignored and will be treated as +// |SSL_TLSEXT_ERR_NOACK|. +// +// The callback will only be called if the client supports ALPN. Callers that +// wish to require ALPN for all clients must check |SSL_get0_alpn_selected| +// after the handshake. In QUIC connections, this is done automatically. +// +// The cipher suite is selected before negotiating ALPN. The callback may use +// |SSL_get_pending_cipher| to query the cipher suite. This may be used to +// implement HTTP/2's cipher suite constraints. +OPENSSL_EXPORT void SSL_CTX_set_alpn_select_cb( + SSL_CTX *ctx, int (*cb)(SSL *ssl, const uint8_t **out, uint8_t *out_len, + const uint8_t *in, unsigned in_len, void *arg), + void *arg); + +// SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|. +// On return it sets |*out_data| to point to |*out_len| bytes of protocol name +// (not including the leading length-prefix byte). If the server didn't respond +// with a negotiated protocol then |*out_len| will be zero. +OPENSSL_EXPORT void SSL_get0_alpn_selected(const SSL *ssl, + const uint8_t **out_data, + unsigned *out_len); + +// SSL_CTX_set_allow_unknown_alpn_protos configures client connections on |ctx| +// to allow unknown ALPN protocols from the server. Otherwise, by default, the +// client will require that the protocol be advertised in +// |SSL_CTX_set_alpn_protos|. +OPENSSL_EXPORT void SSL_CTX_set_allow_unknown_alpn_protos(SSL_CTX *ctx, + int enabled); + + +// Application-layer protocol settings +// +// The ALPS extension (draft-vvv-tls-alps) allows exchanging application-layer +// settings in the TLS handshake for applications negotiated with ALPN. Note +// that, when ALPS is negotiated, the client and server each advertise their own +// settings, so there are functions to both configure setting to send and query +// received settings. + +// SSL_add_application_settings configures |ssl| to enable ALPS with ALPN +// protocol |proto|, sending an ALPS value of |settings|. It returns one on +// success and zero on error. If |proto| is negotiated via ALPN and the peer +// supports ALPS, |settings| will be sent to the peer. The peer's ALPS value can +// be retrieved with |SSL_get0_peer_application_settings|. +// +// On the client, this function should be called before the handshake, once for +// each supported ALPN protocol which uses ALPS. |proto| must be included in the +// client's ALPN configuration (see |SSL_CTX_set_alpn_protos| and +// |SSL_set_alpn_protos|). On the server, ALPS can be preconfigured for each +// protocol as in the client, or configuration can be deferred to the ALPN +// callback (see |SSL_CTX_set_alpn_select_cb|), in which case only the selected +// protocol needs to be configured. +// +// ALPS can be independently configured from 0-RTT, however changes in protocol +// settings will fallback to 1-RTT to negotiate the new value, so it is +// recommended for |settings| to be relatively stable. +OPENSSL_EXPORT int SSL_add_application_settings(SSL *ssl, const uint8_t *proto, + size_t proto_len, + const uint8_t *settings, + size_t settings_len); + +// SSL_get0_peer_application_settings sets |*out_data| and |*out_len| to a +// buffer containing the peer's ALPS value, or the empty string if ALPS was not +// negotiated. Note an empty string could also indicate the peer sent an empty +// settings value. Use |SSL_has_application_settings| to check if ALPS was +// negotiated. The output buffer is owned by |ssl| and is valid until the next +// time |ssl| is modified. +OPENSSL_EXPORT void SSL_get0_peer_application_settings(const SSL *ssl, + const uint8_t **out_data, + size_t *out_len); + +// SSL_has_application_settings returns one if ALPS was negotiated on this +// connection and zero otherwise. +OPENSSL_EXPORT int SSL_has_application_settings(const SSL *ssl); + + +// Certificate compression. +// +// Certificates in TLS 1.3 can be compressed (RFC 8879). BoringSSL supports this +// as both a client and a server, but does not link against any specific +// compression libraries in order to keep dependencies to a minimum. Instead, +// hooks for compression and decompression can be installed in an |SSL_CTX| to +// enable support. + +// ssl_cert_compression_func_t is a pointer to a function that performs +// compression. It must write the compressed representation of |in| to |out|, +// returning one on success and zero on error. The results of compressing +// certificates are not cached internally. Implementations may wish to implement +// their own cache if they expect it to be useful given the certificates that +// they serve. +typedef int (*ssl_cert_compression_func_t)(SSL *ssl, CBB *out, + const uint8_t *in, size_t in_len); + +// ssl_cert_decompression_func_t is a pointer to a function that performs +// decompression. The compressed data from the peer is passed as |in| and the +// decompressed result must be exactly |uncompressed_len| bytes long. It returns +// one on success, in which case |*out| must be set to the result of +// decompressing |in|, or zero on error. Setting |*out| transfers ownership, +// i.e. |CRYPTO_BUFFER_free| will be called on |*out| at some point in the +// future. The results of decompressions are not cached internally. +// Implementations may wish to implement their own cache if they expect it to be +// useful. +typedef int (*ssl_cert_decompression_func_t)(SSL *ssl, CRYPTO_BUFFER **out, + size_t uncompressed_len, + const uint8_t *in, size_t in_len); + +// SSL_CTX_add_cert_compression_alg registers a certificate compression +// algorithm on |ctx| with ID |alg_id|. (The value of |alg_id| should be an IANA +// assigned value and each can only be registered once.) +// +// One of the function pointers may be NULL to avoid having to implement both +// sides of a compression algorithm if you're only going to use it in one +// direction. In this case, the unimplemented direction acts like it was never +// configured. +// +// For a server, algorithms are registered in preference order with the most +// preferable first. It returns one on success or zero on error. +OPENSSL_EXPORT int SSL_CTX_add_cert_compression_alg( + SSL_CTX *ctx, uint16_t alg_id, ssl_cert_compression_func_t compress, + ssl_cert_decompression_func_t decompress); + + +// Next protocol negotiation. +// +// The NPN extension (draft-agl-tls-nextprotoneg-03) is the predecessor to ALPN +// and deprecated in favor of it. + +// SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when a +// TLS server needs a list of supported protocols for Next Protocol +// Negotiation. The returned list must be in wire format. The list is returned +// by setting |*out| to point to it and |*out_len| to its length. This memory +// will not be modified, but one should assume that |ssl| keeps a reference to +// it. +// +// The callback should return |SSL_TLSEXT_ERR_OK| if it wishes to advertise. +// Otherwise, no such extension will be included in the ServerHello. +OPENSSL_EXPORT void SSL_CTX_set_next_protos_advertised_cb( + SSL_CTX *ctx, + int (*cb)(SSL *ssl, const uint8_t **out, unsigned *out_len, void *arg), + void *arg); + +// SSL_CTX_set_next_proto_select_cb sets a callback that is called when a client +// needs to select a protocol from the server's provided list. |*out| must be +// set to point to the selected protocol (which may be within |in|). The length +// of the protocol name must be written into |*out_len|. The server's advertised +// protocols are provided in |in| and |in_len|. The callback can assume that +// |in| is syntactically valid. +// +// The client must select a protocol. It is fatal to the connection if this +// callback returns a value other than |SSL_TLSEXT_ERR_OK|. +// +// Configuring this callback enables NPN on a client. +OPENSSL_EXPORT void SSL_CTX_set_next_proto_select_cb( + SSL_CTX *ctx, int (*cb)(SSL *ssl, uint8_t **out, uint8_t *out_len, + const uint8_t *in, unsigned in_len, void *arg), + void *arg); + +// SSL_get0_next_proto_negotiated sets |*out_data| and |*out_len| to point to +// the client's requested protocol for this connection. If the client didn't +// request any protocol, then |*out_data| is set to NULL. +// +// Note that the client can request any protocol it chooses. The value returned +// from this function need not be a member of the list of supported protocols +// provided by the server. +OPENSSL_EXPORT void SSL_get0_next_proto_negotiated(const SSL *ssl, + const uint8_t **out_data, + unsigned *out_len); + +// SSL_select_next_proto implements the standard protocol selection. It is +// expected that this function is called from the callback set by +// |SSL_CTX_set_next_proto_select_cb|. +// +// |peer| and |supported| must be vectors of 8-bit, length-prefixed byte strings +// containing the peer and locally-configured protocols, respectively. The +// length byte itself is not included in the length. A byte string of length 0 +// is invalid. No byte string may be truncated. |supported| is assumed to be +// non-empty. +// +// This function finds the first protocol in |peer| which is also in +// |supported|. If one was found, it sets |*out| and |*out_len| to point to it +// and returns |OPENSSL_NPN_NEGOTIATED|. Otherwise, it returns +// |OPENSSL_NPN_NO_OVERLAP| and sets |*out| and |*out_len| to the first +// supported protocol. +OPENSSL_EXPORT int SSL_select_next_proto(uint8_t **out, uint8_t *out_len, + const uint8_t *peer, unsigned peer_len, + const uint8_t *supported, + unsigned supported_len); + +#define OPENSSL_NPN_UNSUPPORTED 0 +#define OPENSSL_NPN_NEGOTIATED 1 +#define OPENSSL_NPN_NO_OVERLAP 2 + + +// Channel ID. +// +// See draft-balfanz-tls-channelid-01. This is an old, experimental mechanism +// and should not be used in new code. + +// SSL_CTX_set_tls_channel_id_enabled configures whether connections associated +// with |ctx| should enable Channel ID as a server. +OPENSSL_EXPORT void SSL_CTX_set_tls_channel_id_enabled(SSL_CTX *ctx, + int enabled); + +// SSL_set_tls_channel_id_enabled configures whether |ssl| should enable Channel +// ID as a server. +OPENSSL_EXPORT void SSL_set_tls_channel_id_enabled(SSL *ssl, int enabled); + +// SSL_CTX_set1_tls_channel_id configures a TLS client to send a TLS Channel ID +// to compatible servers. |private_key| must be a P-256 EC key. It returns one +// on success and zero on error. +OPENSSL_EXPORT int SSL_CTX_set1_tls_channel_id(SSL_CTX *ctx, + EVP_PKEY *private_key); + +// SSL_set1_tls_channel_id configures a TLS client to send a TLS Channel ID to +// compatible servers. |private_key| must be a P-256 EC key. It returns one on +// success and zero on error. +OPENSSL_EXPORT int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key); + +// SSL_get_tls_channel_id gets the client's TLS Channel ID from a server |SSL| +// and copies up to the first |max_out| bytes into |out|. The Channel ID +// consists of the client's P-256 public key as an (x,y) pair where each is a +// 32-byte, big-endian field element. It returns 0 if the client didn't offer a +// Channel ID and the length of the complete Channel ID otherwise. This function +// always returns zero if |ssl| is a client. +OPENSSL_EXPORT size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, + size_t max_out); + + +// DTLS-SRTP. +// +// See RFC 5764. + +// srtp_protection_profile_st (aka |SRTP_PROTECTION_PROFILE|) is an SRTP +// profile for use with the use_srtp extension. +struct srtp_protection_profile_st { + const char *name; + unsigned long id; +} /* SRTP_PROTECTION_PROFILE */; + +DEFINE_CONST_STACK_OF(SRTP_PROTECTION_PROFILE) + +// SRTP_* define constants for SRTP profiles. +#define SRTP_AES128_CM_SHA1_80 0x0001 +#define SRTP_AES128_CM_SHA1_32 0x0002 +#define SRTP_AES128_F8_SHA1_80 0x0003 +#define SRTP_AES128_F8_SHA1_32 0x0004 +#define SRTP_NULL_SHA1_80 0x0005 +#define SRTP_NULL_SHA1_32 0x0006 +#define SRTP_AEAD_AES_128_GCM 0x0007 +#define SRTP_AEAD_AES_256_GCM 0x0008 + +// SSL_CTX_set_srtp_profiles enables SRTP for all SSL objects created from +// |ctx|. |profile| contains a colon-separated list of profile names. It returns +// one on success and zero on failure. +OPENSSL_EXPORT int SSL_CTX_set_srtp_profiles(SSL_CTX *ctx, + const char *profiles); + +// SSL_set_srtp_profiles enables SRTP for |ssl|. |profile| contains a +// colon-separated list of profile names. It returns one on success and zero on +// failure. +OPENSSL_EXPORT int SSL_set_srtp_profiles(SSL *ssl, const char *profiles); + +// SSL_get_srtp_profiles returns the SRTP profiles supported by |ssl|. +OPENSSL_EXPORT const STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles( + const SSL *ssl); + +// SSL_get_selected_srtp_profile returns the selected SRTP profile, or NULL if +// SRTP was not negotiated. +OPENSSL_EXPORT const SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile( + SSL *ssl); + + +// Pre-shared keys. +// +// Connections may be configured with PSK (Pre-Shared Key) cipher suites. These +// authenticate using out-of-band pre-shared keys rather than certificates. See +// RFC 4279. +// +// This implementation uses NUL-terminated C strings for identities and identity +// hints, so values with a NUL character are not supported. (RFC 4279 does not +// specify the format of an identity.) + +// PSK_MAX_IDENTITY_LEN is the maximum supported length of a PSK identity, +// excluding the NUL terminator. +#define PSK_MAX_IDENTITY_LEN 128 + +// PSK_MAX_PSK_LEN is the maximum supported length of a pre-shared key. +#define PSK_MAX_PSK_LEN 256 + +// SSL_CTX_set_psk_client_callback sets the callback to be called when PSK is +// negotiated on the client. This callback must be set to enable PSK cipher +// suites on the client. +// +// The callback is passed the identity hint in |hint| or NULL if none was +// provided. It should select a PSK identity and write the identity and the +// corresponding PSK to |identity| and |psk|, respectively. The identity is +// written as a NUL-terminated C string of length (excluding the NUL terminator) +// at most |max_identity_len|. The PSK's length must be at most |max_psk_len|. +// The callback returns the length of the PSK or 0 if no suitable identity was +// found. +OPENSSL_EXPORT void SSL_CTX_set_psk_client_callback( + SSL_CTX *ctx, unsigned (*cb)(SSL *ssl, const char *hint, char *identity, + unsigned max_identity_len, uint8_t *psk, + unsigned max_psk_len)); + +// SSL_set_psk_client_callback sets the callback to be called when PSK is +// negotiated on the client. This callback must be set to enable PSK cipher +// suites on the client. See also |SSL_CTX_set_psk_client_callback|. +OPENSSL_EXPORT void SSL_set_psk_client_callback( + SSL *ssl, unsigned (*cb)(SSL *ssl, const char *hint, char *identity, + unsigned max_identity_len, uint8_t *psk, + unsigned max_psk_len)); + +// SSL_CTX_set_psk_server_callback sets the callback to be called when PSK is +// negotiated on the server. This callback must be set to enable PSK cipher +// suites on the server. +// +// The callback is passed the identity in |identity|. It should write a PSK of +// length at most |max_psk_len| to |psk| and return the number of bytes written +// or zero if the PSK identity is unknown. +OPENSSL_EXPORT void SSL_CTX_set_psk_server_callback( + SSL_CTX *ctx, unsigned (*cb)(SSL *ssl, const char *identity, uint8_t *psk, + unsigned max_psk_len)); + +// SSL_set_psk_server_callback sets the callback to be called when PSK is +// negotiated on the server. This callback must be set to enable PSK cipher +// suites on the server. See also |SSL_CTX_set_psk_server_callback|. +OPENSSL_EXPORT void SSL_set_psk_server_callback( + SSL *ssl, unsigned (*cb)(SSL *ssl, const char *identity, uint8_t *psk, + unsigned max_psk_len)); + +// SSL_CTX_use_psk_identity_hint configures server connections to advertise an +// identity hint of |identity_hint|. It returns one on success and zero on +// error. +OPENSSL_EXPORT int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, + const char *identity_hint); + +// SSL_use_psk_identity_hint configures server connections to advertise an +// identity hint of |identity_hint|. It returns one on success and zero on +// error. +OPENSSL_EXPORT int SSL_use_psk_identity_hint(SSL *ssl, + const char *identity_hint); + +// SSL_get_psk_identity_hint returns the PSK identity hint advertised for |ssl| +// or NULL if there is none. +OPENSSL_EXPORT const char *SSL_get_psk_identity_hint(const SSL *ssl); + +// SSL_get_psk_identity, after the handshake completes, returns the PSK identity +// that was negotiated by |ssl| or NULL if PSK was not used. +OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *ssl); + + +// Delegated credentials. +// +// *** EXPERIMENTAL — PRONE TO CHANGE *** +// +// draft-ietf-tls-subcerts is a proposed extension for TLS 1.3 and above that +// allows an end point to use its certificate to delegate credentials for +// authentication. If the peer indicates support for this extension, then this +// host may use a delegated credential to sign the handshake. Once issued, +// credentials can't be revoked. In order to mitigate the damage in case the +// credential secret key is compromised, the credential is only valid for a +// short time (days, hours, or even minutes). This library implements draft-03 +// of the protocol spec. +// +// The extension ID has not been assigned; we're using 0xff02 for the time +// being. Currently only the server side is implemented. +// +// Servers configure a DC for use in the handshake via +// |SSL_set1_delegated_credential|. It must be signed by the host's end-entity +// certificate as defined in draft-ietf-tls-subcerts-03. + +// SSL_set1_delegated_credential configures the delegated credential (DC) that +// will be sent to the peer for the current connection. |dc| is the DC in wire +// format, and |pkey| or |key_method| is the corresponding private key. +// Currently (as of draft-03), only servers may configure a DC to use in the +// handshake. +// +// The DC will only be used if the protocol version is correct and the signature +// scheme is supported by the peer. If not, the DC will not be negotiated and +// the handshake will use the private key (or private key method) associated +// with the certificate. +OPENSSL_EXPORT int SSL_set1_delegated_credential( + SSL *ssl, CRYPTO_BUFFER *dc, EVP_PKEY *pkey, + const SSL_PRIVATE_KEY_METHOD *key_method); + +// SSL_delegated_credential_used returns one if a delegated credential was used +// and zero otherwise. +OPENSSL_EXPORT int SSL_delegated_credential_used(const SSL *ssl); + + +// QUIC integration. +// +// QUIC acts as an underlying transport for the TLS 1.3 handshake. The following +// functions allow a QUIC implementation to serve as the underlying transport as +// described in RFC 9001. +// +// When configured for QUIC, |SSL_do_handshake| will drive the handshake as +// before, but it will not use the configured |BIO|. It will call functions on +// |SSL_QUIC_METHOD| to configure secrets and send data. If data is needed from +// the peer, it will return |SSL_ERROR_WANT_READ|. As the caller receives data +// it can decrypt, it calls |SSL_provide_quic_data|. Subsequent +// |SSL_do_handshake| calls will then consume that data and progress the +// handshake. After the handshake is complete, the caller should continue to +// call |SSL_provide_quic_data| for any post-handshake data, followed by +// |SSL_process_quic_post_handshake| to process it. It is an error to call +// |SSL_read| and |SSL_write| in QUIC. +// +// 0-RTT behaves similarly to |TLS_method|'s usual behavior. |SSL_do_handshake| +// returns early as soon as the client (respectively, server) is allowed to send +// 0-RTT (respectively, half-RTT) data. The caller should then call +// |SSL_do_handshake| again to consume the remaining handshake messages and +// confirm the handshake. As a client, |SSL_ERROR_EARLY_DATA_REJECTED| and +// |SSL_reset_early_data_reject| behave as usual. +// +// See https://www.rfc-editor.org/rfc/rfc9001.html#section-4.1 for more details. +// +// To avoid DoS attacks, the QUIC implementation must limit the amount of data +// being queued up. The implementation can call +// |SSL_quic_max_handshake_flight_len| to get the maximum buffer length at each +// encryption level. +// +// QUIC implementations must additionally configure transport parameters with +// |SSL_set_quic_transport_params|. |SSL_get_peer_quic_transport_params| may be +// used to query the value received from the peer. BoringSSL handles this +// extension as an opaque byte string. The caller is responsible for serializing +// and parsing them. See https://www.rfc-editor.org/rfc/rfc9000#section-7.4 for +// details. +// +// QUIC additionally imposes restrictions on 0-RTT. In particular, the QUIC +// transport layer requires that if a server accepts 0-RTT data, then the +// transport parameters sent on the resumed connection must not lower any limits +// compared to the transport parameters that the server sent on the connection +// where the ticket for 0-RTT was issued. In effect, the server must remember +// the transport parameters with the ticket. Application protocols running on +// QUIC may impose similar restrictions, for example HTTP/3's restrictions on +// SETTINGS frames. +// +// BoringSSL implements this check by doing a byte-for-byte comparison of an +// opaque context passed in by the server. This context must be the same on the +// connection where the ticket was issued and the connection where that ticket +// is used for 0-RTT. If there is a mismatch, or the context was not set, +// BoringSSL will reject early data (but not reject the resumption attempt). +// This context is set via |SSL_set_quic_early_data_context| and should cover +// both transport parameters and any application state. +// |SSL_set_quic_early_data_context| must be called on the server with a +// non-empty context if the server is to support 0-RTT in QUIC. +// +// BoringSSL does not perform any client-side checks on the transport +// parameters received from a server that also accepted early data. It is up to +// the caller to verify that the received transport parameters do not lower any +// limits, and to close the QUIC connection if that is not the case. The same +// holds for any application protocol state remembered for 0-RTT, e.g. HTTP/3 +// SETTINGS. + +// ssl_encryption_level_t represents a specific QUIC encryption level used to +// transmit handshake messages. +enum ssl_encryption_level_t BORINGSSL_ENUM_INT { + ssl_encryption_initial = 0, + ssl_encryption_early_data, + ssl_encryption_handshake, + ssl_encryption_application, +}; + +// ssl_quic_method_st (aka |SSL_QUIC_METHOD|) describes custom QUIC hooks. +struct ssl_quic_method_st { + // set_read_secret configures the read secret and cipher suite for the given + // encryption level. It returns one on success and zero to terminate the + // handshake with an error. It will be called at most once per encryption + // level. + // + // BoringSSL will not release read keys before QUIC may use them. Once a level + // has been initialized, QUIC may begin processing data from it. Handshake + // data should be passed to |SSL_provide_quic_data| and application data (if + // |level| is |ssl_encryption_early_data| or |ssl_encryption_application|) may + // be processed according to the rules of the QUIC protocol. + // + // QUIC ACKs packets at the same encryption level they were received at, + // except that client |ssl_encryption_early_data| (0-RTT) packets trigger + // server |ssl_encryption_application| (1-RTT) ACKs. BoringSSL will always + // install ACK-writing keys with |set_write_secret| before the packet-reading + // keys with |set_read_secret|. This ensures the caller can always ACK any + // packet it decrypts. Note this means the server installs 1-RTT write keys + // before 0-RTT read keys. + // + // The converse is not true. An encryption level may be configured with write + // secrets a roundtrip before the corresponding secrets for reading ACKs is + // available. + int (*set_read_secret)(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, + size_t secret_len); + // set_write_secret behaves like |set_read_secret| but configures the write + // secret and cipher suite for the given encryption level. It will be called + // at most once per encryption level. + // + // BoringSSL will not release write keys before QUIC may use them. If |level| + // is |ssl_encryption_early_data| or |ssl_encryption_application|, QUIC may + // begin sending application data at |level|. However, note that BoringSSL + // configures server |ssl_encryption_application| write keys before the client + // Finished. This allows QUIC to send half-RTT data, but the handshake is not + // confirmed at this point and, if requesting client certificates, the client + // is not yet authenticated. + // + // See |set_read_secret| for additional invariants between packets and their + // ACKs. + // + // Note that, on 0-RTT reject, the |ssl_encryption_early_data| write secret + // may use a different cipher suite from the other keys. + int (*set_write_secret)(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, + size_t secret_len); + // add_handshake_data adds handshake data to the current flight at the given + // encryption level. It returns one on success and zero on error. + // + // BoringSSL will pack data from a single encryption level together, but a + // single handshake flight may include multiple encryption levels. Callers + // should defer writing data to the network until |flush_flight| to better + // pack QUIC packets into transport datagrams. + // + // If |level| is not |ssl_encryption_initial|, this function will not be + // called before |level| is initialized with |set_write_secret|. + int (*add_handshake_data)(SSL *ssl, enum ssl_encryption_level_t level, + const uint8_t *data, size_t len); + // flush_flight is called when the current flight is complete and should be + // written to the transport. Note a flight may contain data at several + // encryption levels. It returns one on success and zero on error. + int (*flush_flight)(SSL *ssl); + // send_alert sends a fatal alert at the specified encryption level. It + // returns one on success and zero on error. + // + // If |level| is not |ssl_encryption_initial|, this function will not be + // called before |level| is initialized with |set_write_secret|. + int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert); +}; + +// SSL_quic_max_handshake_flight_len returns returns the maximum number of bytes +// that may be received at the given encryption level. This function should be +// used to limit buffering in the QUIC implementation. +// +// See https://www.rfc-editor.org/rfc/rfc9000#section-7.5 +OPENSSL_EXPORT size_t SSL_quic_max_handshake_flight_len( + const SSL *ssl, enum ssl_encryption_level_t level); + +// SSL_quic_read_level returns the current read encryption level. +// +// TODO(davidben): Is it still necessary to expose this function to callers? +// QUICHE does not use it. +OPENSSL_EXPORT enum ssl_encryption_level_t SSL_quic_read_level(const SSL *ssl); + +// SSL_quic_write_level returns the current write encryption level. +// +// TODO(davidben): Is it still necessary to expose this function to callers? +// QUICHE does not use it. +OPENSSL_EXPORT enum ssl_encryption_level_t SSL_quic_write_level(const SSL *ssl); + +// SSL_provide_quic_data provides data from QUIC at a particular encryption +// level |level|. It returns one on success and zero on error. Note this +// function will return zero if the handshake is not expecting data from |level| +// at this time. The QUIC implementation should then close the connection with +// an error. +OPENSSL_EXPORT int SSL_provide_quic_data(SSL *ssl, + enum ssl_encryption_level_t level, + const uint8_t *data, size_t len); + + +// SSL_process_quic_post_handshake processes any data that QUIC has provided +// after the handshake has completed. This includes NewSessionTicket messages +// sent by the server. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_process_quic_post_handshake(SSL *ssl); + +// SSL_CTX_set_quic_method configures the QUIC hooks. This should only be +// configured with a minimum version of TLS 1.3. |quic_method| must remain valid +// for the lifetime of |ctx|. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_CTX_set_quic_method(SSL_CTX *ctx, + const SSL_QUIC_METHOD *quic_method); + +// SSL_set_quic_method configures the QUIC hooks. This should only be +// configured with a minimum version of TLS 1.3. |quic_method| must remain valid +// for the lifetime of |ssl|. It returns one on success and zero on error. +OPENSSL_EXPORT int SSL_set_quic_method(SSL *ssl, + const SSL_QUIC_METHOD *quic_method); + +// SSL_set_quic_transport_params configures |ssl| to send |params| (of length +// |params_len|) in the quic_transport_parameters extension in either the +// ClientHello or EncryptedExtensions handshake message. It is an error to set +// transport parameters if |ssl| is not configured for QUIC. The buffer pointed +// to by |params| only need be valid for the duration of the call to this +// function. This function returns 1 on success and 0 on failure. +OPENSSL_EXPORT int SSL_set_quic_transport_params(SSL *ssl, + const uint8_t *params, + size_t params_len); + +// SSL_get_peer_quic_transport_params provides the caller with the value of the +// quic_transport_parameters extension sent by the peer. A pointer to the buffer +// containing the TransportParameters will be put in |*out_params|, and its +// length in |*params_len|. This buffer will be valid for the lifetime of the +// |SSL|. If no params were received from the peer, |*out_params_len| will be 0. +OPENSSL_EXPORT void SSL_get_peer_quic_transport_params( + const SSL *ssl, const uint8_t **out_params, size_t *out_params_len); + +// SSL_set_quic_use_legacy_codepoint configures whether to use the legacy QUIC +// extension codepoint 0xffa5 as opposed to the official value 57. Call with +// |use_legacy| set to 1 to use 0xffa5 and call with 0 to use 57. By default, +// the standard code point is used. +OPENSSL_EXPORT void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy); + +// SSL_set_quic_early_data_context configures a context string in QUIC servers +// for accepting early data. If a resumption connection offers early data, the +// server will check if the value matches that of the connection which minted +// the ticket. If not, resumption still succeeds but early data is rejected. +// This should include all QUIC Transport Parameters except ones specified that +// the client MUST NOT remember. This should also include any application +// protocol-specific state. For HTTP/3, this should be the serialized server +// SETTINGS frame and the QUIC Transport Parameters (except the stateless reset +// token). +// +// This function may be called before |SSL_do_handshake| or during server +// certificate selection. It returns 1 on success and 0 on failure. +OPENSSL_EXPORT int SSL_set_quic_early_data_context(SSL *ssl, + const uint8_t *context, + size_t context_len); + + +// Early data. +// +// WARNING: 0-RTT support in BoringSSL is currently experimental and not fully +// implemented. It may cause interoperability or security failures when used. +// +// Early data, or 0-RTT, is a feature in TLS 1.3 which allows clients to send +// data on the first flight during a resumption handshake. This can save a +// round-trip in some application protocols. +// +// WARNING: A 0-RTT handshake has different security properties from normal +// handshake, so it is off by default unless opted in. In particular, early data +// is replayable by a network attacker. Callers must account for this when +// sending or processing data before the handshake is confirmed. See RFC 8446 +// for more information. +// +// As a server, if early data is accepted, |SSL_do_handshake| will complete as +// soon as the ClientHello is processed and server flight sent. |SSL_write| may +// be used to send half-RTT data. |SSL_read| will consume early data and +// transition to 1-RTT data as appropriate. Prior to the transition, +// |SSL_in_init| will report the handshake is still in progress. Callers may use +// it or |SSL_in_early_data| to defer or reject requests as needed. +// +// Early data as a client is more complex. If the offered session (see +// |SSL_set_session|) is 0-RTT-capable, the handshake will return after sending +// the ClientHello. The predicted peer certificates and ALPN protocol will be +// available via the usual APIs. |SSL_write| will write early data, up to the +// session's limit. Writes past this limit and |SSL_read| will complete the +// handshake before continuing. Callers may also call |SSL_do_handshake| again +// to complete the handshake sooner. +// +// If the server accepts early data, the handshake will succeed. |SSL_read| and +// |SSL_write| will then act as in a 1-RTT handshake. The peer certificates and +// ALPN protocol will be as predicted and need not be re-queried. +// +// If the server rejects early data, |SSL_do_handshake| (and thus |SSL_read| and +// |SSL_write|) will then fail with |SSL_get_error| returning +// |SSL_ERROR_EARLY_DATA_REJECTED|. The caller should treat this as a connection +// error and most likely perform a high-level retry. Note the server may still +// have processed the early data due to attacker replays. +// +// To then continue the handshake on the original connection, use +// |SSL_reset_early_data_reject|. The connection will then behave as one which +// had not yet completed the handshake. This allows a faster retry than making a +// fresh connection. |SSL_do_handshake| will complete the full handshake, +// possibly resulting in different peer certificates, ALPN protocol, and other +// properties. The caller must disregard any values from before the reset and +// query again. +// +// Finally, to implement the fallback described in RFC 8446 appendix D.3, retry +// on a fresh connection without 0-RTT if the handshake fails with +// |SSL_R_WRONG_VERSION_ON_EARLY_DATA|. + +// SSL_CTX_set_early_data_enabled sets whether early data is allowed to be used +// with resumptions using |ctx|. +OPENSSL_EXPORT void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled); + +// SSL_set_early_data_enabled sets whether early data is allowed to be used +// with resumptions using |ssl|. See |SSL_CTX_set_early_data_enabled| for more +// information. +OPENSSL_EXPORT void SSL_set_early_data_enabled(SSL *ssl, int enabled); + +// SSL_in_early_data returns one if |ssl| has a pending handshake that has +// progressed enough to send or receive early data. Clients may call |SSL_write| +// to send early data, but |SSL_read| will complete the handshake before +// accepting application data. Servers may call |SSL_read| to read early data +// and |SSL_write| to send half-RTT data. +OPENSSL_EXPORT int SSL_in_early_data(const SSL *ssl); + +// SSL_SESSION_early_data_capable returns whether early data would have been +// attempted with |session| if enabled. +OPENSSL_EXPORT int SSL_SESSION_early_data_capable(const SSL_SESSION *session); + +// SSL_SESSION_copy_without_early_data returns a copy of |session| with early +// data disabled. If |session| already does not support early data, it returns +// |session| with the reference count increased. The caller takes ownership of +// the result and must release it with |SSL_SESSION_free|. +// +// This function may be used on the client to clear early data support from +// existing sessions when the server rejects early data. In particular, +// |SSL_R_WRONG_VERSION_ON_EARLY_DATA| requires a fresh connection to retry, and +// the client would not want 0-RTT enabled for the next connection attempt. +OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_copy_without_early_data( + SSL_SESSION *session); + +// SSL_early_data_accepted returns whether early data was accepted on the +// handshake performed by |ssl|. +OPENSSL_EXPORT int SSL_early_data_accepted(const SSL *ssl); + +// SSL_reset_early_data_reject resets |ssl| after an early data reject. All +// 0-RTT state is discarded, including any pending |SSL_write| calls. The caller +// should treat |ssl| as a logically fresh connection, usually by driving the +// handshake to completion using |SSL_do_handshake|. +// +// It is an error to call this function on an |SSL| object that is not signaling +// |SSL_ERROR_EARLY_DATA_REJECTED|. +OPENSSL_EXPORT void SSL_reset_early_data_reject(SSL *ssl); + +// SSL_get_ticket_age_skew returns the difference, in seconds, between the +// client-sent ticket age and the server-computed value in TLS 1.3 server +// connections which resumed a session. +OPENSSL_EXPORT int32_t SSL_get_ticket_age_skew(const SSL *ssl); + +// An ssl_early_data_reason_t describes why 0-RTT was accepted or rejected. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum ssl_early_data_reason_t BORINGSSL_ENUM_INT { + // The handshake has not progressed far enough for the 0-RTT status to be + // known. + ssl_early_data_unknown = 0, + // 0-RTT is disabled for this connection. + ssl_early_data_disabled = 1, + // 0-RTT was accepted. + ssl_early_data_accepted = 2, + // The negotiated protocol version does not support 0-RTT. + ssl_early_data_protocol_version = 3, + // The peer declined to offer or accept 0-RTT for an unknown reason. + ssl_early_data_peer_declined = 4, + // The client did not offer a session. + ssl_early_data_no_session_offered = 5, + // The server declined to resume the session. + ssl_early_data_session_not_resumed = 6, + // The session does not support 0-RTT. + ssl_early_data_unsupported_for_session = 7, + // The server sent a HelloRetryRequest. + ssl_early_data_hello_retry_request = 8, + // The negotiated ALPN protocol did not match the session. + ssl_early_data_alpn_mismatch = 9, + // The connection negotiated Channel ID, which is incompatible with 0-RTT. + ssl_early_data_channel_id = 10, + // Value 11 is reserved. (It has historically |ssl_early_data_token_binding|.) + // The client and server ticket age were too far apart. + ssl_early_data_ticket_age_skew = 12, + // QUIC parameters differ between this connection and the original. + ssl_early_data_quic_parameter_mismatch = 13, + // The application settings did not match the session. + ssl_early_data_alps_mismatch = 14, + // The value of the largest entry. + ssl_early_data_reason_max_value = ssl_early_data_alps_mismatch, +}; + +// SSL_get_early_data_reason returns details why 0-RTT was accepted or rejected +// on |ssl|. This is primarily useful on the server. +OPENSSL_EXPORT enum ssl_early_data_reason_t SSL_get_early_data_reason( + const SSL *ssl); + +// SSL_early_data_reason_string returns a string representation for |reason|, or +// NULL if |reason| is unknown. This function may be used for logging. +OPENSSL_EXPORT const char *SSL_early_data_reason_string( + enum ssl_early_data_reason_t reason); + + +// Encrypted ClientHello. +// +// ECH is a mechanism for encrypting the entire ClientHello message in TLS 1.3. +// This can prevent observers from seeing cleartext information about the +// connection, such as the server_name extension. +// +// By default, BoringSSL will treat the server name, session ticket, and client +// certificate as secret, but most other parameters, such as the ALPN protocol +// list will be treated as public and sent in the cleartext ClientHello. Other +// APIs may be added for applications with different secrecy requirements. +// +// ECH support in BoringSSL is still experimental and under development. +// +// See https://tools.ietf.org/html/draft-ietf-tls-esni-13. + +// SSL_set_enable_ech_grease configures whether the client will send a GREASE +// ECH extension when no supported ECHConfig is available. +OPENSSL_EXPORT void SSL_set_enable_ech_grease(SSL *ssl, int enable); + +// SSL_set1_ech_config_list configures |ssl| to, as a client, offer ECH with the +// specified configuration. |ech_config_list| should contain a serialized +// ECHConfigList structure. It returns one on success and zero on error. +// +// This function returns an error if the input is malformed. If the input is +// valid but none of the ECHConfigs implement supported parameters, it will +// return success and proceed without ECH. +// +// If a supported ECHConfig is found, |ssl| will encrypt the true ClientHello +// parameters. If the server cannot decrypt it, e.g. due to a key mismatch, ECH +// has a recovery flow. |ssl| will handshake using the cleartext parameters, +// including a public name in the ECHConfig. If using +// |SSL_CTX_set_custom_verify|, callers should use |SSL_get0_ech_name_override| +// to verify the certificate with the public name. If using the built-in +// verifier, the |X509_STORE_CTX| will be configured automatically. +// +// If no other errors are found in this handshake, it will fail with +// |SSL_R_ECH_REJECTED|. Since it didn't use the true parameters, the connection +// cannot be used for application data. Instead, callers should handle this +// error by calling |SSL_get0_ech_retry_configs| and retrying the connection +// with updated ECH parameters. If the retry also fails with +// |SSL_R_ECH_REJECTED|, the caller should report a connection failure. +OPENSSL_EXPORT int SSL_set1_ech_config_list(SSL *ssl, + const uint8_t *ech_config_list, + size_t ech_config_list_len); + +// SSL_get0_ech_name_override, if |ssl| is a client and the server rejected ECH, +// sets |*out_name| and |*out_name_len| to point to a buffer containing the ECH +// public name. Otherwise, the buffer will be empty. +// +// When offering ECH as a client, this function should be called during the +// certificate verification callback (see |SSL_CTX_set_custom_verify|). If +// |*out_name_len| is non-zero, the caller should verify the certificate against +// the result, interpreted as a DNS name, rather than the true server name. In +// this case, the handshake will never succeed and is only used to authenticate +// retry configs. See also |SSL_get0_ech_retry_configs|. +OPENSSL_EXPORT void SSL_get0_ech_name_override(const SSL *ssl, + const char **out_name, + size_t *out_name_len); + +// SSL_get0_ech_retry_configs sets |*out_retry_configs| and +// |*out_retry_configs_len| to a buffer containing a serialized ECHConfigList. +// If the server did not provide an ECHConfigList, |*out_retry_configs_len| will +// be zero. +// +// When handling an |SSL_R_ECH_REJECTED| error code as a client, callers should +// use this function to recover from potential key mismatches. If the result is +// non-empty, the caller should retry the connection, passing this buffer to +// |SSL_set1_ech_config_list|. If the result is empty, the server has rolled +// back ECH support, and the caller should retry without ECH. +// +// This function must only be called in response to an |SSL_R_ECH_REJECTED| +// error code. Calling this function on |ssl|s that have not authenticated the +// rejection handshake will assert in debug builds and otherwise return an +// unparsable list. +OPENSSL_EXPORT void SSL_get0_ech_retry_configs( + const SSL *ssl, const uint8_t **out_retry_configs, + size_t *out_retry_configs_len); + +// SSL_marshal_ech_config constructs a new serialized ECHConfig. On success, it +// sets |*out| to a newly-allocated buffer containing the result and |*out_len| +// to the size of the buffer. The caller must call |OPENSSL_free| on |*out| to +// release the memory. On failure, it returns zero. +// +// The |config_id| field is a single byte identifer for the ECHConfig. Reusing +// config IDs is allowed, but if multiple ECHConfigs with the same config ID are +// active at a time, server load may increase. See +// |SSL_ECH_KEYS_has_duplicate_config_id|. +// +// The public key and KEM algorithm are taken from |key|. |public_name| is the +// DNS name used to authenticate the recovery flow. |max_name_len| should be the +// length of the longest name in the ECHConfig's anonymity set and influences +// client padding decisions. +OPENSSL_EXPORT int SSL_marshal_ech_config(uint8_t **out, size_t *out_len, + uint8_t config_id, + const EVP_HPKE_KEY *key, + const char *public_name, + size_t max_name_len); + +// SSL_ECH_KEYS_new returns a newly-allocated |SSL_ECH_KEYS| or NULL on error. +OPENSSL_EXPORT SSL_ECH_KEYS *SSL_ECH_KEYS_new(void); + +// SSL_ECH_KEYS_up_ref increments the reference count of |keys|. +OPENSSL_EXPORT void SSL_ECH_KEYS_up_ref(SSL_ECH_KEYS *keys); + +// SSL_ECH_KEYS_free releases memory associated with |keys|. +OPENSSL_EXPORT void SSL_ECH_KEYS_free(SSL_ECH_KEYS *keys); + +// SSL_ECH_KEYS_add decodes |ech_config| as an ECHConfig and appends it with +// |key| to |keys|. If |is_retry_config| is non-zero, this config will be +// returned to the client on configuration mismatch. It returns one on success +// and zero on error. +// +// This function should be called successively to register each ECHConfig in +// decreasing order of preference. This configuration must be completed before +// setting |keys| on an |SSL_CTX| with |SSL_CTX_set1_ech_keys|. After that +// point, |keys| is immutable; no more ECHConfig values may be added. +// +// See also |SSL_CTX_set1_ech_keys|. +OPENSSL_EXPORT int SSL_ECH_KEYS_add(SSL_ECH_KEYS *keys, int is_retry_config, + const uint8_t *ech_config, + size_t ech_config_len, + const EVP_HPKE_KEY *key); + +// SSL_ECH_KEYS_has_duplicate_config_id returns one if |keys| has duplicate +// config IDs or zero otherwise. Duplicate config IDs still work, but may +// increase server load due to trial decryption. +OPENSSL_EXPORT int SSL_ECH_KEYS_has_duplicate_config_id( + const SSL_ECH_KEYS *keys); + +// SSL_ECH_KEYS_marshal_retry_configs serializes the retry configs in |keys| as +// an ECHConfigList. On success, it sets |*out| to a newly-allocated buffer +// containing the result and |*out_len| to the size of the buffer. The caller +// must call |OPENSSL_free| on |*out| to release the memory. On failure, it +// returns zero. +// +// This output may be advertised to clients in DNS. +OPENSSL_EXPORT int SSL_ECH_KEYS_marshal_retry_configs(const SSL_ECH_KEYS *keys, + uint8_t **out, + size_t *out_len); + +// SSL_CTX_set1_ech_keys configures |ctx| to use |keys| to decrypt encrypted +// ClientHellos. It returns one on success, and zero on failure. If |keys| does +// not contain any retry configs, this function will fail. Retry configs are +// marked as such when they are added to |keys| with |SSL_ECH_KEYS_add|. +// +// Once |keys| has been passed to this function, it is immutable. Unlike most +// |SSL_CTX| configuration functions, this function may be called even if |ctx| +// already has associated connections on multiple threads. This may be used to +// rotate keys in a long-lived server process. +// +// The configured ECHConfig values should also be advertised out-of-band via DNS +// (see draft-ietf-dnsop-svcb-https). Before advertising an ECHConfig in DNS, +// deployments should ensure all instances of the service are configured with +// the ECHConfig and corresponding private key. +// +// Only the most recent fully-deployed ECHConfigs should be advertised in DNS. +// |keys| may contain a newer set if those ECHConfigs are mid-deployment. It +// should also contain older sets, until the DNS change has rolled out and the +// old records have expired from caches. +// +// If there is a mismatch, |SSL| objects associated with |ctx| will complete the +// handshake using the cleartext ClientHello and send updated ECHConfig values +// to the client. The client will then retry to recover, but with a latency +// penalty. This recovery flow depends on the public name in the ECHConfig. +// Before advertising an ECHConfig in DNS, deployments must ensure all instances +// of the service can present a valid certificate for the public name. +// +// BoringSSL negotiates ECH before certificate selection callbacks are called, +// including |SSL_CTX_set_select_certificate_cb|. If ECH is negotiated, the +// reported |SSL_CLIENT_HELLO| structure and |SSL_get_servername| function will +// transparently reflect the inner ClientHello. Callers should select parameters +// based on these values to correctly handle ECH as well as the recovery flow. +OPENSSL_EXPORT int SSL_CTX_set1_ech_keys(SSL_CTX *ctx, SSL_ECH_KEYS *keys); + +// SSL_ech_accepted returns one if |ssl| negotiated ECH and zero otherwise. +OPENSSL_EXPORT int SSL_ech_accepted(const SSL *ssl); + + +// Alerts. +// +// TLS uses alerts to signal error conditions. Alerts have a type (warning or +// fatal) and description. OpenSSL internally handles fatal alerts with +// dedicated error codes (see |SSL_AD_REASON_OFFSET|). Except for close_notify, +// warning alerts are silently ignored and may only be surfaced with +// |SSL_CTX_set_info_callback|. + +// SSL_AD_REASON_OFFSET is the offset between error reasons and |SSL_AD_*| +// values. Any error code under |ERR_LIB_SSL| with an error reason above this +// value corresponds to an alert description. Consumers may add or subtract +// |SSL_AD_REASON_OFFSET| to convert between them. +// +// make_errors.go reserves error codes above 1000 for manually-assigned errors. +// This value must be kept in sync with reservedReasonCode in make_errors.h +#define SSL_AD_REASON_OFFSET 1000 + +// SSL_AD_* are alert descriptions. +#define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY +#define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE +#define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC +#define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED +#define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW +#define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE +#define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE +#define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE // Legacy SSL 3.0 value +#define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE +#define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE +#define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED +#define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED +#define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN +#define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER +#define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA +#define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED +#define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR +#define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR +#define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION +#define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION +#define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY +#define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR +#define SSL_AD_INAPPROPRIATE_FALLBACK SSL3_AD_INAPPROPRIATE_FALLBACK +#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED +#define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION +#define SSL_AD_MISSING_EXTENSION TLS1_AD_MISSING_EXTENSION +#define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION +#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE +#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME +#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE \ + TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE +#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE +#define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY +#define SSL_AD_CERTIFICATE_REQUIRED TLS1_AD_CERTIFICATE_REQUIRED +#define SSL_AD_NO_APPLICATION_PROTOCOL TLS1_AD_NO_APPLICATION_PROTOCOL +#define SSL_AD_ECH_REQUIRED TLS1_AD_ECH_REQUIRED + +// SSL_alert_type_string_long returns a string description of |value| as an +// alert type (warning or fatal). +OPENSSL_EXPORT const char *SSL_alert_type_string_long(int value); + +// SSL_alert_desc_string_long returns a string description of |value| as an +// alert description or "unknown" if unknown. +OPENSSL_EXPORT const char *SSL_alert_desc_string_long(int value); + +// SSL_send_fatal_alert sends a fatal alert over |ssl| of the specified type, +// which should be one of the |SSL_AD_*| constants. It returns one on success +// and <= 0 on error. The caller should pass the return value into +// |SSL_get_error| to determine how to proceed. Once this function has been +// called, future calls to |SSL_write| will fail. +// +// If retrying a failed operation due to |SSL_ERROR_WANT_WRITE|, subsequent +// calls must use the same |alert| parameter. +OPENSSL_EXPORT int SSL_send_fatal_alert(SSL *ssl, uint8_t alert); + + +// ex_data functions. +// +// See |ex_data.h| for details. + +OPENSSL_EXPORT int SSL_set_ex_data(SSL *ssl, int idx, void *data); +OPENSSL_EXPORT void *SSL_get_ex_data(const SSL *ssl, int idx); +OPENSSL_EXPORT int SSL_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); + +OPENSSL_EXPORT int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, + void *data); +OPENSSL_EXPORT void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, + int idx); +OPENSSL_EXPORT int SSL_SESSION_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); + +OPENSSL_EXPORT int SSL_CTX_set_ex_data(SSL_CTX *ctx, int idx, void *data); +OPENSSL_EXPORT void *SSL_CTX_get_ex_data(const SSL_CTX *ctx, int idx); +OPENSSL_EXPORT int SSL_CTX_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); + + +// Low-level record-layer state. + +// SSL_get_ivs sets |*out_iv_len| to the length of the IVs for the ciphers +// underlying |ssl| and sets |*out_read_iv| and |*out_write_iv| to point to the +// current IVs for the read and write directions. This is only meaningful for +// connections with implicit IVs (i.e. CBC mode with TLS 1.0). +// +// It returns one on success or zero on error. +OPENSSL_EXPORT int SSL_get_ivs(const SSL *ssl, const uint8_t **out_read_iv, + const uint8_t **out_write_iv, + size_t *out_iv_len); + +// SSL_get_key_block_len returns the length of |ssl|'s key block, for TLS 1.2 +// and below. It is an error to call this function during a handshake, or if +// |ssl| negotiated TLS 1.3. +OPENSSL_EXPORT size_t SSL_get_key_block_len(const SSL *ssl); + +// SSL_generate_key_block generates |out_len| bytes of key material for |ssl|'s +// current connection state, for TLS 1.2 and below. It is an error to call this +// function during a handshake, or if |ssl| negotiated TLS 1.3. +OPENSSL_EXPORT int SSL_generate_key_block(const SSL *ssl, uint8_t *out, + size_t out_len); + +// SSL_get_read_sequence returns, in TLS, the expected sequence number of the +// next incoming record in the current epoch. In DTLS, it returns the maximum +// sequence number received in the current epoch and includes the epoch number +// in the two most significant bytes. +OPENSSL_EXPORT uint64_t SSL_get_read_sequence(const SSL *ssl); + +// SSL_get_write_sequence returns the sequence number of the next outgoing +// record in the current epoch. In DTLS, it includes the epoch number in the +// two most significant bytes. +OPENSSL_EXPORT uint64_t SSL_get_write_sequence(const SSL *ssl); + +// SSL_CTX_set_record_protocol_version returns whether |version| is zero. +OPENSSL_EXPORT int SSL_CTX_set_record_protocol_version(SSL_CTX *ctx, + int version); + + +// Handshake hints. +// +// *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING *** +// +// Some server deployments make asynchronous RPC calls in both ClientHello +// dispatch and private key operations. In TLS handshakes where the private key +// operation occurs in the first round-trip, this results in two consecutive RPC +// round-trips. Handshake hints allow the RPC service to predicte a signature. +// If correctly predicted, this can skip the second RPC call. +// +// First, the server installs a certificate selection callback (see +// |SSL_CTX_set_select_certificate_cb|). When that is called, it performs the +// RPC as before, but includes the ClientHello and a capabilities string from +// |SSL_serialize_capabilities|. +// +// Next, the RPC service creates its own |SSL| object, applies the results of +// certificate selection, calls |SSL_request_handshake_hints|, and runs the +// handshake. If this successfully computes handshake hints (see +// |SSL_serialize_handshake_hints|), the RPC server should send the hints +// alongside any certificate selection results. +// +// Finally, the server calls |SSL_set_handshake_hints| and applies any +// configuration from the RPC server. It then completes the handshake as before. +// If the hints apply, BoringSSL will use the predicted signature and skip the +// private key callbacks. Otherwise, BoringSSL will call private key callbacks +// to generate a signature as before. +// +// Callers should synchronize configuration across the two services. +// Configuration mismatches and some cases of version skew are not fatal, but +// may result in the hints not applying. Additionally, some handshake flows use +// the private key in later round-trips, such as TLS 1.3 HelloRetryRequest. In +// those cases, BoringSSL will not predict a signature as there is no benefit. +// Callers must allow for handshakes to complete without a predicted signature. +// +// Handshake hints are supported for TLS 1.3 and partially supported for +// TLS 1.2. TLS 1.2 resumption handshakes are not yet fully hinted. They will +// still work, but may not be as efficient. + +// SSL_serialize_capabilities writes an opaque byte string to |out| describing +// some of |ssl|'s capabilities. It returns one on success and zero on error. +// +// This string is used by BoringSSL internally to reduce the impact of version +// skew. +OPENSSL_EXPORT int SSL_serialize_capabilities(const SSL *ssl, CBB *out); + +// SSL_request_handshake_hints configures |ssl| to generate a handshake hint for +// |client_hello|. It returns one on success and zero on error. |client_hello| +// should contain a serialized ClientHello structure, from the |client_hello| +// and |client_hello_len| fields of the |SSL_CLIENT_HELLO| structure. +// |capabilities| should contain the output of |SSL_serialize_capabilities|. +// +// When configured, |ssl| will perform no I/O (so there is no need to configure +// |BIO|s). For QUIC, the caller should still configure an |SSL_QUIC_METHOD|, +// but the callbacks themselves will never be called and may be left NULL or +// report failure. |SSL_provide_quic_data| also should not be called. +// +// If hint generation is successful, |SSL_do_handshake| will stop the handshake +// early with |SSL_get_error| returning |SSL_ERROR_HANDSHAKE_HINTS_READY|. At +// this point, the caller should run |SSL_serialize_handshake_hints| to extract +// the resulting hints. +// +// Hint generation may fail if, e.g., |ssl| was unable to process the +// ClientHello. Callers should then complete the certificate selection RPC and +// continue the original handshake with no hint. It will likely fail, but this +// reports the correct alert to the client and is more robust in case of +// mismatch. +OPENSSL_EXPORT int SSL_request_handshake_hints(SSL *ssl, + const uint8_t *client_hello, + size_t client_hello_len, + const uint8_t *capabilities, + size_t capabilities_len); + +// SSL_serialize_handshake_hints writes an opaque byte string to |out| +// containing the handshake hints computed by |out|. It returns one on success +// and zero on error. This function should only be called if +// |SSL_request_handshake_hints| was configured and the handshake terminated +// with |SSL_ERROR_HANDSHAKE_HINTS_READY|. +// +// This string may be passed to |SSL_set_handshake_hints| on another |SSL| to +// avoid an extra signature call. +OPENSSL_EXPORT int SSL_serialize_handshake_hints(const SSL *ssl, CBB *out); + +// SSL_set_handshake_hints configures |ssl| to use |hints| as handshake hints. +// It returns one on success and zero on error. The handshake will then continue +// as before, but apply predicted values from |hints| where applicable. +// +// Hints may contain connection and session secrets, so they must not leak and +// must come from a source trusted to terminate the connection. However, they +// will not change |ssl|'s configuration. The caller is responsible for +// serializing and applying options from the RPC server as needed. This ensures +// |ssl|'s behavior is self-consistent and consistent with the caller's local +// decisions. +OPENSSL_EXPORT int SSL_set_handshake_hints(SSL *ssl, const uint8_t *hints, + size_t hints_len); + + +// Obscure functions. + +// SSL_CTX_set_msg_callback installs |cb| as the message callback for |ctx|. +// This callback will be called when sending or receiving low-level record +// headers, complete handshake messages, ChangeCipherSpec, and alerts. +// |write_p| is one for outgoing messages and zero for incoming messages. +// +// For each record header, |cb| is called with |version| = 0 and |content_type| +// = |SSL3_RT_HEADER|. The |len| bytes from |buf| contain the header. Note that +// this does not include the record body. If the record is sealed, the length +// in the header is the length of the ciphertext. +// +// For each handshake message, ChangeCipherSpec, and alert, |version| is the +// protocol version and |content_type| is the corresponding record type. The +// |len| bytes from |buf| contain the handshake message, one-byte +// ChangeCipherSpec body, and two-byte alert, respectively. +// +// In connections that enable ECH, |cb| is additionally called with +// |content_type| = |SSL3_RT_CLIENT_HELLO_INNER| for each ClientHelloInner that +// is encrypted or decrypted. The |len| bytes from |buf| contain the +// ClientHelloInner, including the reconstructed outer extensions and handshake +// header. +// +// For a V2ClientHello, |version| is |SSL2_VERSION|, |content_type| is zero, and +// the |len| bytes from |buf| contain the V2ClientHello structure. +OPENSSL_EXPORT void SSL_CTX_set_msg_callback( + SSL_CTX *ctx, void (*cb)(int is_write, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg)); + +// SSL_CTX_set_msg_callback_arg sets the |arg| parameter of the message +// callback. +OPENSSL_EXPORT void SSL_CTX_set_msg_callback_arg(SSL_CTX *ctx, void *arg); + +// SSL_set_msg_callback installs |cb| as the message callback of |ssl|. See +// |SSL_CTX_set_msg_callback| for when this callback is called. +OPENSSL_EXPORT void SSL_set_msg_callback( + SSL *ssl, void (*cb)(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg)); + +// SSL_set_msg_callback_arg sets the |arg| parameter of the message callback. +OPENSSL_EXPORT void SSL_set_msg_callback_arg(SSL *ssl, void *arg); + +// SSL_CTX_set_keylog_callback configures a callback to log key material. This +// is intended for debugging use with tools like Wireshark. The |cb| function +// should log |line| followed by a newline, synchronizing with any concurrent +// access to the log. +// +// The format is described in +// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. +OPENSSL_EXPORT void SSL_CTX_set_keylog_callback( + SSL_CTX *ctx, void (*cb)(const SSL *ssl, const char *line)); + +// SSL_CTX_get_keylog_callback returns the callback configured by +// |SSL_CTX_set_keylog_callback|. +OPENSSL_EXPORT void (*SSL_CTX_get_keylog_callback(const SSL_CTX *ctx))( + const SSL *ssl, const char *line); + +// SSL_CTX_set_current_time_cb configures a callback to retrieve the current +// time, which should be set in |*out_clock|. This can be used for testing +// purposes; for example, a callback can be configured that returns a time +// set explicitly by the test. The |ssl| pointer passed to |cb| is always null. +OPENSSL_EXPORT void SSL_CTX_set_current_time_cb( + SSL_CTX *ctx, void (*cb)(const SSL *ssl, struct timeval *out_clock)); + +// SSL_set_shed_handshake_config allows some of the configuration of |ssl| to be +// freed after its handshake completes. Once configuration has been shed, APIs +// that query it may fail. "Configuration" in this context means anything that +// was set by the caller, as distinct from information derived from the +// handshake. For example, |SSL_get_ciphers| queries how the |SSL| was +// configured by the caller, and fails after configuration has been shed, +// whereas |SSL_get_cipher| queries the result of the handshake, and is +// unaffected by configuration shedding. +// +// If configuration shedding is enabled, it is an error to call |SSL_clear|. +// +// Note that configuration shedding as a client additionally depends on +// renegotiation being disabled (see |SSL_set_renegotiate_mode|). If +// renegotiation is possible, the configuration will be retained. If +// configuration shedding is enabled and renegotiation later disabled after the +// handshake, |SSL_set_renegotiate_mode| will shed configuration then. This may +// be useful for clients which support renegotiation with some ALPN protocols, +// such as HTTP/1.1, and not others, such as HTTP/2. +OPENSSL_EXPORT void SSL_set_shed_handshake_config(SSL *ssl, int enable); + +enum ssl_renegotiate_mode_t BORINGSSL_ENUM_INT { + ssl_renegotiate_never = 0, + ssl_renegotiate_once, + ssl_renegotiate_freely, + ssl_renegotiate_ignore, + ssl_renegotiate_explicit, +}; + +// SSL_set_renegotiate_mode configures how |ssl|, a client, reacts to +// renegotiation attempts by a server. If |ssl| is a server, peer-initiated +// renegotiations are *always* rejected and this function does nothing. +// +// WARNING: Renegotiation is error-prone, complicates TLS's security properties, +// and increases its attack surface. When enabled, many common assumptions about +// BoringSSL's behavior no longer hold, and the calling application must handle +// more cases. Renegotiation is also incompatible with many application +// protocols, e.g. section 9.2.1 of RFC 7540. Many functions behave in ambiguous +// or undefined ways during a renegotiation. +// +// The renegotiation mode defaults to |ssl_renegotiate_never|, but may be set +// at any point in a connection's lifetime. Set it to |ssl_renegotiate_once| to +// allow one renegotiation, |ssl_renegotiate_freely| to allow all +// renegotiations or |ssl_renegotiate_ignore| to ignore HelloRequest messages. +// Note that ignoring HelloRequest messages may cause the connection to stall +// if the server waits for the renegotiation to complete. +// +// If set to |ssl_renegotiate_explicit|, |SSL_read| and |SSL_peek| calls which +// encounter a HelloRequest will pause with |SSL_ERROR_WANT_RENEGOTIATE|. +// |SSL_write| will continue to work while paused. The caller may call +// |SSL_renegotiate| to begin the renegotiation at a later point. This mode may +// be used if callers wish to eagerly call |SSL_peek| without triggering a +// renegotiation. +// +// If configuration shedding is enabled (see |SSL_set_shed_handshake_config|), +// configuration is released if, at any point after the handshake, renegotiation +// is disabled. It is not possible to switch from disabling renegotiation to +// enabling it on a given connection. Callers that condition renegotiation on, +// e.g., ALPN must enable renegotiation before the handshake and conditionally +// disable it afterwards. +// +// When enabled, renegotiation can cause properties of |ssl|, such as the cipher +// suite, to change during the lifetime of the connection. More over, during a +// renegotiation, not all properties of the new handshake are available or fully +// established. In BoringSSL, most functions, such as |SSL_get_current_cipher|, +// report information from the most recently completed handshake, not the +// pending one. However, renegotiation may rerun handshake callbacks, such as +// |SSL_CTX_set_cert_cb|. Such callbacks must ensure they are acting on the +// desired versions of each property. +// +// BoringSSL does not reverify peer certificates on renegotiation and instead +// requires they match between handshakes, so certificate verification callbacks +// (see |SSL_CTX_set_custom_verify|) may assume |ssl| is in the initial +// handshake and use |SSL_get0_peer_certificates|, etc. +// +// There is no support in BoringSSL for initiating renegotiations as a client +// or server. +OPENSSL_EXPORT void SSL_set_renegotiate_mode(SSL *ssl, + enum ssl_renegotiate_mode_t mode); + +// SSL_renegotiate starts a deferred renegotiation on |ssl| if it was configured +// with |ssl_renegotiate_explicit| and has a pending HelloRequest. It returns +// one on success and zero on error. +// +// This function does not do perform any I/O. On success, a subsequent +// |SSL_do_handshake| call will run the handshake. |SSL_write| and +// |SSL_read| will also complete the handshake before sending or receiving +// application data. +OPENSSL_EXPORT int SSL_renegotiate(SSL *ssl); + +// SSL_renegotiate_pending returns one if |ssl| is in the middle of a +// renegotiation. +OPENSSL_EXPORT int SSL_renegotiate_pending(SSL *ssl); + +// SSL_total_renegotiations returns the total number of renegotiation handshakes +// performed by |ssl|. This includes the pending renegotiation, if any. +OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl); + +// SSL_MAX_CERT_LIST_DEFAULT is the default maximum length, in bytes, of a peer +// certificate chain. +#define SSL_MAX_CERT_LIST_DEFAULT (1024 * 100) + +// SSL_CTX_get_max_cert_list returns the maximum length, in bytes, of a peer +// certificate chain accepted by |ctx|. +OPENSSL_EXPORT size_t SSL_CTX_get_max_cert_list(const SSL_CTX *ctx); + +// SSL_CTX_set_max_cert_list sets the maximum length, in bytes, of a peer +// certificate chain to |max_cert_list|. This affects how much memory may be +// consumed during the handshake. +OPENSSL_EXPORT void SSL_CTX_set_max_cert_list(SSL_CTX *ctx, + size_t max_cert_list); + +// SSL_get_max_cert_list returns the maximum length, in bytes, of a peer +// certificate chain accepted by |ssl|. +OPENSSL_EXPORT size_t SSL_get_max_cert_list(const SSL *ssl); + +// SSL_set_max_cert_list sets the maximum length, in bytes, of a peer +// certificate chain to |max_cert_list|. This affects how much memory may be +// consumed during the handshake. +OPENSSL_EXPORT void SSL_set_max_cert_list(SSL *ssl, size_t max_cert_list); + +// SSL_CTX_set_max_send_fragment sets the maximum length, in bytes, of records +// sent by |ctx|. Beyond this length, handshake messages and application data +// will be split into multiple records. It returns one on success or zero on +// error. +OPENSSL_EXPORT int SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, + size_t max_send_fragment); + +// SSL_set_max_send_fragment sets the maximum length, in bytes, of records sent +// by |ssl|. Beyond this length, handshake messages and application data will +// be split into multiple records. It returns one on success or zero on +// error. +OPENSSL_EXPORT int SSL_set_max_send_fragment(SSL *ssl, + size_t max_send_fragment); + +// ssl_early_callback_ctx (aka |SSL_CLIENT_HELLO|) is passed to certain +// callbacks that are called very early on during the server handshake. At this +// point, much of the SSL* hasn't been filled out and only the ClientHello can +// be depended on. +struct ssl_early_callback_ctx { + SSL *ssl; + const uint8_t *client_hello; + size_t client_hello_len; + uint16_t version; + const uint8_t *random; + size_t random_len; + const uint8_t *session_id; + size_t session_id_len; + const uint8_t *cipher_suites; + size_t cipher_suites_len; + const uint8_t *compression_methods; + size_t compression_methods_len; + const uint8_t *extensions; + size_t extensions_len; +} /* SSL_CLIENT_HELLO */; + +// ssl_select_cert_result_t enumerates the possible results from selecting a +// certificate with |select_certificate_cb|. +enum ssl_select_cert_result_t BORINGSSL_ENUM_INT { + // ssl_select_cert_success indicates that the certificate selection was + // successful. + ssl_select_cert_success = 1, + // ssl_select_cert_retry indicates that the operation could not be + // immediately completed and must be reattempted at a later point. + ssl_select_cert_retry = 0, + // ssl_select_cert_error indicates that a fatal error occured and the + // handshake should be terminated. + ssl_select_cert_error = -1, +}; + +// SSL_early_callback_ctx_extension_get searches the extensions in +// |client_hello| for an extension of the given type. If not found, it returns +// zero. Otherwise it sets |out_data| to point to the extension contents (not +// including the type and length bytes), sets |out_len| to the length of the +// extension contents and returns one. +OPENSSL_EXPORT int SSL_early_callback_ctx_extension_get( + const SSL_CLIENT_HELLO *client_hello, uint16_t extension_type, + const uint8_t **out_data, size_t *out_len); + +// SSL_CTX_set_select_certificate_cb sets a callback that is called before most +// ClientHello processing and before the decision whether to resume a session +// is made. The callback may inspect the ClientHello and configure the +// connection. See |ssl_select_cert_result_t| for details of the return values. +// +// In the case that a retry is indicated, |SSL_get_error| will return +// |SSL_ERROR_PENDING_CERTIFICATE| and the caller should arrange for the +// high-level operation on |ssl| to be retried at a later time, which will +// result in another call to |cb|. +// +// |SSL_get_servername| may be used during this callback. +// +// Note: The |SSL_CLIENT_HELLO| is only valid for the duration of the callback +// and is not valid while the handshake is paused. +OPENSSL_EXPORT void SSL_CTX_set_select_certificate_cb( + SSL_CTX *ctx, + enum ssl_select_cert_result_t (*cb)(const SSL_CLIENT_HELLO *)); + +// SSL_CTX_set_dos_protection_cb sets a callback that is called once the +// resumption decision for a ClientHello has been made. It can return one to +// allow the handshake to continue or zero to cause the handshake to abort. +OPENSSL_EXPORT void SSL_CTX_set_dos_protection_cb( + SSL_CTX *ctx, int (*cb)(const SSL_CLIENT_HELLO *)); + +// SSL_CTX_set_reverify_on_resume configures whether the certificate +// verification callback will be used to reverify stored certificates +// when resuming a session. This only works with |SSL_CTX_set_custom_verify|. +// For now, this is incompatible with |SSL_VERIFY_NONE| mode, and is only +// respected on clients. +OPENSSL_EXPORT void SSL_CTX_set_reverify_on_resume(SSL_CTX *ctx, int enabled); + +// SSL_set_enforce_rsa_key_usage configures whether, when |ssl| is a client +// negotiating TLS 1.2 or below, the keyUsage extension of RSA leaf server +// certificates will be checked for consistency with the TLS usage. In all other +// cases, this check is always enabled. +// +// This parameter may be set late; it will not be read until after the +// certificate verification callback. +OPENSSL_EXPORT void SSL_set_enforce_rsa_key_usage(SSL *ssl, int enabled); + +// SSL_was_key_usage_invalid returns one if |ssl|'s handshake succeeded despite +// using TLS parameters which were incompatible with the leaf certificate's +// keyUsage extension. Otherwise, it returns zero. +// +// If |SSL_set_enforce_rsa_key_usage| is enabled or not applicable, this +// function will always return zero because key usages will be consistently +// checked. +OPENSSL_EXPORT int SSL_was_key_usage_invalid(const SSL *ssl); + +// SSL_ST_* are possible values for |SSL_state|, the bitmasks that make them up, +// and some historical values for compatibility. Only |SSL_ST_INIT| and +// |SSL_ST_OK| are ever returned. +#define SSL_ST_CONNECT 0x1000 +#define SSL_ST_ACCEPT 0x2000 +#define SSL_ST_MASK 0x0FFF +#define SSL_ST_INIT (SSL_ST_CONNECT | SSL_ST_ACCEPT) +#define SSL_ST_OK 0x03 +#define SSL_ST_RENEGOTIATE (0x04 | SSL_ST_INIT) +#define SSL_ST_BEFORE (0x05 | SSL_ST_INIT) + +// TLS_ST_* are aliases for |SSL_ST_*| for OpenSSL 1.1.0 compatibility. +#define TLS_ST_OK SSL_ST_OK +#define TLS_ST_BEFORE SSL_ST_BEFORE + +// SSL_CB_* are possible values for the |type| parameter in the info +// callback and the bitmasks that make them up. +#define SSL_CB_LOOP 0x01 +#define SSL_CB_EXIT 0x02 +#define SSL_CB_READ 0x04 +#define SSL_CB_WRITE 0x08 +#define SSL_CB_ALERT 0x4000 +#define SSL_CB_READ_ALERT (SSL_CB_ALERT | SSL_CB_READ) +#define SSL_CB_WRITE_ALERT (SSL_CB_ALERT | SSL_CB_WRITE) +#define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT | SSL_CB_LOOP) +#define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT | SSL_CB_EXIT) +#define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT | SSL_CB_LOOP) +#define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT | SSL_CB_EXIT) +#define SSL_CB_HANDSHAKE_START 0x10 +#define SSL_CB_HANDSHAKE_DONE 0x20 + +// SSL_CTX_set_info_callback configures a callback to be run when various +// events occur during a connection's lifetime. The |type| argument determines +// the type of event and the meaning of the |value| argument. Callbacks must +// ignore unexpected |type| values. +// +// |SSL_CB_READ_ALERT| is signaled for each alert received, warning or fatal. +// The |value| argument is a 16-bit value where the alert level (either +// |SSL3_AL_WARNING| or |SSL3_AL_FATAL|) is in the most-significant eight bits +// and the alert type (one of |SSL_AD_*|) is in the least-significant eight. +// +// |SSL_CB_WRITE_ALERT| is signaled for each alert sent. The |value| argument +// is constructed as with |SSL_CB_READ_ALERT|. +// +// |SSL_CB_HANDSHAKE_START| is signaled when a handshake begins. The |value| +// argument is always one. +// +// |SSL_CB_HANDSHAKE_DONE| is signaled when a handshake completes successfully. +// The |value| argument is always one. If a handshake False Starts, this event +// may be used to determine when the Finished message is received. +// +// The following event types expose implementation details of the handshake +// state machine. Consuming them is deprecated. +// +// |SSL_CB_ACCEPT_LOOP| (respectively, |SSL_CB_CONNECT_LOOP|) is signaled when +// a server (respectively, client) handshake progresses. The |value| argument +// is always one. +// +// |SSL_CB_ACCEPT_EXIT| (respectively, |SSL_CB_CONNECT_EXIT|) is signaled when +// a server (respectively, client) handshake completes, fails, or is paused. +// The |value| argument is one if the handshake succeeded and <= 0 +// otherwise. +OPENSSL_EXPORT void SSL_CTX_set_info_callback( + SSL_CTX *ctx, void (*cb)(const SSL *ssl, int type, int value)); + +// SSL_CTX_get_info_callback returns the callback set by +// |SSL_CTX_set_info_callback|. +OPENSSL_EXPORT void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, + int type, + int value); + +// SSL_set_info_callback configures a callback to be run at various events +// during a connection's lifetime. See |SSL_CTX_set_info_callback|. +OPENSSL_EXPORT void SSL_set_info_callback( + SSL *ssl, void (*cb)(const SSL *ssl, int type, int value)); + +// SSL_get_info_callback returns the callback set by |SSL_set_info_callback|. +OPENSSL_EXPORT void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl, + int type, + int value); + +// SSL_state_string_long returns the current state of the handshake state +// machine as a string. This may be useful for debugging and logging. +OPENSSL_EXPORT const char *SSL_state_string_long(const SSL *ssl); + +#define SSL_SENT_SHUTDOWN 1 +#define SSL_RECEIVED_SHUTDOWN 2 + +// SSL_get_shutdown returns a bitmask with a subset of |SSL_SENT_SHUTDOWN| and +// |SSL_RECEIVED_SHUTDOWN| to query whether close_notify was sent or received, +// respectively. +OPENSSL_EXPORT int SSL_get_shutdown(const SSL *ssl); + +// SSL_get_peer_signature_algorithm returns the signature algorithm used by the +// peer. If not applicable, it returns zero. +OPENSSL_EXPORT uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl); + +// SSL_get_client_random writes up to |max_out| bytes of the most recent +// handshake's client_random to |out| and returns the number of bytes written. +// If |max_out| is zero, it returns the size of the client_random. +OPENSSL_EXPORT size_t SSL_get_client_random(const SSL *ssl, uint8_t *out, + size_t max_out); + +// SSL_get_server_random writes up to |max_out| bytes of the most recent +// handshake's server_random to |out| and returns the number of bytes written. +// If |max_out| is zero, it returns the size of the server_random. +OPENSSL_EXPORT size_t SSL_get_server_random(const SSL *ssl, uint8_t *out, + size_t max_out); + +// SSL_get_pending_cipher returns the cipher suite for the current handshake or +// NULL if one has not been negotiated yet or there is no pending handshake. +OPENSSL_EXPORT const SSL_CIPHER *SSL_get_pending_cipher(const SSL *ssl); + +// SSL_set_retain_only_sha256_of_client_certs, on a server, sets whether only +// the SHA-256 hash of peer's certificate should be saved in memory and in the +// session. This can save memory, ticket size and session cache space. If +// enabled, |SSL_get_peer_certificate| will return NULL after the handshake +// completes. See |SSL_SESSION_has_peer_sha256| and +// |SSL_SESSION_get0_peer_sha256| to query the hash. +OPENSSL_EXPORT void SSL_set_retain_only_sha256_of_client_certs(SSL *ssl, + int enable); + +// SSL_CTX_set_retain_only_sha256_of_client_certs, on a server, sets whether +// only the SHA-256 hash of peer's certificate should be saved in memory and in +// the session. This can save memory, ticket size and session cache space. If +// enabled, |SSL_get_peer_certificate| will return NULL after the handshake +// completes. See |SSL_SESSION_has_peer_sha256| and +// |SSL_SESSION_get0_peer_sha256| to query the hash. +OPENSSL_EXPORT void SSL_CTX_set_retain_only_sha256_of_client_certs(SSL_CTX *ctx, + int enable); + +// SSL_CTX_set_grease_enabled configures whether sockets on |ctx| should enable +// GREASE. See RFC 8701. +OPENSSL_EXPORT void SSL_CTX_set_grease_enabled(SSL_CTX *ctx, int enabled); + +// SSL_CTX_set_permute_extensions configures whether sockets on |ctx| should +// permute extensions. For now, this is only implemented for the ClientHello. +OPENSSL_EXPORT void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled); + +// SSL_set_permute_extensions configures whether sockets on |ssl| should +// permute extensions. For now, this is only implemented for the ClientHello. +OPENSSL_EXPORT void SSL_set_permute_extensions(SSL *ssl, int enabled); + +// SSL_max_seal_overhead returns the maximum overhead, in bytes, of sealing a +// record with |ssl|. +OPENSSL_EXPORT size_t SSL_max_seal_overhead(const SSL *ssl); + +// SSL_CTX_set_false_start_allowed_without_alpn configures whether connections +// on |ctx| may use False Start (if |SSL_MODE_ENABLE_FALSE_START| is enabled) +// without negotiating ALPN. +OPENSSL_EXPORT void SSL_CTX_set_false_start_allowed_without_alpn(SSL_CTX *ctx, + int allowed); + +// SSL_used_hello_retry_request returns one if the TLS 1.3 HelloRetryRequest +// message has been either sent by the server or received by the client. It +// returns zero otherwise. +OPENSSL_EXPORT int SSL_used_hello_retry_request(const SSL *ssl); + +// SSL_set_jdk11_workaround configures whether to workaround various bugs in +// JDK 11's TLS 1.3 implementation by disabling TLS 1.3 for such clients. +// +// https://bugs.openjdk.java.net/browse/JDK-8211806 +// https://bugs.openjdk.java.net/browse/JDK-8212885 +// https://bugs.openjdk.java.net/browse/JDK-8213202 +OPENSSL_EXPORT void SSL_set_jdk11_workaround(SSL *ssl, int enable); + + +// Deprecated functions. + +// SSL_library_init calls |CRYPTO_library_init| and returns one. +OPENSSL_EXPORT int SSL_library_init(void); + +// SSL_CIPHER_description writes a description of |cipher| into |buf| and +// returns |buf|. If |buf| is NULL, it returns a newly allocated string, to be +// freed with |OPENSSL_free|, or NULL on error. +// +// The description includes a trailing newline and has the form: +// AES128-SHA Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1 +// +// Consider |SSL_CIPHER_standard_name| or |SSL_CIPHER_get_name| instead. +OPENSSL_EXPORT const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, + char *buf, int len); + +// SSL_CIPHER_get_version returns the string "TLSv1/SSLv3". +OPENSSL_EXPORT const char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher); + +typedef void COMP_METHOD; +typedef struct ssl_comp_st SSL_COMP; + +// SSL_COMP_get_compression_methods returns NULL. +OPENSSL_EXPORT STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); + +// SSL_COMP_add_compression_method returns one. +OPENSSL_EXPORT int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm); + +// SSL_COMP_get_name returns NULL. +OPENSSL_EXPORT const char *SSL_COMP_get_name(const COMP_METHOD *comp); + +// SSL_COMP_get0_name returns the |name| member of |comp|. +OPENSSL_EXPORT const char *SSL_COMP_get0_name(const SSL_COMP *comp); + +// SSL_COMP_get_id returns the |id| member of |comp|. +OPENSSL_EXPORT int SSL_COMP_get_id(const SSL_COMP *comp); + +// SSL_COMP_free_compression_methods does nothing. +OPENSSL_EXPORT void SSL_COMP_free_compression_methods(void); + +// SSLv23_method calls |TLS_method|. +OPENSSL_EXPORT const SSL_METHOD *SSLv23_method(void); + +// These version-specific methods behave exactly like |TLS_method| and +// |DTLS_method| except they also call |SSL_CTX_set_min_proto_version| and +// |SSL_CTX_set_max_proto_version| to lock connections to that protocol +// version. +OPENSSL_EXPORT const SSL_METHOD *TLSv1_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_method(void); +OPENSSL_EXPORT const SSL_METHOD *DTLSv1_method(void); +OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_method(void); + +// These client- and server-specific methods call their corresponding generic +// methods. +OPENSSL_EXPORT const SSL_METHOD *TLS_server_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLS_client_method(void); +OPENSSL_EXPORT const SSL_METHOD *SSLv23_server_method(void); +OPENSSL_EXPORT const SSL_METHOD *SSLv23_client_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLSv1_server_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLSv1_client_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_server_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_client_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_server_method(void); +OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_client_method(void); +OPENSSL_EXPORT const SSL_METHOD *DTLS_server_method(void); +OPENSSL_EXPORT const SSL_METHOD *DTLS_client_method(void); +OPENSSL_EXPORT const SSL_METHOD *DTLSv1_server_method(void); +OPENSSL_EXPORT const SSL_METHOD *DTLSv1_client_method(void); +OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_server_method(void); +OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_client_method(void); + +// SSL_clear resets |ssl| to allow another connection and returns one on success +// or zero on failure. It returns most configuration state but releases memory +// associated with the current connection. +// +// Free |ssl| and create a new one instead. +OPENSSL_EXPORT int SSL_clear(SSL *ssl); + +// SSL_CTX_set_tmp_rsa_callback does nothing. +OPENSSL_EXPORT void SSL_CTX_set_tmp_rsa_callback( + SSL_CTX *ctx, RSA *(*cb)(SSL *ssl, int is_export, int keylength)); + +// SSL_set_tmp_rsa_callback does nothing. +OPENSSL_EXPORT void SSL_set_tmp_rsa_callback(SSL *ssl, + RSA *(*cb)(SSL *ssl, int is_export, + int keylength)); + +// SSL_CTX_sess_connect returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_connect(const SSL_CTX *ctx); + +// SSL_CTX_sess_connect_good returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_connect_good(const SSL_CTX *ctx); + +// SSL_CTX_sess_connect_renegotiate returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx); + +// SSL_CTX_sess_accept returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_accept(const SSL_CTX *ctx); + +// SSL_CTX_sess_accept_renegotiate returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_accept_renegotiate(const SSL_CTX *ctx); + +// SSL_CTX_sess_accept_good returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_accept_good(const SSL_CTX *ctx); + +// SSL_CTX_sess_hits returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_hits(const SSL_CTX *ctx); + +// SSL_CTX_sess_cb_hits returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_cb_hits(const SSL_CTX *ctx); + +// SSL_CTX_sess_misses returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_misses(const SSL_CTX *ctx); + +// SSL_CTX_sess_timeouts returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_timeouts(const SSL_CTX *ctx); + +// SSL_CTX_sess_cache_full returns zero. +OPENSSL_EXPORT int SSL_CTX_sess_cache_full(const SSL_CTX *ctx); + +// SSL_cutthrough_complete calls |SSL_in_false_start|. +OPENSSL_EXPORT int SSL_cutthrough_complete(const SSL *ssl); + +// SSL_num_renegotiations calls |SSL_total_renegotiations|. +OPENSSL_EXPORT int SSL_num_renegotiations(const SSL *ssl); + +// SSL_CTX_need_tmp_RSA returns zero. +OPENSSL_EXPORT int SSL_CTX_need_tmp_RSA(const SSL_CTX *ctx); + +// SSL_need_tmp_RSA returns zero. +OPENSSL_EXPORT int SSL_need_tmp_RSA(const SSL *ssl); + +// SSL_CTX_set_tmp_rsa returns one. +OPENSSL_EXPORT int SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, const RSA *rsa); + +// SSL_set_tmp_rsa returns one. +OPENSSL_EXPORT int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa); + +// SSL_CTX_get_read_ahead returns zero. +OPENSSL_EXPORT int SSL_CTX_get_read_ahead(const SSL_CTX *ctx); + +// SSL_CTX_set_read_ahead returns one. +OPENSSL_EXPORT int SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes); + +// SSL_get_read_ahead returns zero. +OPENSSL_EXPORT int SSL_get_read_ahead(const SSL *ssl); + +// SSL_set_read_ahead returns one. +OPENSSL_EXPORT int SSL_set_read_ahead(SSL *ssl, int yes); + +// SSL_set_state does nothing. +OPENSSL_EXPORT void SSL_set_state(SSL *ssl, int state); + +// SSL_get_shared_ciphers writes an empty string to |buf| and returns a +// pointer to |buf|, or NULL if |len| is less than or equal to zero. +OPENSSL_EXPORT char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len); + +// SSL_get_shared_sigalgs returns zero. +OPENSSL_EXPORT int SSL_get_shared_sigalgs(SSL *ssl, int idx, int *psign, + int *phash, int *psignandhash, + uint8_t *rsig, uint8_t *rhash); + +// SSL_MODE_HANDSHAKE_CUTTHROUGH is the same as SSL_MODE_ENABLE_FALSE_START. +#define SSL_MODE_HANDSHAKE_CUTTHROUGH SSL_MODE_ENABLE_FALSE_START + +// i2d_SSL_SESSION serializes |in|, as described in |i2d_SAMPLE|. +// +// Use |SSL_SESSION_to_bytes| instead. +OPENSSL_EXPORT int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp); + +// d2i_SSL_SESSION parses a serialized session from the |length| bytes pointed +// to by |*pp|, as described in |d2i_SAMPLE|. +// +// Use |SSL_SESSION_from_bytes| instead. +OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, + long length); + +// i2d_SSL_SESSION_bio serializes |session| and writes the result to |bio|. It +// returns the number of bytes written on success and <= 0 on error. +OPENSSL_EXPORT int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session); + +// d2i_SSL_SESSION_bio reads a serialized |SSL_SESSION| from |bio| and returns a +// newly-allocated |SSL_SESSION| or NULL on error. If |out| is not NULL, it also +// frees |*out| and sets |*out| to the new |SSL_SESSION|. +OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out); + +// ERR_load_SSL_strings does nothing. +OPENSSL_EXPORT void ERR_load_SSL_strings(void); + +// SSL_load_error_strings does nothing. +OPENSSL_EXPORT void SSL_load_error_strings(void); + +// SSL_CTX_set_tlsext_use_srtp calls |SSL_CTX_set_srtp_profiles|. It returns +// zero on success and one on failure. +// +// WARNING: this function is dangerous because it breaks the usual return value +// convention. Use |SSL_CTX_set_srtp_profiles| instead. +OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, + const char *profiles); + +// SSL_set_tlsext_use_srtp calls |SSL_set_srtp_profiles|. It returns zero on +// success and one on failure. +// +// WARNING: this function is dangerous because it breaks the usual return value +// convention. Use |SSL_set_srtp_profiles| instead. +OPENSSL_EXPORT int SSL_set_tlsext_use_srtp(SSL *ssl, const char *profiles); + +// SSL_get_current_compression returns NULL. +OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_compression(SSL *ssl); + +// SSL_get_current_expansion returns NULL. +OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_expansion(SSL *ssl); + +// SSL_get_server_tmp_key returns zero. +OPENSSL_EXPORT int SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key); + +// SSL_CTX_set_tmp_dh returns 1. +OPENSSL_EXPORT int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh); + +// SSL_set_tmp_dh returns 1. +OPENSSL_EXPORT int SSL_set_tmp_dh(SSL *ssl, const DH *dh); + +// SSL_CTX_set_tmp_dh_callback does nothing. +OPENSSL_EXPORT void SSL_CTX_set_tmp_dh_callback( + SSL_CTX *ctx, DH *(*cb)(SSL *ssl, int is_export, int keylength)); + +// SSL_set_tmp_dh_callback does nothing. +OPENSSL_EXPORT void SSL_set_tmp_dh_callback(SSL *ssl, + DH *(*cb)(SSL *ssl, int is_export, + int keylength)); + +// SSL_CTX_set1_sigalgs takes |num_values| ints and interprets them as pairs +// where the first is the nid of a hash function and the second is an +// |EVP_PKEY_*| value. It configures the signature algorithm preferences for +// |ctx| based on them and returns one on success or zero on error. +// +// This API is compatible with OpenSSL. However, BoringSSL-specific code should +// prefer |SSL_CTX_set_signing_algorithm_prefs| because it's clearer and it's +// more convenient to codesearch for specific algorithm values. +OPENSSL_EXPORT int SSL_CTX_set1_sigalgs(SSL_CTX *ctx, const int *values, + size_t num_values); + +// SSL_set1_sigalgs takes |num_values| ints and interprets them as pairs where +// the first is the nid of a hash function and the second is an |EVP_PKEY_*| +// value. It configures the signature algorithm preferences for |ssl| based on +// them and returns one on success or zero on error. +// +// This API is compatible with OpenSSL. However, BoringSSL-specific code should +// prefer |SSL_CTX_set_signing_algorithm_prefs| because it's clearer and it's +// more convenient to codesearch for specific algorithm values. +OPENSSL_EXPORT int SSL_set1_sigalgs(SSL *ssl, const int *values, + size_t num_values); + +// SSL_CTX_set1_sigalgs_list takes a textual specification of a set of signature +// algorithms and configures them on |ctx|. It returns one on success and zero +// on error. See +// https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set1_sigalgs_list.html for +// a description of the text format. Also note that TLS 1.3 names (e.g. +// "rsa_pkcs1_md5_sha1") can also be used (as in OpenSSL, although OpenSSL +// doesn't document that). +// +// This API is compatible with OpenSSL. However, BoringSSL-specific code should +// prefer |SSL_CTX_set_signing_algorithm_prefs| because it's clearer and it's +// more convenient to codesearch for specific algorithm values. +OPENSSL_EXPORT int SSL_CTX_set1_sigalgs_list(SSL_CTX *ctx, const char *str); + +// SSL_set1_sigalgs_list takes a textual specification of a set of signature +// algorithms and configures them on |ssl|. It returns one on success and zero +// on error. See +// https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set1_sigalgs_list.html for +// a description of the text format. Also note that TLS 1.3 names (e.g. +// "rsa_pkcs1_md5_sha1") can also be used (as in OpenSSL, although OpenSSL +// doesn't document that). +// +// This API is compatible with OpenSSL. However, BoringSSL-specific code should +// prefer |SSL_CTX_set_signing_algorithm_prefs| because it's clearer and it's +// more convenient to codesearch for specific algorithm values. +OPENSSL_EXPORT int SSL_set1_sigalgs_list(SSL *ssl, const char *str); + +#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)(arg))) +#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) +#define SSL_SESSION_set_app_data(s, a) \ + (SSL_SESSION_set_ex_data(s, 0, (char *)(a))) +#define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s, 0)) +#define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx, 0)) +#define SSL_CTX_set_app_data(ctx, arg) \ + (SSL_CTX_set_ex_data(ctx, 0, (char *)(arg))) + +#define OpenSSL_add_ssl_algorithms() SSL_library_init() +#define SSLeay_add_ssl_algorithms() SSL_library_init() + +#define SSL_get_cipher(ssl) SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)) +#define SSL_get_cipher_bits(ssl, out_alg_bits) \ + SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), out_alg_bits) +#define SSL_get_cipher_version(ssl) \ + SSL_CIPHER_get_version(SSL_get_current_cipher(ssl)) +#define SSL_get_cipher_name(ssl) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)) +#define SSL_get_time(session) SSL_SESSION_get_time(session) +#define SSL_set_time(session, time) SSL_SESSION_set_time((session), (time)) +#define SSL_get_timeout(session) SSL_SESSION_get_timeout(session) +#define SSL_set_timeout(session, timeout) \ + SSL_SESSION_set_timeout((session), (timeout)) + +struct ssl_comp_st { + int id; + const char *name; + char *method; +}; + +DEFINE_STACK_OF(SSL_COMP) + +// The following flags do nothing and are included only to make it easier to +// compile code with BoringSSL. +#define SSL_MODE_AUTO_RETRY 0 +#define SSL_MODE_RELEASE_BUFFERS 0 +#define SSL_MODE_SEND_CLIENTHELLO_TIME 0 +#define SSL_MODE_SEND_SERVERHELLO_TIME 0 +#define SSL_OP_ALL 0 +#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0 +#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0 +#define SSL_OP_EPHEMERAL_RSA 0 +#define SSL_OP_LEGACY_SERVER_CONNECT 0 +#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0 +#define SSL_OP_MICROSOFT_SESS_ID_BUG 0 +#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0 +#define SSL_OP_NETSCAPE_CA_DN_BUG 0 +#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0 +#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0 +#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0 +#define SSL_OP_NO_COMPRESSION 0 +#define SSL_OP_NO_RENEGOTIATION 0 // ssl_renegotiate_never is the default +#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0 +#define SSL_OP_NO_SSLv2 0 +#define SSL_OP_NO_SSLv3 0 +#define SSL_OP_PKCS1_CHECK_1 0 +#define SSL_OP_PKCS1_CHECK_2 0 +#define SSL_OP_SINGLE_DH_USE 0 +#define SSL_OP_SINGLE_ECDH_USE 0 +#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0 +#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0 +#define SSL_OP_TLS_BLOCK_PADDING_BUG 0 +#define SSL_OP_TLS_D5_BUG 0 +#define SSL_OP_TLS_ROLLBACK_BUG 0 +#define SSL_VERIFY_CLIENT_ONCE 0 + +// SSL_cache_hit calls |SSL_session_reused|. +OPENSSL_EXPORT int SSL_cache_hit(SSL *ssl); + +// SSL_get_default_timeout returns |SSL_DEFAULT_SESSION_TIMEOUT|. +OPENSSL_EXPORT long SSL_get_default_timeout(const SSL *ssl); + +// SSL_get_version returns a string describing the TLS version used by |ssl|. +// For example, "TLSv1.2" or "DTLSv1". +OPENSSL_EXPORT const char *SSL_get_version(const SSL *ssl); + +// SSL_get_all_version_names outputs a list of possible strings +// |SSL_get_version| may return in this version of BoringSSL. It writes at most +// |max_out| entries to |out| and returns the total number it would have +// written, if |max_out| had been large enough. |max_out| may be initially set +// to zero to size the output. +// +// This function is only intended to help initialize tables in callers that want +// possible strings pre-declared. This list would not be suitable to set a list +// of supported features. It is in no particular order, and may contain +// placeholder, experimental, or deprecated values that do not apply to every +// caller. Future versions of BoringSSL may also return strings not in this +// list, so this does not apply if, say, sending strings across services. +OPENSSL_EXPORT size_t SSL_get_all_version_names(const char **out, + size_t max_out); + +// SSL_get_cipher_list returns the name of the |n|th cipher in the output of +// |SSL_get_ciphers| or NULL if out of range. Use |SSL_get_ciphers| instead. +OPENSSL_EXPORT const char *SSL_get_cipher_list(const SSL *ssl, int n); + +// SSL_CTX_set_client_cert_cb sets a callback which is called on the client if +// the server requests a client certificate and none is configured. On success, +// the callback should return one and set |*out_x509| to |*out_pkey| to a leaf +// certificate and private key, respectively, passing ownership. It should +// return zero to send no certificate and -1 to fail or pause the handshake. If +// the handshake is paused, |SSL_get_error| will return +// |SSL_ERROR_WANT_X509_LOOKUP|. +// +// The callback may call |SSL_get0_certificate_types| and +// |SSL_get_client_CA_list| for information on the server's certificate request. +// +// Use |SSL_CTX_set_cert_cb| instead. Configuring intermediate certificates with +// this function is confusing. This callback may not be registered concurrently +// with |SSL_CTX_set_cert_cb| or |SSL_set_cert_cb|. +OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb( + SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey)); + +#define SSL_NOTHING SSL_ERROR_NONE +#define SSL_WRITING SSL_ERROR_WANT_WRITE +#define SSL_READING SSL_ERROR_WANT_READ + +// SSL_want returns one of the above values to determine what the most recent +// operation on |ssl| was blocked on. Use |SSL_get_error| instead. +OPENSSL_EXPORT int SSL_want(const SSL *ssl); + +#define SSL_want_read(ssl) (SSL_want(ssl) == SSL_READING) +#define SSL_want_write(ssl) (SSL_want(ssl) == SSL_WRITING) + + // SSL_get_finished writes up to |count| bytes of the Finished message sent by + // |ssl| to |buf|. It returns the total untruncated length or zero if none has + // been sent yet. At TLS 1.3 and later, it returns zero. + // + // Use |SSL_get_tls_unique| instead. +OPENSSL_EXPORT size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count); + + // SSL_get_peer_finished writes up to |count| bytes of the Finished message + // received from |ssl|'s peer to |buf|. It returns the total untruncated length + // or zero if none has been received yet. At TLS 1.3 and later, it returns + // zero. + // + // Use |SSL_get_tls_unique| instead. +OPENSSL_EXPORT size_t SSL_get_peer_finished(const SSL *ssl, void *buf, + size_t count); + +// SSL_alert_type_string returns "!". Use |SSL_alert_type_string_long| +// instead. +OPENSSL_EXPORT const char *SSL_alert_type_string(int value); + +// SSL_alert_desc_string returns "!!". Use |SSL_alert_desc_string_long| +// instead. +OPENSSL_EXPORT const char *SSL_alert_desc_string(int value); + +// SSL_state_string returns "!!!!!!". Use |SSL_state_string_long| for a more +// intelligible string. +OPENSSL_EXPORT const char *SSL_state_string(const SSL *ssl); + +// SSL_TXT_* expand to strings. +#define SSL_TXT_MEDIUM "MEDIUM" +#define SSL_TXT_HIGH "HIGH" +#define SSL_TXT_FIPS "FIPS" +#define SSL_TXT_kRSA "kRSA" +#define SSL_TXT_kDHE "kDHE" +#define SSL_TXT_kEDH "kEDH" +#define SSL_TXT_kECDHE "kECDHE" +#define SSL_TXT_kEECDH "kEECDH" +#define SSL_TXT_kPSK "kPSK" +#define SSL_TXT_aRSA "aRSA" +#define SSL_TXT_aECDSA "aECDSA" +#define SSL_TXT_aPSK "aPSK" +#define SSL_TXT_DH "DH" +#define SSL_TXT_DHE "DHE" +#define SSL_TXT_EDH "EDH" +#define SSL_TXT_RSA "RSA" +#define SSL_TXT_ECDH "ECDH" +#define SSL_TXT_ECDHE "ECDHE" +#define SSL_TXT_EECDH "EECDH" +#define SSL_TXT_ECDSA "ECDSA" +#define SSL_TXT_PSK "PSK" +#define SSL_TXT_3DES "3DES" +#define SSL_TXT_RC4 "RC4" +#define SSL_TXT_AES128 "AES128" +#define SSL_TXT_AES256 "AES256" +#define SSL_TXT_AES "AES" +#define SSL_TXT_AES_GCM "AESGCM" +#define SSL_TXT_CHACHA20 "CHACHA20" +#define SSL_TXT_MD5 "MD5" +#define SSL_TXT_SHA1 "SHA1" +#define SSL_TXT_SHA "SHA" +#define SSL_TXT_SHA256 "SHA256" +#define SSL_TXT_SHA384 "SHA384" +#define SSL_TXT_SSLV3 "SSLv3" +#define SSL_TXT_TLSV1 "TLSv1" +#define SSL_TXT_TLSV1_1 "TLSv1.1" +#define SSL_TXT_TLSV1_2 "TLSv1.2" +#define SSL_TXT_TLSV1_3 "TLSv1.3" +#define SSL_TXT_ALL "ALL" +#define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT" + +typedef struct ssl_conf_ctx_st SSL_CONF_CTX; + +// SSL_state returns |SSL_ST_INIT| if a handshake is in progress and |SSL_ST_OK| +// otherwise. +// +// Use |SSL_is_init| instead. +OPENSSL_EXPORT int SSL_state(const SSL *ssl); + +#define SSL_get_state(ssl) SSL_state(ssl) + +// SSL_set_shutdown causes |ssl| to behave as if the shutdown bitmask (see +// |SSL_get_shutdown|) were |mode|. This may be used to skip sending or +// receiving close_notify in |SSL_shutdown| by causing the implementation to +// believe the events already happened. +// +// It is an error to use |SSL_set_shutdown| to unset a bit that has already been +// set. Doing so will trigger an |assert| in debug builds and otherwise be +// ignored. +// +// Use |SSL_CTX_set_quiet_shutdown| instead. +OPENSSL_EXPORT void SSL_set_shutdown(SSL *ssl, int mode); + +// SSL_CTX_set_tmp_ecdh calls |SSL_CTX_set1_curves| with a one-element list +// containing |ec_key|'s curve. +OPENSSL_EXPORT int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key); + +// SSL_set_tmp_ecdh calls |SSL_set1_curves| with a one-element list containing +// |ec_key|'s curve. +OPENSSL_EXPORT int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key); + +// SSL_add_dir_cert_subjects_to_stack lists files in directory |dir|. It calls +// |SSL_add_file_cert_subjects_to_stack| on each file and returns one on success +// or zero on error. This function is only available from the libdecrepit +// library. +OPENSSL_EXPORT int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *out, + const char *dir); + +// SSL_CTX_enable_tls_channel_id calls |SSL_CTX_set_tls_channel_id_enabled|. +OPENSSL_EXPORT int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx); + +// SSL_enable_tls_channel_id calls |SSL_set_tls_channel_id_enabled|. +OPENSSL_EXPORT int SSL_enable_tls_channel_id(SSL *ssl); + +// BIO_f_ssl returns a |BIO_METHOD| that can wrap an |SSL*| in a |BIO*|. Note +// that this has quite different behaviour from the version in OpenSSL (notably +// that it doesn't try to auto renegotiate). +// +// IMPORTANT: if you are not curl, don't use this. +OPENSSL_EXPORT const BIO_METHOD *BIO_f_ssl(void); + +// BIO_set_ssl sets |ssl| as the underlying connection for |bio|, which must +// have been created using |BIO_f_ssl|. If |take_owership| is true, |bio| will +// call |SSL_free| on |ssl| when closed. It returns one on success or something +// other than one on error. +OPENSSL_EXPORT long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership); + +// SSL_CTX_set_ecdh_auto returns one. +#define SSL_CTX_set_ecdh_auto(ctx, onoff) 1 + +// SSL_set_ecdh_auto returns one. +#define SSL_set_ecdh_auto(ssl, onoff) 1 + +// SSL_get_session returns a non-owning pointer to |ssl|'s session. For +// historical reasons, which session it returns depends on |ssl|'s state. +// +// Prior to the start of the initial handshake, it returns the session the +// caller set with |SSL_set_session|. After the initial handshake has finished +// and if no additional handshakes are in progress, it returns the currently +// active session. Its behavior is undefined while a handshake is in progress. +// +// If trying to add new sessions to an external session cache, use +// |SSL_CTX_sess_set_new_cb| instead. In particular, using the callback is +// required as of TLS 1.3. For compatibility, this function will return an +// unresumable session which may be cached, but will never be resumed. +// +// If querying properties of the connection, use APIs on the |SSL| object. +OPENSSL_EXPORT SSL_SESSION *SSL_get_session(const SSL *ssl); + +// SSL_get0_session is an alias for |SSL_get_session|. +#define SSL_get0_session SSL_get_session + +// SSL_get1_session acts like |SSL_get_session| but returns a new reference to +// the session. +OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl); + +#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0 +#define OPENSSL_INIT_LOAD_SSL_STRINGS 0 +#define OPENSSL_INIT_SSL_DEFAULT 0 + +// OPENSSL_init_ssl calls |CRYPTO_library_init| and returns one. +OPENSSL_EXPORT int OPENSSL_init_ssl(uint64_t opts, + const OPENSSL_INIT_SETTINGS *settings); + +// The following constants are legacy aliases for RSA-PSS with rsaEncryption +// keys. Use the new names instead. +#define SSL_SIGN_RSA_PSS_SHA256 SSL_SIGN_RSA_PSS_RSAE_SHA256 +#define SSL_SIGN_RSA_PSS_SHA384 SSL_SIGN_RSA_PSS_RSAE_SHA384 +#define SSL_SIGN_RSA_PSS_SHA512 SSL_SIGN_RSA_PSS_RSAE_SHA512 + +// SSL_set_tlsext_status_type configures a client to request OCSP stapling if +// |type| is |TLSEXT_STATUSTYPE_ocsp| and disables it otherwise. It returns one +// on success and zero if handshake configuration has already been shed. +// +// Use |SSL_enable_ocsp_stapling| instead. +OPENSSL_EXPORT int SSL_set_tlsext_status_type(SSL *ssl, int type); + +// SSL_get_tlsext_status_type returns |TLSEXT_STATUSTYPE_ocsp| if the client +// requested OCSP stapling and |TLSEXT_STATUSTYPE_nothing| otherwise. On the +// client, this reflects whether OCSP stapling was enabled via, e.g., +// |SSL_set_tlsext_status_type|. On the server, this is determined during the +// handshake. It may be queried in callbacks set by |SSL_CTX_set_cert_cb|. The +// result is undefined after the handshake completes. +OPENSSL_EXPORT int SSL_get_tlsext_status_type(const SSL *ssl); + +// SSL_set_tlsext_status_ocsp_resp sets the OCSP response. It returns one on +// success and zero on error. On success, |ssl| takes ownership of |resp|, which +// must have been allocated by |OPENSSL_malloc|. +// +// Use |SSL_set_ocsp_response| instead. +OPENSSL_EXPORT int SSL_set_tlsext_status_ocsp_resp(SSL *ssl, uint8_t *resp, + size_t resp_len); + +// SSL_get_tlsext_status_ocsp_resp sets |*out| to point to the OCSP response +// from the server. It returns the length of the response. If there was no +// response, it sets |*out| to NULL and returns zero. +// +// Use |SSL_get0_ocsp_response| instead. +// +// WARNING: the returned data is not guaranteed to be well formed. +OPENSSL_EXPORT size_t SSL_get_tlsext_status_ocsp_resp(const SSL *ssl, + const uint8_t **out); + +// SSL_CTX_set_tlsext_status_cb configures the legacy OpenSSL OCSP callback and +// returns one. Though the type signature is the same, this callback has +// different behavior for client and server connections: +// +// For clients, the callback is called after certificate verification. It should +// return one for success, zero for a bad OCSP response, and a negative number +// for internal error. Instead, handle this as part of certificate verification. +// (Historically, OpenSSL verified certificates just before parsing stapled OCSP +// responses, but BoringSSL fixes this ordering. All server credentials are +// available during verification.) +// +// Do not use this callback as a server. It is provided for compatibility +// purposes only. For servers, it is called to configure server credentials. It +// should return |SSL_TLSEXT_ERR_OK| on success, |SSL_TLSEXT_ERR_NOACK| to +// ignore OCSP requests, or |SSL_TLSEXT_ERR_ALERT_FATAL| on error. It is usually +// used to fetch OCSP responses on demand, which is not ideal. Instead, treat +// OCSP responses like other server credentials, such as certificates or SCT +// lists. Configure, store, and refresh them eagerly. This avoids downtime if +// the CA's OCSP responder is briefly offline. +OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx, + int (*callback)(SSL *ssl, + void *arg)); + +// SSL_CTX_set_tlsext_status_arg sets additional data for +// |SSL_CTX_set_tlsext_status_cb|'s callback and returns one. +OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg); + +// The following symbols are compatibility aliases for reason codes used when +// receiving an alert from the peer. Use the other names instead, which fit the +// naming convention. +// +// TODO(davidben): Fix references to |SSL_R_TLSV1_CERTIFICATE_REQUIRED| and +// remove the compatibility value. The others come from OpenSSL. +#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION \ + SSL_R_TLSV1_ALERT_UNSUPPORTED_EXTENSION +#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE \ + SSL_R_TLSV1_ALERT_CERTIFICATE_UNOBTAINABLE +#define SSL_R_TLSV1_UNRECOGNIZED_NAME SSL_R_TLSV1_ALERT_UNRECOGNIZED_NAME +#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE \ + SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE +#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE \ + SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_HASH_VALUE +#define SSL_R_TLSV1_CERTIFICATE_REQUIRED SSL_R_TLSV1_ALERT_CERTIFICATE_REQUIRED + +// SSL_CIPHER_get_value calls |SSL_CIPHER_get_protocol_id|. +// +// TODO(davidben): |SSL_CIPHER_get_value| was our name for this function, but +// upstream added it as |SSL_CIPHER_get_protocol_id|. Switch callers to the new +// name and remove this one. +OPENSSL_EXPORT uint16_t SSL_CIPHER_get_value(const SSL_CIPHER *cipher); + + +// Compliance policy configurations +// +// A TLS connection has a large number of different parameters. Some are well +// known, like cipher suites, but many are obscure and configuration functions +// for them may not exist. These policy controls allow broad configuration +// goals to be specified so that they can flow down to all the different +// parameters of a TLS connection. + +enum ssl_compliance_policy_t BORINGSSL_ENUM_INT { + // ssl_compliance_policy_none does nothing. However, since setting this + // doesn't undo other policies it's an error to try and set it. + ssl_compliance_policy_none, + + // ssl_policy_fips_202205 configures a TLS connection to use: + // * TLS 1.2 or 1.3 + // * For TLS 1.2, only ECDHE_[RSA|ECDSA]_WITH_AES_*_GCM_SHA*. + // * For TLS 1.3, only AES-GCM + // * P-256 or P-384 for key agreement. + // * For server signatures, only PKCS#1/PSS with SHA256/384/512, or ECDSA + // with P-256 or P-384. + // + // Note: this policy can be configured even if BoringSSL has not been built in + // FIPS mode. Call |FIPS_mode| to check that. + // + // Note: this setting aids with compliance with NIST requirements but does not + // guarantee it. Careful reading of SP 800-52r2 is recommended. + ssl_compliance_policy_fips_202205, + + // ssl_compliance_policy_wpa3_192_202304 configures a TLS connection to use: + // * TLS 1.2 or 1.3. + // * For TLS 1.2, only TLS_ECDHE_[ECDSA|RSA]_WITH_AES_256_GCM_SHA384. + // * For TLS 1.3, only AES-256-GCM. + // * P-384 for key agreement. + // * For handshake signatures, only ECDSA with P-384 and SHA-384, or RSA + // with SHA-384 or SHA-512. + // + // No limitations on the certificate chain nor leaf public key are imposed, + // other than by the supported signature algorithms. But WPA3's "192-bit" + // mode requires at least P-384 or 3072-bit along the chain. The caller must + // enforce this themselves on the verified chain using functions such as + // `X509_STORE_CTX_get0_chain`. + // + // Note that this setting is less secure than the default. The + // implementation risks of using a more obscure primitive like P-384 + // dominate other considerations. + ssl_compliance_policy_wpa3_192_202304, +}; + +// SSL_CTX_set_compliance_policy configures various aspects of |ctx| based on +// the given policy requirements. Subsequently calling other functions that +// configure |ctx| may override |policy|, or may not. This should be the final +// configuration function called in order to have defined behaviour. It's a +// fatal error if |policy| is |ssl_compliance_policy_none|. +OPENSSL_EXPORT int SSL_CTX_set_compliance_policy( + SSL_CTX *ctx, enum ssl_compliance_policy_t policy); + +// SSL_set_compliance_policy acts the same as |SSL_CTX_set_compliance_policy|, +// but only configures a single |SSL*|. +OPENSSL_EXPORT int SSL_set_compliance_policy( + SSL *ssl, enum ssl_compliance_policy_t policy); + + +// Nodejs compatibility section (hidden). +// +// These defines exist for node.js, with the hope that we can eliminate the +// need for them over time. + +#define SSLerr(function, reason) \ + ERR_put_error(ERR_LIB_SSL, 0, reason, __FILE__, __LINE__) + + +// Preprocessor compatibility section (hidden). +// +// Historically, a number of APIs were implemented in OpenSSL as macros and +// constants to 'ctrl' functions. To avoid breaking #ifdefs in consumers, this +// section defines a number of legacy macros. +// +// Although using either the CTRL values or their wrapper macros in #ifdefs is +// still supported, the CTRL values may not be passed to |SSL_ctrl| and +// |SSL_CTX_ctrl|. Call the functions (previously wrapper macros) instead. +// +// See PORTING.md in the BoringSSL source tree for a table of corresponding +// functions. +// https://boringssl.googlesource.com/boringssl/+/master/PORTING.md#Replacements-for-values + +#define DTLS_CTRL_GET_TIMEOUT doesnt_exist +#define DTLS_CTRL_HANDLE_TIMEOUT doesnt_exist +#define SSL_CTRL_CHAIN doesnt_exist +#define SSL_CTRL_CHAIN_CERT doesnt_exist +#define SSL_CTRL_CHANNEL_ID doesnt_exist +#define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS doesnt_exist +#define SSL_CTRL_CLEAR_MODE doesnt_exist +#define SSL_CTRL_CLEAR_OPTIONS doesnt_exist +#define SSL_CTRL_EXTRA_CHAIN_CERT doesnt_exist +#define SSL_CTRL_GET_CHAIN_CERTS doesnt_exist +#define SSL_CTRL_GET_CHANNEL_ID doesnt_exist +#define SSL_CTRL_GET_CLIENT_CERT_TYPES doesnt_exist +#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS doesnt_exist +#define SSL_CTRL_GET_MAX_CERT_LIST doesnt_exist +#define SSL_CTRL_GET_NUM_RENEGOTIATIONS doesnt_exist +#define SSL_CTRL_GET_READ_AHEAD doesnt_exist +#define SSL_CTRL_GET_RI_SUPPORT doesnt_exist +#define SSL_CTRL_GET_SERVER_TMP_KEY doesnt_exist +#define SSL_CTRL_GET_SESSION_REUSED doesnt_exist +#define SSL_CTRL_GET_SESS_CACHE_MODE doesnt_exist +#define SSL_CTRL_GET_SESS_CACHE_SIZE doesnt_exist +#define SSL_CTRL_GET_TLSEXT_TICKET_KEYS doesnt_exist +#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS doesnt_exist +#define SSL_CTRL_MODE doesnt_exist +#define SSL_CTRL_NEED_TMP_RSA doesnt_exist +#define SSL_CTRL_OPTIONS doesnt_exist +#define SSL_CTRL_SESS_NUMBER doesnt_exist +#define SSL_CTRL_SET_CURVES doesnt_exist +#define SSL_CTRL_SET_CURVES_LIST doesnt_exist +#define SSL_CTRL_SET_ECDH_AUTO doesnt_exist +#define SSL_CTRL_SET_MAX_CERT_LIST doesnt_exist +#define SSL_CTRL_SET_MAX_SEND_FRAGMENT doesnt_exist +#define SSL_CTRL_SET_MSG_CALLBACK doesnt_exist +#define SSL_CTRL_SET_MSG_CALLBACK_ARG doesnt_exist +#define SSL_CTRL_SET_MTU doesnt_exist +#define SSL_CTRL_SET_READ_AHEAD doesnt_exist +#define SSL_CTRL_SET_SESS_CACHE_MODE doesnt_exist +#define SSL_CTRL_SET_SESS_CACHE_SIZE doesnt_exist +#define SSL_CTRL_SET_TLSEXT_HOSTNAME doesnt_exist +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG doesnt_exist +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB doesnt_exist +#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS doesnt_exist +#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB doesnt_exist +#define SSL_CTRL_SET_TMP_DH doesnt_exist +#define SSL_CTRL_SET_TMP_DH_CB doesnt_exist +#define SSL_CTRL_SET_TMP_ECDH doesnt_exist +#define SSL_CTRL_SET_TMP_ECDH_CB doesnt_exist +#define SSL_CTRL_SET_TMP_RSA doesnt_exist +#define SSL_CTRL_SET_TMP_RSA_CB doesnt_exist + +// |BORINGSSL_PREFIX| already makes each of these symbols into macros, so there +// is no need to define conflicting macros. +#if !defined(BORINGSSL_PREFIX) + +#define DTLSv1_get_timeout DTLSv1_get_timeout +#define DTLSv1_handle_timeout DTLSv1_handle_timeout +#define SSL_CTX_add0_chain_cert SSL_CTX_add0_chain_cert +#define SSL_CTX_add1_chain_cert SSL_CTX_add1_chain_cert +#define SSL_CTX_add_extra_chain_cert SSL_CTX_add_extra_chain_cert +#define SSL_CTX_clear_extra_chain_certs SSL_CTX_clear_extra_chain_certs +#define SSL_CTX_clear_chain_certs SSL_CTX_clear_chain_certs +#define SSL_CTX_clear_mode SSL_CTX_clear_mode +#define SSL_CTX_clear_options SSL_CTX_clear_options +#define SSL_CTX_get0_chain_certs SSL_CTX_get0_chain_certs +#define SSL_CTX_get_extra_chain_certs SSL_CTX_get_extra_chain_certs +#define SSL_CTX_get_max_cert_list SSL_CTX_get_max_cert_list +#define SSL_CTX_get_mode SSL_CTX_get_mode +#define SSL_CTX_get_options SSL_CTX_get_options +#define SSL_CTX_get_read_ahead SSL_CTX_get_read_ahead +#define SSL_CTX_get_session_cache_mode SSL_CTX_get_session_cache_mode +#define SSL_CTX_get_tlsext_ticket_keys SSL_CTX_get_tlsext_ticket_keys +#define SSL_CTX_need_tmp_RSA SSL_CTX_need_tmp_RSA +#define SSL_CTX_sess_get_cache_size SSL_CTX_sess_get_cache_size +#define SSL_CTX_sess_number SSL_CTX_sess_number +#define SSL_CTX_sess_set_cache_size SSL_CTX_sess_set_cache_size +#define SSL_CTX_set0_chain SSL_CTX_set0_chain +#define SSL_CTX_set1_chain SSL_CTX_set1_chain +#define SSL_CTX_set1_curves SSL_CTX_set1_curves +#define SSL_CTX_set_max_cert_list SSL_CTX_set_max_cert_list +#define SSL_CTX_set_max_send_fragment SSL_CTX_set_max_send_fragment +#define SSL_CTX_set_mode SSL_CTX_set_mode +#define SSL_CTX_set_msg_callback_arg SSL_CTX_set_msg_callback_arg +#define SSL_CTX_set_options SSL_CTX_set_options +#define SSL_CTX_set_read_ahead SSL_CTX_set_read_ahead +#define SSL_CTX_set_session_cache_mode SSL_CTX_set_session_cache_mode +#define SSL_CTX_set_tlsext_servername_arg SSL_CTX_set_tlsext_servername_arg +#define SSL_CTX_set_tlsext_servername_callback \ + SSL_CTX_set_tlsext_servername_callback +#define SSL_CTX_set_tlsext_ticket_key_cb SSL_CTX_set_tlsext_ticket_key_cb +#define SSL_CTX_set_tlsext_ticket_keys SSL_CTX_set_tlsext_ticket_keys +#define SSL_CTX_set_tmp_dh SSL_CTX_set_tmp_dh +#define SSL_CTX_set_tmp_ecdh SSL_CTX_set_tmp_ecdh +#define SSL_CTX_set_tmp_rsa SSL_CTX_set_tmp_rsa +#define SSL_add0_chain_cert SSL_add0_chain_cert +#define SSL_add1_chain_cert SSL_add1_chain_cert +#define SSL_clear_chain_certs SSL_clear_chain_certs +#define SSL_clear_mode SSL_clear_mode +#define SSL_clear_options SSL_clear_options +#define SSL_get0_certificate_types SSL_get0_certificate_types +#define SSL_get0_chain_certs SSL_get0_chain_certs +#define SSL_get_max_cert_list SSL_get_max_cert_list +#define SSL_get_mode SSL_get_mode +#define SSL_get_options SSL_get_options +#define SSL_get_secure_renegotiation_support \ + SSL_get_secure_renegotiation_support +#define SSL_need_tmp_RSA SSL_need_tmp_RSA +#define SSL_num_renegotiations SSL_num_renegotiations +#define SSL_session_reused SSL_session_reused +#define SSL_set0_chain SSL_set0_chain +#define SSL_set1_chain SSL_set1_chain +#define SSL_set1_curves SSL_set1_curves +#define SSL_set_max_cert_list SSL_set_max_cert_list +#define SSL_set_max_send_fragment SSL_set_max_send_fragment +#define SSL_set_mode SSL_set_mode +#define SSL_set_msg_callback_arg SSL_set_msg_callback_arg +#define SSL_set_mtu SSL_set_mtu +#define SSL_set_options SSL_set_options +#define SSL_set_tlsext_host_name SSL_set_tlsext_host_name +#define SSL_set_tmp_dh SSL_set_tmp_dh +#define SSL_set_tmp_ecdh SSL_set_tmp_ecdh +#define SSL_set_tmp_rsa SSL_set_tmp_rsa +#define SSL_total_renegotiations SSL_total_renegotiations + +#endif // !defined(BORINGSSL_PREFIX) + + +#if defined(__cplusplus) +} // extern C + +#if !defined(BORINGSSL_NO_CXX) + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(SSL, SSL_free) +BORINGSSL_MAKE_DELETER(SSL_CTX, SSL_CTX_free) +BORINGSSL_MAKE_UP_REF(SSL_CTX, SSL_CTX_up_ref) +BORINGSSL_MAKE_DELETER(SSL_ECH_KEYS, SSL_ECH_KEYS_free) +BORINGSSL_MAKE_UP_REF(SSL_ECH_KEYS, SSL_ECH_KEYS_up_ref) +BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free) +BORINGSSL_MAKE_UP_REF(SSL_SESSION, SSL_SESSION_up_ref) + + +// *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING *** +// +// Split handshakes. +// +// Split handshakes allows the handshake part of a TLS connection to be +// performed in a different process (or on a different machine) than the data +// exchange. This only applies to servers. +// +// In the first part of a split handshake, an |SSL| (where the |SSL_CTX| has +// been configured with |SSL_CTX_set_handoff_mode|) is used normally. Once the +// ClientHello message has been received, the handshake will stop and +// |SSL_get_error| will indicate |SSL_ERROR_HANDOFF|. At this point (and only +// at this point), |SSL_serialize_handoff| can be called to write the “handoff” +// state of the connection. +// +// Elsewhere, a fresh |SSL| can be used with |SSL_apply_handoff| to continue +// the connection. The connection from the client is fed into this |SSL|, and +// the handshake resumed. When the handshake stops again and |SSL_get_error| +// indicates |SSL_ERROR_HANDBACK|, |SSL_serialize_handback| should be called to +// serialize the state of the handshake again. +// +// Back at the first location, a fresh |SSL| can be used with +// |SSL_apply_handback|. Then the client's connection can be processed mostly +// as normal. +// +// Lastly, when a connection is in the handoff state, whether or not +// |SSL_serialize_handoff| is called, |SSL_decline_handoff| will move it back +// into a normal state where the connection can proceed without impact. +// +// WARNING: Currently only works with TLS 1.0–1.2. +// WARNING: The serialisation formats are not yet stable: version skew may be +// fatal. +// WARNING: The handback data contains sensitive key material and must be +// protected. +// WARNING: Some calls on the final |SSL| will not work. Just as an example, +// calls like |SSL_get0_session_id_context| and |SSL_get_privatekey| won't +// work because the certificate used for handshaking isn't available. +// WARNING: |SSL_apply_handoff| may trigger “msg” callback calls. + +OPENSSL_EXPORT void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on); +OPENSSL_EXPORT void SSL_set_handoff_mode(SSL *SSL, bool on); +OPENSSL_EXPORT bool SSL_serialize_handoff(const SSL *ssl, CBB *out, + SSL_CLIENT_HELLO *out_hello); +OPENSSL_EXPORT bool SSL_decline_handoff(SSL *ssl); +OPENSSL_EXPORT bool SSL_apply_handoff(SSL *ssl, Span handoff); +OPENSSL_EXPORT bool SSL_serialize_handback(const SSL *ssl, CBB *out); +OPENSSL_EXPORT bool SSL_apply_handback(SSL *ssl, Span handback); + +// SSL_get_traffic_secrets sets |*out_read_traffic_secret| and +// |*out_write_traffic_secret| to reference the TLS 1.3 traffic secrets for +// |ssl|. This function is only valid on TLS 1.3 connections that have +// completed the handshake. It returns true on success and false on error. +OPENSSL_EXPORT bool SSL_get_traffic_secrets( + const SSL *ssl, Span *out_read_traffic_secret, + Span *out_write_traffic_secret); + +// SSL_CTX_set_aes_hw_override_for_testing sets |override_value| to +// override checking for aes hardware support for testing. If |override_value| +// is set to true, the library will behave as if aes hardware support is +// present. If it is set to false, the library will behave as if aes hardware +// support is not present. +OPENSSL_EXPORT void SSL_CTX_set_aes_hw_override_for_testing( + SSL_CTX *ctx, bool override_value); + +// SSL_set_aes_hw_override_for_testing acts the same as +// |SSL_CTX_set_aes_override_for_testing| but only configures a single |SSL*|. +OPENSSL_EXPORT void SSL_set_aes_hw_override_for_testing(SSL *ssl, + bool override_value); + +BSSL_NAMESPACE_END + +} // extern C++ + +#endif // !defined(BORINGSSL_NO_CXX) + +#endif + +#define SSL_R_APP_DATA_IN_HANDSHAKE 100 +#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 101 +#define SSL_R_BAD_ALERT 102 +#define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 +#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 104 +#define SSL_R_BAD_DH_P_LENGTH 105 +#define SSL_R_BAD_DIGEST_LENGTH 106 +#define SSL_R_BAD_ECC_CERT 107 +#define SSL_R_BAD_ECPOINT 108 +#define SSL_R_BAD_HANDSHAKE_RECORD 109 +#define SSL_R_BAD_HELLO_REQUEST 110 +#define SSL_R_BAD_LENGTH 111 +#define SSL_R_BAD_PACKET_LENGTH 112 +#define SSL_R_BAD_RSA_ENCRYPT 113 +#define SSL_R_BAD_SIGNATURE 114 +#define SSL_R_BAD_SRTP_MKI_VALUE 115 +#define SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST 116 +#define SSL_R_BAD_SSL_FILETYPE 117 +#define SSL_R_BAD_WRITE_RETRY 118 +#define SSL_R_BIO_NOT_SET 119 +#define SSL_R_BN_LIB 120 +#define SSL_R_BUFFER_TOO_SMALL 121 +#define SSL_R_CA_DN_LENGTH_MISMATCH 122 +#define SSL_R_CA_DN_TOO_LONG 123 +#define SSL_R_CCS_RECEIVED_EARLY 124 +#define SSL_R_CERTIFICATE_VERIFY_FAILED 125 +#define SSL_R_CERT_CB_ERROR 126 +#define SSL_R_CERT_LENGTH_MISMATCH 127 +#define SSL_R_CHANNEL_ID_NOT_P256 128 +#define SSL_R_CHANNEL_ID_SIGNATURE_INVALID 129 +#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 130 +#define SSL_R_CLIENTHELLO_PARSE_FAILED 131 +#define SSL_R_CLIENTHELLO_TLSEXT 132 +#define SSL_R_CONNECTION_REJECTED 133 +#define SSL_R_CONNECTION_TYPE_NOT_SET 134 +#define SSL_R_CUSTOM_EXTENSION_ERROR 135 +#define SSL_R_DATA_LENGTH_TOO_LONG 136 +#define SSL_R_DECODE_ERROR 137 +#define SSL_R_DECRYPTION_FAILED 138 +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 139 +#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 140 +#define SSL_R_DH_P_TOO_LONG 141 +#define SSL_R_DIGEST_CHECK_FAILED 142 +#define SSL_R_DTLS_MESSAGE_TOO_BIG 143 +#define SSL_R_ECC_CERT_NOT_FOR_SIGNING 144 +#define SSL_R_EMS_STATE_INCONSISTENT 145 +#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 146 +#define SSL_R_ERROR_ADDING_EXTENSION 147 +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 148 +#define SSL_R_ERROR_PARSING_EXTENSION 149 +#define SSL_R_EXCESSIVE_MESSAGE_SIZE 150 +#define SSL_R_EXTRA_DATA_IN_MESSAGE 151 +#define SSL_R_FRAGMENT_MISMATCH 152 +#define SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION 153 +#define SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO 154 +#define SSL_R_HTTPS_PROXY_REQUEST 155 +#define SSL_R_HTTP_REQUEST 156 +#define SSL_R_INAPPROPRIATE_FALLBACK 157 +#define SSL_R_INVALID_COMMAND 158 +#define SSL_R_INVALID_MESSAGE 159 +#define SSL_R_INVALID_SSL_SESSION 160 +#define SSL_R_INVALID_TICKET_KEYS_LENGTH 161 +#define SSL_R_LENGTH_MISMATCH 162 +#define SSL_R_MISSING_EXTENSION 164 +#define SSL_R_MISSING_RSA_CERTIFICATE 165 +#define SSL_R_MISSING_TMP_DH_KEY 166 +#define SSL_R_MISSING_TMP_ECDH_KEY 167 +#define SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS 168 +#define SSL_R_MTU_TOO_SMALL 169 +#define SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN 170 +#define SSL_R_NESTED_GROUP 171 +#define SSL_R_NO_CERTIFICATES_RETURNED 172 +#define SSL_R_NO_CERTIFICATE_ASSIGNED 173 +#define SSL_R_NO_CERTIFICATE_SET 174 +#define SSL_R_NO_CIPHERS_AVAILABLE 175 +#define SSL_R_NO_CIPHERS_PASSED 176 +#define SSL_R_NO_CIPHER_MATCH 177 +#define SSL_R_NO_COMPRESSION_SPECIFIED 178 +#define SSL_R_NO_METHOD_SPECIFIED 179 +#define SSL_R_NO_P256_SUPPORT 180 +#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 181 +#define SSL_R_NO_RENEGOTIATION 182 +#define SSL_R_NO_REQUIRED_DIGEST 183 +#define SSL_R_NO_SHARED_CIPHER 184 +#define SSL_R_NULL_SSL_CTX 185 +#define SSL_R_NULL_SSL_METHOD_PASSED 186 +#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 187 +#define SSL_R_OLD_SESSION_VERSION_NOT_RETURNED 188 +#define SSL_R_OUTPUT_ALIASES_INPUT 189 +#define SSL_R_PARSE_TLSEXT 190 +#define SSL_R_PATH_TOO_LONG 191 +#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 192 +#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 193 +#define SSL_R_PROTOCOL_IS_SHUTDOWN 194 +#define SSL_R_PSK_IDENTITY_NOT_FOUND 195 +#define SSL_R_PSK_NO_CLIENT_CB 196 +#define SSL_R_PSK_NO_SERVER_CB 197 +#define SSL_R_READ_TIMEOUT_EXPIRED 198 +#define SSL_R_RECORD_LENGTH_MISMATCH 199 +#define SSL_R_RECORD_TOO_LARGE 200 +#define SSL_R_RENEGOTIATION_ENCODING_ERR 201 +#define SSL_R_RENEGOTIATION_MISMATCH 202 +#define SSL_R_REQUIRED_CIPHER_MISSING 203 +#define SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION 204 +#define SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION 205 +#define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 206 +#define SSL_R_SERVERHELLO_TLSEXT 207 +#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 208 +#define SSL_R_SESSION_MAY_NOT_BE_CREATED 209 +#define SSL_R_SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER 210 +#define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 211 +#define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 212 +#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 213 +#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 214 +#define SSL_R_SSL_HANDSHAKE_FAILURE 215 +#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 216 +#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 217 +#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 218 +#define SSL_R_TOO_MANY_EMPTY_FRAGMENTS 219 +#define SSL_R_TOO_MANY_WARNING_ALERTS 220 +#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 221 +#define SSL_R_UNEXPECTED_EXTENSION 222 +#define SSL_R_UNEXPECTED_MESSAGE 223 +#define SSL_R_UNEXPECTED_OPERATOR_IN_GROUP 224 +#define SSL_R_UNEXPECTED_RECORD 225 +#define SSL_R_UNINITIALIZED 226 +#define SSL_R_UNKNOWN_ALERT_TYPE 227 +#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 228 +#define SSL_R_UNKNOWN_CIPHER_RETURNED 229 +#define SSL_R_UNKNOWN_CIPHER_TYPE 230 +#define SSL_R_UNKNOWN_DIGEST 231 +#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 232 +#define SSL_R_UNKNOWN_PROTOCOL 233 +#define SSL_R_UNKNOWN_SSL_VERSION 234 +#define SSL_R_UNKNOWN_STATE 235 +#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 236 +#define SSL_R_UNSUPPORTED_CIPHER 237 +#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 238 +#define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE 239 +#define SSL_R_UNSUPPORTED_PROTOCOL 240 +#define SSL_R_WRONG_CERTIFICATE_TYPE 241 +#define SSL_R_WRONG_CIPHER_RETURNED 242 +#define SSL_R_WRONG_CURVE 243 +#define SSL_R_WRONG_MESSAGE_TYPE 244 +#define SSL_R_WRONG_SIGNATURE_TYPE 245 +#define SSL_R_WRONG_SSL_VERSION 246 +#define SSL_R_WRONG_VERSION_NUMBER 247 +#define SSL_R_X509_LIB 248 +#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 249 +#define SSL_R_SHUTDOWN_WHILE_IN_INIT 250 +#define SSL_R_INVALID_OUTER_RECORD_TYPE 251 +#define SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY 252 +#define SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS 253 +#define SSL_R_DOWNGRADE_DETECTED 254 +#define SSL_R_EXCESS_HANDSHAKE_DATA 255 +#define SSL_R_INVALID_COMPRESSION_LIST 256 +#define SSL_R_DUPLICATE_EXTENSION 257 +#define SSL_R_MISSING_KEY_SHARE 258 +#define SSL_R_INVALID_ALPN_PROTOCOL 259 +#define SSL_R_TOO_MANY_KEY_UPDATES 260 +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 261 +#define SSL_R_NO_CIPHERS_SPECIFIED 262 +#define SSL_R_RENEGOTIATION_EMS_MISMATCH 263 +#define SSL_R_DUPLICATE_KEY_SHARE 264 +#define SSL_R_NO_GROUPS_SPECIFIED 265 +#define SSL_R_NO_SHARED_GROUP 266 +#define SSL_R_PRE_SHARED_KEY_MUST_BE_LAST 267 +#define SSL_R_OLD_SESSION_PRF_HASH_MISMATCH 268 +#define SSL_R_INVALID_SCT_LIST 269 +#define SSL_R_TOO_MUCH_SKIPPED_EARLY_DATA 270 +#define SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH 271 +#define SSL_R_CANNOT_PARSE_LEAF_CERT 272 +#define SSL_R_SERVER_CERT_CHANGED 273 +#define SSL_R_CERTIFICATE_AND_PRIVATE_KEY_MISMATCH 274 +#define SSL_R_CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD 275 +#define SSL_R_TICKET_ENCRYPTION_FAILED 276 +#define SSL_R_ALPN_MISMATCH_ON_EARLY_DATA 277 +#define SSL_R_WRONG_VERSION_ON_EARLY_DATA 278 +#define SSL_R_UNEXPECTED_EXTENSION_ON_EARLY_DATA 279 +#define SSL_R_NO_SUPPORTED_VERSIONS_ENABLED 280 +#define SSL_R_APPLICATION_DATA_INSTEAD_OF_HANDSHAKE 281 +#define SSL_R_EMPTY_HELLO_RETRY_REQUEST 282 +#define SSL_R_EARLY_DATA_NOT_IN_USE 283 +#define SSL_R_HANDSHAKE_NOT_COMPLETE 284 +#define SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI 285 +#define SSL_R_SERVER_ECHOED_INVALID_SESSION_ID 286 +#define SSL_R_PRIVATE_KEY_OPERATION_FAILED 287 +#define SSL_R_SECOND_SERVERHELLO_VERSION_MISMATCH 288 +#define SSL_R_OCSP_CB_ERROR 289 +#define SSL_R_SSL_SESSION_ID_TOO_LONG 290 +#define SSL_R_APPLICATION_DATA_ON_SHUTDOWN 291 +#define SSL_R_CERT_DECOMPRESSION_FAILED 292 +#define SSL_R_UNCOMPRESSED_CERT_TOO_LARGE 293 +#define SSL_R_UNKNOWN_CERT_COMPRESSION_ALG 294 +#define SSL_R_INVALID_SIGNATURE_ALGORITHM 295 +#define SSL_R_DUPLICATE_SIGNATURE_ALGORITHM 296 +#define SSL_R_TLS13_DOWNGRADE 297 +#define SSL_R_QUIC_INTERNAL_ERROR 298 +#define SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED 299 +#define SSL_R_TOO_MUCH_READ_EARLY_DATA 300 +#define SSL_R_INVALID_DELEGATED_CREDENTIAL 301 +#define SSL_R_KEY_USAGE_BIT_INCORRECT 302 +#define SSL_R_INCONSISTENT_CLIENT_HELLO 303 +#define SSL_R_CIPHER_MISMATCH_ON_EARLY_DATA 304 +#define SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED 305 +#define SSL_R_UNEXPECTED_COMPATIBILITY_MODE 306 +#define SSL_R_NO_APPLICATION_PROTOCOL 307 +#define SSL_R_NEGOTIATED_ALPS_WITHOUT_ALPN 308 +#define SSL_R_ALPS_MISMATCH_ON_EARLY_DATA 309 +#define SSL_R_ECH_SERVER_CONFIG_AND_PRIVATE_KEY_MISMATCH 310 +#define SSL_R_ECH_SERVER_CONFIG_UNSUPPORTED_EXTENSION 311 +#define SSL_R_UNSUPPORTED_ECH_SERVER_CONFIG 312 +#define SSL_R_ECH_SERVER_WOULD_HAVE_NO_RETRY_CONFIGS 313 +#define SSL_R_INVALID_CLIENT_HELLO_INNER 314 +#define SSL_R_INVALID_ALPN_PROTOCOL_LIST 315 +#define SSL_R_COULD_NOT_PARSE_HINTS 316 +#define SSL_R_INVALID_ECH_PUBLIC_NAME 317 +#define SSL_R_INVALID_ECH_CONFIG_LIST 318 +#define SSL_R_ECH_REJECTED 319 +#define SSL_R_INVALID_OUTER_EXTENSION 320 +#define SSL_R_INCONSISTENT_ECH_NEGOTIATION 321 +#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000 +#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 +#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 +#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 +#define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 +#define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 +#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 +#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 +#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 +#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 +#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +#define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086 +#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 +#define SSL_R_TLSV1_ALERT_UNSUPPORTED_EXTENSION 1110 +#define SSL_R_TLSV1_ALERT_CERTIFICATE_UNOBTAINABLE 1111 +#define SSL_R_TLSV1_ALERT_UNRECOGNIZED_NAME 1112 +#define SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 1113 +#define SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_HASH_VALUE 1114 +#define SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY 1115 +#define SSL_R_TLSV1_ALERT_CERTIFICATE_REQUIRED 1116 +#define SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL 1120 +#define SSL_R_TLSV1_ALERT_ECH_REQUIRED 1121 + +#endif // OPENSSL_HEADER_SSL_H diff --git a/lib/boringssl/include/openssl/ssl3.h b/lib/boringssl/include/openssl/ssl3.h new file mode 100644 index 00000000..221adf08 --- /dev/null +++ b/lib/boringssl/include/openssl/ssl3.h @@ -0,0 +1,328 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef OPENSSL_HEADER_SSL3_H +#define OPENSSL_HEADER_SSL3_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +// These are kept to support clients that negotiates higher protocol versions +// using SSLv2 client hello records. +#define SSL2_MT_CLIENT_HELLO 1 +#define SSL2_VERSION 0x0002 + +// Signalling cipher suite value from RFC 5746. +#define SSL3_CK_SCSV 0x030000FF +// Fallback signalling cipher suite value from RFC 7507. +#define SSL3_CK_FALLBACK_SCSV 0x03005600 + +#define SSL3_CK_RSA_NULL_MD5 0x03000001 +#define SSL3_CK_RSA_NULL_SHA 0x03000002 +#define SSL3_CK_RSA_RC4_40_MD5 0x03000003 +#define SSL3_CK_RSA_RC4_128_MD5 0x03000004 +#define SSL3_CK_RSA_RC4_128_SHA 0x03000005 +#define SSL3_CK_RSA_RC2_40_MD5 0x03000006 +#define SSL3_CK_RSA_IDEA_128_SHA 0x03000007 +#define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008 +#define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009 +#define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A + +#define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B +#define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C +#define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D +#define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E +#define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F +#define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010 + +#define SSL3_CK_EDH_DSS_DES_40_CBC_SHA 0x03000011 +#define SSL3_CK_EDH_DSS_DES_64_CBC_SHA 0x03000012 +#define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA 0x03000013 +#define SSL3_CK_EDH_RSA_DES_40_CBC_SHA 0x03000014 +#define SSL3_CK_EDH_RSA_DES_64_CBC_SHA 0x03000015 +#define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA 0x03000016 + +#define SSL3_CK_ADH_RC4_40_MD5 0x03000017 +#define SSL3_CK_ADH_RC4_128_MD5 0x03000018 +#define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019 +#define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A +#define SSL3_CK_ADH_DES_192_CBC_SHA 0x0300001B + +#define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5" +#define SSL3_TXT_RSA_NULL_SHA "NULL-SHA" +#define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5" +#define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5" +#define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA" +#define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5" +#define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-SHA" +#define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA" +#define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA" +#define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA" + +#define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA" +#define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA" +#define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA" +#define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA" +#define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA" +#define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA" + +#define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA" +#define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA" +#define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA" +#define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC-SHA" +#define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA" +#define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA" + +#define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5" +#define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5" +#define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA" +#define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA" +#define SSL3_TXT_ADH_DES_192_CBC_SHA "ADH-DES-CBC3-SHA" + +#define SSL3_SSL_SESSION_ID_LENGTH 32 +#define SSL3_MAX_SSL_SESSION_ID_LENGTH 32 + +#define SSL3_MASTER_SECRET_SIZE 48 +#define SSL3_RANDOM_SIZE 32 +#define SSL3_SESSION_ID_SIZE 32 +#define SSL3_RT_HEADER_LENGTH 5 + +#define SSL3_HM_HEADER_LENGTH 4 + +#ifndef SSL3_ALIGN_PAYLOAD +// Some will argue that this increases memory footprint, but it's not actually +// true. Point is that malloc has to return at least 64-bit aligned pointers, +// meaning that allocating 5 bytes wastes 3 bytes in either case. Suggested +// pre-gaping simply moves these wasted bytes from the end of allocated region +// to its front, but makes data payload aligned, which improves performance. +#define SSL3_ALIGN_PAYLOAD 8 +#else +#if (SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) != 0 +#error "insane SSL3_ALIGN_PAYLOAD" +#undef SSL3_ALIGN_PAYLOAD +#endif +#endif + +// This is the maximum MAC (digest) size used by the SSL library. Currently +// maximum of 20 is used by SHA1, but we reserve for future extension for +// 512-bit hashes. + +#define SSL3_RT_MAX_MD_SIZE 64 + +// Maximum block size used in all ciphersuites. Currently 16 for AES. + +#define SSL_RT_MAX_CIPHER_BLOCK_SIZE 16 + +// Maximum plaintext length: defined by SSL/TLS standards +#define SSL3_RT_MAX_PLAIN_LENGTH 16384 +// Maximum compression overhead: defined by SSL/TLS standards +#define SSL3_RT_MAX_COMPRESSED_OVERHEAD 1024 + +// The standards give a maximum encryption overhead of 1024 bytes. In practice +// the value is lower than this. The overhead is the maximum number of padding +// bytes (256) plus the mac size. +// +// TODO(davidben): This derivation doesn't take AEADs into account, or TLS 1.1 +// explicit nonces. It happens to work because |SSL3_RT_MAX_MD_SIZE| is larger +// than necessary and no true AEAD has variable overhead in TLS 1.2. +#define SSL3_RT_MAX_ENCRYPTED_OVERHEAD (256 + SSL3_RT_MAX_MD_SIZE) + +// SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD is the maximum overhead in encrypting a +// record. This does not include the record header. Some ciphers use explicit +// nonces, so it includes both the AEAD overhead as well as the nonce. +#define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + (EVP_AEAD_MAX_OVERHEAD + EVP_AEAD_MAX_NONCE_LENGTH) + +// SSL3_RT_MAX_COMPRESSED_LENGTH is an alias for +// |SSL3_RT_MAX_PLAIN_LENGTH|. Compression is gone, so don't include the +// compression overhead. +#define SSL3_RT_MAX_COMPRESSED_LENGTH SSL3_RT_MAX_PLAIN_LENGTH + +#define SSL3_RT_MAX_ENCRYPTED_LENGTH \ + (SSL3_RT_MAX_ENCRYPTED_OVERHEAD + SSL3_RT_MAX_COMPRESSED_LENGTH) +#define SSL3_RT_MAX_PACKET_SIZE \ + (SSL3_RT_MAX_ENCRYPTED_LENGTH + SSL3_RT_HEADER_LENGTH) + +#define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54" +#define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52" + +#define SSL3_RT_CHANGE_CIPHER_SPEC 20 +#define SSL3_RT_ALERT 21 +#define SSL3_RT_HANDSHAKE 22 +#define SSL3_RT_APPLICATION_DATA 23 + +// Pseudo content type for SSL/TLS header info +#define SSL3_RT_HEADER 0x100 +#define SSL3_RT_CLIENT_HELLO_INNER 0x101 + +#define SSL3_AL_WARNING 1 +#define SSL3_AL_FATAL 2 + +#define SSL3_AD_CLOSE_NOTIFY 0 +#define SSL3_AD_UNEXPECTED_MESSAGE 10 // fatal +#define SSL3_AD_BAD_RECORD_MAC 20 // fatal +#define SSL3_AD_DECOMPRESSION_FAILURE 30 // fatal +#define SSL3_AD_HANDSHAKE_FAILURE 40 // fatal +#define SSL3_AD_NO_CERTIFICATE 41 +#define SSL3_AD_BAD_CERTIFICATE 42 +#define SSL3_AD_UNSUPPORTED_CERTIFICATE 43 +#define SSL3_AD_CERTIFICATE_REVOKED 44 +#define SSL3_AD_CERTIFICATE_EXPIRED 45 +#define SSL3_AD_CERTIFICATE_UNKNOWN 46 +#define SSL3_AD_ILLEGAL_PARAMETER 47 // fatal +#define SSL3_AD_INAPPROPRIATE_FALLBACK 86 // fatal + +#define SSL3_CT_RSA_SIGN 1 + +#define SSL3_MT_HELLO_REQUEST 0 +#define SSL3_MT_CLIENT_HELLO 1 +#define SSL3_MT_SERVER_HELLO 2 +#define SSL3_MT_NEW_SESSION_TICKET 4 +#define SSL3_MT_END_OF_EARLY_DATA 5 +#define SSL3_MT_ENCRYPTED_EXTENSIONS 8 +#define SSL3_MT_CERTIFICATE 11 +#define SSL3_MT_SERVER_KEY_EXCHANGE 12 +#define SSL3_MT_CERTIFICATE_REQUEST 13 +#define SSL3_MT_SERVER_HELLO_DONE 14 +#define SSL3_MT_CERTIFICATE_VERIFY 15 +#define SSL3_MT_CLIENT_KEY_EXCHANGE 16 +#define SSL3_MT_FINISHED 20 +#define SSL3_MT_CERTIFICATE_STATUS 22 +#define SSL3_MT_SUPPLEMENTAL_DATA 23 +#define SSL3_MT_KEY_UPDATE 24 +#define SSL3_MT_COMPRESSED_CERTIFICATE 25 +#define SSL3_MT_NEXT_PROTO 67 +#define SSL3_MT_CHANNEL_ID 203 +#define SSL3_MT_MESSAGE_HASH 254 +#define DTLS1_MT_HELLO_VERIFY_REQUEST 3 + +// The following are legacy aliases for consumers which use +// |SSL_CTX_set_msg_callback|. +#define SSL3_MT_SERVER_DONE SSL3_MT_SERVER_HELLO_DONE +#define SSL3_MT_NEWSESSION_TICKET SSL3_MT_NEW_SESSION_TICKET + + +#define SSL3_MT_CCS 1 + + +#ifdef __cplusplus +} // extern C +#endif + +#endif // OPENSSL_HEADER_SSL3_H diff --git a/lib/boringssl/include/openssl/stack.h b/lib/boringssl/include/openssl/stack.h new file mode 100644 index 00000000..59b1c5ef --- /dev/null +++ b/lib/boringssl/include/openssl/stack.h @@ -0,0 +1,636 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_STACK_H +#define OPENSSL_HEADER_STACK_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// A stack, in OpenSSL, is an array of pointers. They are the most commonly +// used collection object. +// +// This file defines macros for type-safe use of the stack functions. A stack +// type is named like |STACK_OF(FOO)| and is accessed with functions named +// like |sk_FOO_*|. Note the stack will typically contain /pointers/ to |FOO|. +// +// The |DECLARE_STACK_OF| macro makes |STACK_OF(FOO)| available, and +// |DEFINE_STACK_OF| makes the corresponding functions available. + + +// Defining stacks. + +// STACK_OF expands to the stack type for |type|. +#define STACK_OF(type) struct stack_st_##type + +// DECLARE_STACK_OF declares the |STACK_OF(type)| type. It does not make the +// corresponding |sk_type_*| functions available. This macro should be used in +// files which only need the type. +#define DECLARE_STACK_OF(type) STACK_OF(type); + +// DEFINE_NAMED_STACK_OF defines |STACK_OF(name)| to be a stack whose elements +// are |type| *. This macro makes the |sk_name_*| functions available. +// +// It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. +#define DEFINE_NAMED_STACK_OF(name, type) \ + BORINGSSL_DEFINE_STACK_OF_IMPL(name, type *, const type *) \ + BORINGSSL_DEFINE_STACK_TRAITS(name, type, false) + +// DEFINE_STACK_OF defines |STACK_OF(type)| to be a stack whose elements are +// |type| *. This macro makes the |sk_type_*| functions available. +// +// It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. +#define DEFINE_STACK_OF(type) DEFINE_NAMED_STACK_OF(type, type) + +// DEFINE_CONST_STACK_OF defines |STACK_OF(type)| to be a stack whose elements +// are const |type| *. This macro makes the |sk_type_*| functions available. +// +// It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. +#define DEFINE_CONST_STACK_OF(type) \ + BORINGSSL_DEFINE_STACK_OF_IMPL(type, const type *, const type *) \ + BORINGSSL_DEFINE_STACK_TRAITS(type, const type, true) + + +// Using stacks. +// +// After the |DEFINE_STACK_OF| macro is used, the following functions are +// available. + +#if 0 // Sample + +// sk_SAMPLE_free_func is a callback to free an element in a stack. +typedef void (*sk_SAMPLE_free_func)(SAMPLE *); + +// sk_SAMPLE_copy_func is a callback to copy an element in a stack. It should +// return the copy or NULL on error. +typedef SAMPLE *(*sk_SAMPLE_copy_func)(const SAMPLE *); + +// sk_SAMPLE_cmp_func is a callback to compare |*a| to |*b|. It should return a +// value < 0, 0, or > 0 if |*a| is less than, equal to, or greater than |*b|, +// respectively. Note the extra indirection - the function is given a pointer +// to a pointer to the element. This is the |qsort|/|bsearch| comparison +// function applied to an array of |SAMPLE*|. +typedef int (*sk_SAMPLE_cmp_func)(const SAMPLE *const *a, + const SAMPLE *const *b); + +// sk_SAMPLE_new creates a new, empty stack with the given comparison function, +// which may be NULL. It returns the new stack or NULL on allocation failure. +STACK_OF(SAMPLE) *sk_SAMPLE_new(sk_SAMPLE_cmp_func comp); + +// sk_SAMPLE_new_null creates a new, empty stack. It returns the new stack or +// NULL on allocation failure. +STACK_OF(SAMPLE) *sk_SAMPLE_new_null(void); + +// sk_SAMPLE_num returns the number of elements in |sk|. +size_t sk_SAMPLE_num(const STACK_OF(SAMPLE) *sk); + +// sk_SAMPLE_zero resets |sk| to the empty state but does nothing to free the +// individual elements themselves. +void sk_SAMPLE_zero(STACK_OF(SAMPLE) *sk); + +// sk_SAMPLE_value returns the |i|th pointer in |sk|, or NULL if |i| is out of +// range. +SAMPLE *sk_SAMPLE_value(const STACK_OF(SAMPLE) *sk, size_t i); + +// sk_SAMPLE_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i| +// is out of range, it returns NULL. +SAMPLE *sk_SAMPLE_set(STACK_OF(SAMPLE) *sk, size_t i, SAMPLE *p); + +// sk_SAMPLE_free frees |sk|, but does nothing to free the individual elements. +// Use |sk_SAMPLE_pop_free| to also free the elements. +void sk_SAMPLE_free(STACK_OF(SAMPLE) *sk); + +// sk_SAMPLE_pop_free calls |free_func| on each element in |sk| and then +// frees the stack itself. +void sk_SAMPLE_pop_free(STACK_OF(SAMPLE) *sk, sk_SAMPLE_free_func free_func); + +// sk_SAMPLE_insert inserts |p| into the stack at index |where|, moving existing +// elements if needed. It returns the length of the new stack, or zero on +// error. +size_t sk_SAMPLE_insert(STACK_OF(SAMPLE) *sk, SAMPLE *p, size_t where); + +// sk_SAMPLE_delete removes the pointer at index |where|, moving other elements +// down if needed. It returns the removed pointer, or NULL if |where| is out of +// range. +SAMPLE *sk_SAMPLE_delete(STACK_OF(SAMPLE) *sk, size_t where); + +// sk_SAMPLE_delete_ptr removes, at most, one instance of |p| from |sk| based on +// pointer equality. If an instance of |p| is found then |p| is returned, +// otherwise it returns NULL. +SAMPLE *sk_SAMPLE_delete_ptr(STACK_OF(SAMPLE) *sk, const SAMPLE *p); + +// sk_SAMPLE_delete_if_func is the callback function for |sk_SAMPLE_delete_if|. +// It should return one to remove |p| and zero to keep it. +typedef int (*sk_SAMPLE_delete_if_func)(SAMPLE *p, void *data); + +// sk_SAMPLE_delete_if calls |func| with each element of |sk| and removes the +// entries where |func| returned one. This function does not free or return +// removed pointers so, if |sk| owns its contents, |func| should release the +// pointers prior to returning one. +void sk_SAMPLE_delete_if(STACK_OF(SAMPLE) *sk, sk_SAMPLE_delete_if_func func, + void *data); + +// sk_SAMPLE_find find the first value in |sk| equal to |p|. |sk|'s comparison +// function determines equality, or pointer equality if |sk| has no comparison +// function. +// +// If the stack is sorted (see |sk_SAMPLE_sort|), this function uses a binary +// search. Otherwise it performs a linear search. If it finds a matching +// element, it writes the index to |*out_index| (if |out_index| is not NULL) and +// returns one. Otherwise, it returns zero. +// +// Note this differs from OpenSSL. The type signature is slightly different, and +// OpenSSL's version will implicitly sort |sk| if it has a comparison function +// defined. +int sk_SAMPLE_find(const STACK_OF(SAMPLE) *sk, size_t *out_index, + const SAMPLE *p); + +// sk_SAMPLE_shift removes and returns the first element in |sk|, or NULL if +// |sk| is empty. +SAMPLE *sk_SAMPLE_shift(STACK_OF(SAMPLE) *sk); + +// sk_SAMPLE_push appends |p| to |sk| and returns the length of the new stack, +// or 0 on allocation failure. +size_t sk_SAMPLE_push(STACK_OF(SAMPLE) *sk, SAMPLE *p); + +// sk_SAMPLE_pop removes and returns the last element of |sk|, or NULL if |sk| +// is empty. +SAMPLE *sk_SAMPLE_pop(STACK_OF(SAMPLE) *sk); + +// sk_SAMPLE_dup performs a shallow copy of a stack and returns the new stack, +// or NULL on error. Use |sk_SAMPLE_deep_copy| to also copy the elements. +STACK_OF(SAMPLE) *sk_SAMPLE_dup(const STACK_OF(SAMPLE) *sk); + +// sk_SAMPLE_sort sorts the elements of |sk| into ascending order based on the +// comparison function. The stack maintains a "sorted" flag and sorting an +// already sorted stack is a no-op. +void sk_SAMPLE_sort(STACK_OF(SAMPLE) *sk); + +// sk_SAMPLE_is_sorted returns one if |sk| is known to be sorted and zero +// otherwise. +int sk_SAMPLE_is_sorted(const STACK_OF(SAMPLE) *sk); + +// sk_SAMPLE_set_cmp_func sets the comparison function to be used by |sk| and +// returns the previous one. +sk_SAMPLE_cmp_func sk_SAMPLE_set_cmp_func(STACK_OF(SAMPLE) *sk, + sk_SAMPLE_cmp_func comp); + +// sk_SAMPLE_deep_copy performs a copy of |sk| and of each of the non-NULL +// elements in |sk| by using |copy_func|. If an error occurs, it calls +// |free_func| to free any copies already made and returns NULL. +STACK_OF(SAMPLE) *sk_SAMPLE_deep_copy(const STACK_OF(SAMPLE) *sk, + sk_SAMPLE_copy_func copy_func, + sk_SAMPLE_free_func free_func); + +#endif // Sample + + +// Private functions. +// +// TODO(https://crbug.com/boringssl/499): Rename to |OPENSSL_sk_foo|, after +// external code that calls them is fixed. + +// OPENSSL_sk_free_func is a function that frees an element in a stack. Note its +// actual type is void (*)(T *) for some T. Low-level |sk_*| functions will be +// passed a type-specific wrapper to call it correctly. +typedef void (*OPENSSL_sk_free_func)(void *ptr); + +// OPENSSL_sk_copy_func is a function that copies an element in a stack. Note +// its actual type is T *(*)(const T *) for some T. Low-level |sk_*| functions +// will be passed a type-specific wrapper to call it correctly. +typedef void *(*OPENSSL_sk_copy_func)(const void *ptr); + +// OPENSSL_sk_cmp_func is a comparison function that returns a value < 0, 0 or > +// 0 if |*a| is less than, equal to or greater than |*b|, respectively. Note +// the extra indirection - the function is given a pointer to a pointer to the +// element. This differs from the usual qsort/bsearch comparison function. +// +// Note its actual type is |int (*)(const T *const *a, const T *const *b)|. +// Low-level |sk_*| functions will be passed a type-specific wrapper to call it +// correctly. +typedef int (*OPENSSL_sk_cmp_func)(const void *const *a, const void *const *b); + +// OPENSSL_sk_delete_if_func is the generic version of +// |sk_SAMPLE_delete_if_func|. +typedef int (*OPENSSL_sk_delete_if_func)(void *obj, void *data); + +// The following function types call the above type-erased signatures with the +// true types. +typedef void (*OPENSSL_sk_call_free_func)(OPENSSL_sk_free_func, void *); +typedef void *(*OPENSSL_sk_call_copy_func)(OPENSSL_sk_copy_func, const void *); +typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func, + const void *const *, + const void *const *); +typedef int (*OPENSSL_sk_call_delete_if_func)(OPENSSL_sk_delete_if_func, void *, + void *); + +// stack_st contains an array of pointers. It is not designed to be used +// directly, rather the wrapper macros should be used. +typedef struct stack_st { + // num contains the number of valid pointers in |data|. + size_t num; + void **data; + // sorted is non-zero if the values pointed to by |data| are in ascending + // order, based on |comp|. + int sorted; + // num_alloc contains the number of pointers allocated in the buffer pointed + // to by |data|, which may be larger than |num|. + size_t num_alloc; + // comp is an optional comparison function. + OPENSSL_sk_cmp_func comp; +} _STACK; + +// The following are raw stack functions. They implement the corresponding typed +// |sk_SAMPLE_*| functions generated by |DEFINE_STACK_OF|. Callers shouldn't be +// using them. Rather, callers should use the typed functions. +OPENSSL_EXPORT _STACK *sk_new(OPENSSL_sk_cmp_func comp); +OPENSSL_EXPORT _STACK *sk_new_null(void); +OPENSSL_EXPORT size_t sk_num(const _STACK *sk); +OPENSSL_EXPORT void sk_zero(_STACK *sk); +OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i); +OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p); +OPENSSL_EXPORT void sk_free(_STACK *sk); +OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk, + OPENSSL_sk_call_free_func call_free_func, + OPENSSL_sk_free_func free_func); +OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where); +OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where); +OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p); +OPENSSL_EXPORT void sk_delete_if(_STACK *sk, + OPENSSL_sk_call_delete_if_func call_func, + OPENSSL_sk_delete_if_func func, void *data); +OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p, + OPENSSL_sk_call_cmp_func call_cmp_func); +OPENSSL_EXPORT void *sk_shift(_STACK *sk); +OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p); +OPENSSL_EXPORT void *sk_pop(_STACK *sk); +OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk); +OPENSSL_EXPORT void sk_sort(_STACK *sk, OPENSSL_sk_call_cmp_func call_cmp_func); +OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk); +OPENSSL_EXPORT OPENSSL_sk_cmp_func sk_set_cmp_func(_STACK *sk, + OPENSSL_sk_cmp_func comp); +OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk, + OPENSSL_sk_call_copy_func call_copy_func, + OPENSSL_sk_copy_func copy_func, + OPENSSL_sk_call_free_func call_free_func, + OPENSSL_sk_free_func free_func); + +// sk_pop_free behaves like |sk_pop_free_ex| but performs an invalid function +// pointer cast. It exists because some existing callers called |sk_pop_free| +// directly. +// +// TODO(davidben): Migrate callers to bssl::UniquePtr and remove this. +OPENSSL_EXPORT void sk_pop_free(_STACK *sk, OPENSSL_sk_free_func free_func); + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { +BSSL_NAMESPACE_BEGIN +namespace internal { +template +struct StackTraits {}; +} +BSSL_NAMESPACE_END +} + +#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \ + extern "C++" { \ + BSSL_NAMESPACE_BEGIN \ + namespace internal { \ + template <> \ + struct StackTraits { \ + static constexpr bool kIsStack = true; \ + using Type = type; \ + static constexpr bool kIsConst = is_const; \ + }; \ + } \ + BSSL_NAMESPACE_END \ + } + +#else +#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) +#endif + +#define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype) \ + /* We disable MSVC C4191 in this macro, which warns when pointers are cast \ + * to the wrong type. While the cast itself is valid, it is often a bug \ + * because calling it through the cast is UB. However, we never actually \ + * call functions as |OPENSSL_sk_cmp_func|. The type is just a type-erased \ + * function pointer. (C does not guarantee function pointers fit in \ + * |void*|, and GCC will warn on this.) Thus we just disable the false \ + * positive warning. */ \ + OPENSSL_MSVC_PRAGMA(warning(push)) \ + OPENSSL_MSVC_PRAGMA(warning(disable : 4191)) \ + \ + DECLARE_STACK_OF(name) \ + \ + typedef void (*sk_##name##_free_func)(ptrtype); \ + typedef ptrtype (*sk_##name##_copy_func)(constptrtype); \ + typedef int (*sk_##name##_cmp_func)(constptrtype const *, \ + constptrtype const *); \ + typedef int (*sk_##name##_delete_if_func)(ptrtype, void *); \ + \ + OPENSSL_INLINE void sk_##name##_call_free_func( \ + OPENSSL_sk_free_func free_func, void *ptr) { \ + ((sk_##name##_free_func)free_func)((ptrtype)ptr); \ + } \ + \ + OPENSSL_INLINE void *sk_##name##_call_copy_func( \ + OPENSSL_sk_copy_func copy_func, const void *ptr) { \ + return (void *)((sk_##name##_copy_func)copy_func)((constptrtype)ptr); \ + } \ + \ + OPENSSL_INLINE int sk_##name##_call_cmp_func(OPENSSL_sk_cmp_func cmp_func, \ + const void *const *a, \ + const void *const *b) { \ + /* The data is actually stored as |void*| pointers, so read the pointer \ + * as |void*| and then pass the corrected type into the caller-supplied \ + * function, which expects |constptrtype*|. */ \ + constptrtype a_ptr = (constptrtype)*a; \ + constptrtype b_ptr = (constptrtype)*b; \ + return ((sk_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \ + } \ + \ + OPENSSL_INLINE int sk_##name##_call_delete_if_func( \ + OPENSSL_sk_delete_if_func func, void *obj, void *data) { \ + return ((sk_##name##_delete_if_func)func)((ptrtype)obj, data); \ + } \ + \ + OPENSSL_INLINE STACK_OF(name) *sk_##name##_new(sk_##name##_cmp_func comp) { \ + return (STACK_OF(name) *)sk_new((OPENSSL_sk_cmp_func)comp); \ + } \ + \ + OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) { \ + return (STACK_OF(name) *)sk_new_null(); \ + } \ + \ + OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) { \ + return sk_num((const _STACK *)sk); \ + } \ + \ + OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) { \ + sk_zero((_STACK *)sk); \ + } \ + \ + OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk, \ + size_t i) { \ + return (ptrtype)sk_value((const _STACK *)sk, i); \ + } \ + \ + OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i, \ + ptrtype p) { \ + return (ptrtype)sk_set((_STACK *)sk, i, (void *)p); \ + } \ + \ + OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) *sk) { \ + sk_free((_STACK *)sk); \ + } \ + \ + OPENSSL_INLINE void sk_##name##_pop_free(STACK_OF(name) *sk, \ + sk_##name##_free_func free_func) { \ + sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func, \ + (OPENSSL_sk_free_func)free_func); \ + } \ + \ + OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p, \ + size_t where) { \ + return sk_insert((_STACK *)sk, (void *)p, where); \ + } \ + \ + OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk, \ + size_t where) { \ + return (ptrtype)sk_delete((_STACK *)sk, where); \ + } \ + \ + OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk, \ + constptrtype p) { \ + return (ptrtype)sk_delete_ptr((_STACK *)sk, (const void *)p); \ + } \ + \ + OPENSSL_INLINE void sk_##name##_delete_if( \ + STACK_OF(name) *sk, sk_##name##_delete_if_func func, void *data) { \ + sk_delete_if((_STACK *)sk, sk_##name##_call_delete_if_func, \ + (OPENSSL_sk_delete_if_func)func, data); \ + } \ + \ + OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk, \ + size_t *out_index, constptrtype p) { \ + return sk_find((const _STACK *)sk, out_index, (const void *)p, \ + sk_##name##_call_cmp_func); \ + } \ + \ + OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \ + return (ptrtype)sk_shift((_STACK *)sk); \ + } \ + \ + OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) { \ + return sk_push((_STACK *)sk, (void *)p); \ + } \ + \ + OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) { \ + return (ptrtype)sk_pop((_STACK *)sk); \ + } \ + \ + OPENSSL_INLINE STACK_OF(name) *sk_##name##_dup(const STACK_OF(name) *sk) { \ + return (STACK_OF(name) *)sk_dup((const _STACK *)sk); \ + } \ + \ + OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) { \ + sk_sort((_STACK *)sk, sk_##name##_call_cmp_func); \ + } \ + \ + OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) { \ + return sk_is_sorted((const _STACK *)sk); \ + } \ + \ + OPENSSL_INLINE sk_##name##_cmp_func sk_##name##_set_cmp_func( \ + STACK_OF(name) *sk, sk_##name##_cmp_func comp) { \ + return (sk_##name##_cmp_func)sk_set_cmp_func((_STACK *)sk, \ + (OPENSSL_sk_cmp_func)comp); \ + } \ + \ + OPENSSL_INLINE STACK_OF(name) *sk_##name##_deep_copy( \ + const STACK_OF(name) *sk, sk_##name##_copy_func copy_func, \ + sk_##name##_free_func free_func) { \ + return (STACK_OF(name) *)sk_deep_copy( \ + (const _STACK *)sk, sk_##name##_call_copy_func, \ + (OPENSSL_sk_copy_func)copy_func, sk_##name##_call_free_func, \ + (OPENSSL_sk_free_func)free_func); \ + } \ + \ + OPENSSL_MSVC_PRAGMA(warning(pop)) + + +// Built-in stacks. + +typedef char *OPENSSL_STRING; + +DEFINE_STACK_OF(void) +DEFINE_NAMED_STACK_OF(OPENSSL_STRING, char) + + +#if defined(__cplusplus) +} // extern C +#endif + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +#include + +BSSL_NAMESPACE_BEGIN + +namespace internal { + +// Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|. +template +struct DeleterImpl::kIsConst>> { + static void Free(Stack *sk) { sk_free(reinterpret_cast<_STACK *>(sk)); } +}; + +// Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the +// corresponding type's deleter. +template +struct DeleterImpl::kIsConst>> { + static void Free(Stack *sk) { + // sk_FOO_pop_free is defined by macros and bound by name, so we cannot + // access it from C++ here. + using Type = typename StackTraits::Type; + sk_pop_free_ex(reinterpret_cast<_STACK *>(sk), + [](OPENSSL_sk_free_func /* unused */, void *ptr) { + DeleterImpl::Free(reinterpret_cast(ptr)); + }, + nullptr); + } +}; + +template +class StackIteratorImpl { + public: + using Type = typename StackTraits::Type; + // Iterators must be default-constructable. + StackIteratorImpl() : sk_(nullptr), idx_(0) {} + StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {} + + bool operator==(StackIteratorImpl other) const { + return sk_ == other.sk_ && idx_ == other.idx_; + } + bool operator!=(StackIteratorImpl other) const { + return !(*this == other); + } + + Type *operator*() const { + return reinterpret_cast( + sk_value(reinterpret_cast(sk_), idx_)); + } + + StackIteratorImpl &operator++(/* prefix */) { + idx_++; + return *this; + } + + StackIteratorImpl operator++(int /* postfix */) { + StackIteratorImpl copy(*this); + ++(*this); + return copy; + } + + private: + const Stack *sk_; + size_t idx_; +}; + +template +using StackIterator = + std::enable_if_t::kIsStack, StackIteratorImpl>; + +} // namespace internal + +// PushToStack pushes |elem| to |sk|. It returns true on success and false on +// allocation failure. +template +inline std::enable_if_t::kIsConst, bool> +PushToStack(Stack *sk, + UniquePtr::Type> elem) { + if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) { + return false; + } + // sk_push takes ownership on success. + elem.release(); + return true; +} + +BSSL_NAMESPACE_END + +// Define begin() and end() for stack types so C++ range for loops work. +template +inline bssl::internal::StackIterator begin(const Stack *sk) { + return bssl::internal::StackIterator(sk, 0); +} + +template +inline bssl::internal::StackIterator end(const Stack *sk) { + return bssl::internal::StackIterator( + sk, sk_num(reinterpret_cast(sk))); +} + +} // extern C++ +#endif + +#endif // OPENSSL_HEADER_STACK_H diff --git a/lib/boringssl/include/openssl/thread.h b/lib/boringssl/include/openssl/thread.h new file mode 100644 index 00000000..c6e357e1 --- /dev/null +++ b/lib/boringssl/include/openssl/thread.h @@ -0,0 +1,190 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_THREAD_H +#define OPENSSL_HEADER_THREAD_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if !defined(OPENSSL_THREADS) +typedef struct crypto_mutex_st { + char padding; // Empty structs have different sizes in C and C++. +} CRYPTO_MUTEX; +#elif defined(OPENSSL_WINDOWS) +// CRYPTO_MUTEX can appear in public header files so we really don't want to +// pull in windows.h. It's statically asserted that this structure is large +// enough to contain a Windows SRWLOCK by thread_win.c. +typedef union crypto_mutex_st { + void *handle; +} CRYPTO_MUTEX; +#elif !defined(__GLIBC__) +typedef pthread_rwlock_t CRYPTO_MUTEX; +#else +// On glibc, |pthread_rwlock_t| is hidden under feature flags, and we can't +// ensure that we'll be able to get it from a public header. It's statically +// asserted that this structure is large enough to contain a |pthread_rwlock_t| +// by thread_pthread.c. +typedef union crypto_mutex_st { + double alignment; + uint8_t padding[3*sizeof(int) + 5*sizeof(unsigned) + 16 + 8]; +} CRYPTO_MUTEX; +#endif + +// CRYPTO_refcount_t is the type of a reference count. +// +// Since some platforms use C11 atomics to access this, it should have the +// _Atomic qualifier. However, this header is included by C++ programs as well +// as C code that might not set -std=c11. So, in practice, it's not possible to +// do that. Instead we statically assert that the size and native alignment of +// a plain uint32_t and an _Atomic uint32_t are equal in refcount_c11.c. +typedef uint32_t CRYPTO_refcount_t; + + +// Deprecated functions. +// +// Historically, OpenSSL required callers to provide locking callbacks. +// BoringSSL is thread-safe by default, but some old code calls these functions +// and so no-op implementations are provided. + +// These defines do nothing but are provided to make old code easier to +// compile. +#define CRYPTO_LOCK 1 +#define CRYPTO_UNLOCK 2 +#define CRYPTO_READ 4 +#define CRYPTO_WRITE 8 + +// CRYPTO_num_locks returns one. (This is non-zero that callers who allocate +// sizeof(lock) times this value don't get zero and then fail because malloc(0) +// returned NULL.) +OPENSSL_EXPORT int CRYPTO_num_locks(void); + +// CRYPTO_set_locking_callback does nothing. +OPENSSL_EXPORT void CRYPTO_set_locking_callback( + void (*func)(int mode, int lock_num, const char *file, int line)); + +// CRYPTO_set_add_lock_callback does nothing. +OPENSSL_EXPORT void CRYPTO_set_add_lock_callback(int (*func)( + int *num, int amount, int lock_num, const char *file, int line)); + +// CRYPTO_get_locking_callback returns NULL. +OPENSSL_EXPORT void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num, + const char *file, + int line); + +// CRYPTO_get_lock_name returns a fixed, dummy string. +OPENSSL_EXPORT const char *CRYPTO_get_lock_name(int lock_num); + +// CRYPTO_THREADID_set_callback returns one. +OPENSSL_EXPORT int CRYPTO_THREADID_set_callback( + void (*threadid_func)(CRYPTO_THREADID *threadid)); + +// CRYPTO_THREADID_set_numeric does nothing. +OPENSSL_EXPORT void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, + unsigned long val); + +// CRYPTO_THREADID_set_pointer does nothing. +OPENSSL_EXPORT void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr); + +// CRYPTO_THREADID_current does nothing. +OPENSSL_EXPORT void CRYPTO_THREADID_current(CRYPTO_THREADID *id); + +// CRYPTO_set_id_callback does nothing. +OPENSSL_EXPORT void CRYPTO_set_id_callback(unsigned long (*func)(void)); + +typedef struct { + int references; + struct CRYPTO_dynlock_value *data; +} CRYPTO_dynlock; + +// CRYPTO_set_dynlock_create_callback does nothing. +OPENSSL_EXPORT void CRYPTO_set_dynlock_create_callback( + struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file, + int line)); + +// CRYPTO_set_dynlock_lock_callback does nothing. +OPENSSL_EXPORT void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)( + int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)); + +// CRYPTO_set_dynlock_destroy_callback does nothing. +OPENSSL_EXPORT void CRYPTO_set_dynlock_destroy_callback( + void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l, + const char *file, int line)); + +// CRYPTO_get_dynlock_create_callback returns NULL. +OPENSSL_EXPORT struct CRYPTO_dynlock_value *( + *CRYPTO_get_dynlock_create_callback(void))(const char *file, int line); + +// CRYPTO_get_dynlock_lock_callback returns NULL. +OPENSSL_EXPORT void (*CRYPTO_get_dynlock_lock_callback(void))( + int mode, struct CRYPTO_dynlock_value *l, const char *file, int line); + +// CRYPTO_get_dynlock_destroy_callback returns NULL. +OPENSSL_EXPORT void (*CRYPTO_get_dynlock_destroy_callback(void))( + struct CRYPTO_dynlock_value *l, const char *file, int line); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_THREAD_H diff --git a/lib/boringssl/include/openssl/time.h b/lib/boringssl/include/openssl/time.h new file mode 100644 index 00000000..723ce10a --- /dev/null +++ b/lib/boringssl/include/openssl/time.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2022, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_TIME_H +#define OPENSSL_HEADER_TIME_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +// OPENSSL_posix_to_tm converts a int64_t POSIX time value in |time|, which must +// be in the range of year 0000 to 9999, to a broken out time value in |tm|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int OPENSSL_posix_to_tm(int64_t time, struct tm *out_tm); + +// OPENSSL_tm_to_posix converts a time value between the years 0 and 9999 in +// |tm| to a POSIX time value in |out|. One is returned on success, zero is +// returned on failure. It is a failure if |tm| contains out of range values. +OPENSSL_EXPORT int OPENSSL_tm_to_posix(const struct tm *tm, int64_t *out); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_TIME_H diff --git a/lib/boringssl/include/openssl/tls1.h b/lib/boringssl/include/openssl/tls1.h new file mode 100644 index 00000000..772fb87a --- /dev/null +++ b/lib/boringssl/include/openssl/tls1.h @@ -0,0 +1,662 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef OPENSSL_HEADER_TLS1_H +#define OPENSSL_HEADER_TLS1_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define TLS1_AD_END_OF_EARLY_DATA 1 +#define TLS1_AD_DECRYPTION_FAILED 21 +#define TLS1_AD_RECORD_OVERFLOW 22 +#define TLS1_AD_UNKNOWN_CA 48 +#define TLS1_AD_ACCESS_DENIED 49 +#define TLS1_AD_DECODE_ERROR 50 +#define TLS1_AD_DECRYPT_ERROR 51 +#define TLS1_AD_EXPORT_RESTRICTION 60 +#define TLS1_AD_PROTOCOL_VERSION 70 +#define TLS1_AD_INSUFFICIENT_SECURITY 71 +#define TLS1_AD_INTERNAL_ERROR 80 +#define TLS1_AD_USER_CANCELLED 90 +#define TLS1_AD_NO_RENEGOTIATION 100 +#define TLS1_AD_MISSING_EXTENSION 109 +#define TLS1_AD_UNSUPPORTED_EXTENSION 110 +#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111 +#define TLS1_AD_UNRECOGNIZED_NAME 112 +#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113 +#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114 +#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 +#define TLS1_AD_CERTIFICATE_REQUIRED 116 +#define TLS1_AD_NO_APPLICATION_PROTOCOL 120 +#define TLS1_AD_ECH_REQUIRED 121 // draft-ietf-tls-esni-13 + +// ExtensionType values from RFC 6066 +#define TLSEXT_TYPE_server_name 0 +#define TLSEXT_TYPE_status_request 5 + +// ExtensionType values from RFC 4492 +#define TLSEXT_TYPE_ec_point_formats 11 + +// ExtensionType values from RFC 5246 +#define TLSEXT_TYPE_signature_algorithms 13 + +// ExtensionType value from RFC 5764 +#define TLSEXT_TYPE_srtp 14 + +// ExtensionType value from RFC 7301 +#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +// ExtensionType value from RFC 7685 +#define TLSEXT_TYPE_padding 21 + +// ExtensionType value from RFC 7627 +#define TLSEXT_TYPE_extended_master_secret 23 + +// ExtensionType value from draft-ietf-quic-tls. Drafts 00 through 32 use +// 0xffa5 which is part of the Private Use section of the registry, and it +// collides with TLS-LTS and, based on scans, something else too (though this +// hasn't been a problem in practice since it's QUIC-only). Drafts 33 onward +// use the value 57 which was officially registered with IANA. +#define TLSEXT_TYPE_quic_transport_parameters_legacy 0xffa5 + +// ExtensionType value from RFC 9000 +#define TLSEXT_TYPE_quic_transport_parameters 57 + +// TLSEXT_TYPE_quic_transport_parameters_standard is an alias for +// |TLSEXT_TYPE_quic_transport_parameters|. Use +// |TLSEXT_TYPE_quic_transport_parameters| instead. +#define TLSEXT_TYPE_quic_transport_parameters_standard \ + TLSEXT_TYPE_quic_transport_parameters + +// ExtensionType value from RFC 8879 +#define TLSEXT_TYPE_cert_compression 27 + +// ExtensionType value from RFC 4507 +#define TLSEXT_TYPE_session_ticket 35 + +// ExtensionType values from RFC 8446 +#define TLSEXT_TYPE_supported_groups 10 +#define TLSEXT_TYPE_pre_shared_key 41 +#define TLSEXT_TYPE_early_data 42 +#define TLSEXT_TYPE_supported_versions 43 +#define TLSEXT_TYPE_cookie 44 +#define TLSEXT_TYPE_psk_key_exchange_modes 45 +#define TLSEXT_TYPE_certificate_authorities 47 +#define TLSEXT_TYPE_signature_algorithms_cert 50 +#define TLSEXT_TYPE_key_share 51 + +// ExtensionType value from RFC 5746 +#define TLSEXT_TYPE_renegotiate 0xff01 + +// ExtensionType value from draft-ietf-tls-subcerts. +#define TLSEXT_TYPE_delegated_credential 0x22 + +// ExtensionType value from draft-vvv-tls-alps. This is not an IANA defined +// extension number. +#define TLSEXT_TYPE_application_settings 17513 + +// ExtensionType values from draft-ietf-tls-esni-13. This is not an IANA defined +// extension number. +#define TLSEXT_TYPE_encrypted_client_hello 0xfe0d +#define TLSEXT_TYPE_ech_outer_extensions 0xfd00 + +// ExtensionType value from RFC 6962 +#define TLSEXT_TYPE_certificate_timestamp 18 + +// This is not an IANA defined extension number +#define TLSEXT_TYPE_next_proto_neg 13172 + +// This is not an IANA defined extension number +#define TLSEXT_TYPE_channel_id 30032 + +// status request value from RFC 3546 +#define TLSEXT_STATUSTYPE_nothing (-1) +#define TLSEXT_STATUSTYPE_ocsp 1 + +// ECPointFormat values from RFC 4492 +#define TLSEXT_ECPOINTFORMAT_uncompressed 0 +#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1 + +// Signature and hash algorithms from RFC 5246 + +#define TLSEXT_signature_anonymous 0 +#define TLSEXT_signature_rsa 1 +#define TLSEXT_signature_dsa 2 +#define TLSEXT_signature_ecdsa 3 + +#define TLSEXT_hash_none 0 +#define TLSEXT_hash_md5 1 +#define TLSEXT_hash_sha1 2 +#define TLSEXT_hash_sha224 3 +#define TLSEXT_hash_sha256 4 +#define TLSEXT_hash_sha384 5 +#define TLSEXT_hash_sha512 6 + +// From https://www.rfc-editor.org/rfc/rfc8879.html#section-3 +#define TLSEXT_cert_compression_zlib 1 +#define TLSEXT_cert_compression_brotli 2 + +#define TLSEXT_MAXLEN_host_name 255 + +// PSK ciphersuites from 4279 +#define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A +#define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008B +#define TLS1_CK_PSK_WITH_AES_128_CBC_SHA 0x0300008C +#define TLS1_CK_PSK_WITH_AES_256_CBC_SHA 0x0300008D + +// PSK ciphersuites from RFC 5489 +#define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA 0x0300C035 +#define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA 0x0300C036 + +// Additional TLS ciphersuites from expired Internet Draft +// draft-ietf-tls-56-bit-ciphersuites-01.txt +// (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see +// s3_lib.c). We actually treat them like SSL 3.0 ciphers, which we probably +// shouldn't. Note that the first two are actually not in the IDs. +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5 0x03000060 // not in ID +#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 0x03000061 // not in ID +#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA 0x03000062 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x03000063 +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA 0x03000064 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA 0x03000065 +#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066 + +// AES ciphersuites from RFC 3268 + +#define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F +#define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030 +#define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031 +#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032 +#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033 +#define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034 + +#define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035 +#define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036 +#define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037 +#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038 +#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039 +#define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A + +// TLS v1.2 ciphersuites +#define TLS1_CK_RSA_WITH_NULL_SHA256 0x0300003B +#define TLS1_CK_RSA_WITH_AES_128_SHA256 0x0300003C +#define TLS1_CK_RSA_WITH_AES_256_SHA256 0x0300003D +#define TLS1_CK_DH_DSS_WITH_AES_128_SHA256 0x0300003E +#define TLS1_CK_DH_RSA_WITH_AES_128_SHA256 0x0300003F +#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA256 0x03000040 + +// Camellia ciphersuites from RFC 4132 +#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045 +#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046 + +// TLS v1.2 ciphersuites +#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA256 0x03000067 +#define TLS1_CK_DH_DSS_WITH_AES_256_SHA256 0x03000068 +#define TLS1_CK_DH_RSA_WITH_AES_256_SHA256 0x03000069 +#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA256 0x0300006A +#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA256 0x0300006B +#define TLS1_CK_ADH_WITH_AES_128_SHA256 0x0300006C +#define TLS1_CK_ADH_WITH_AES_256_SHA256 0x0300006D + +// Camellia ciphersuites from RFC 4132 +#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088 +#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089 + +// SEED ciphersuites from RFC 4162 +#define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096 +#define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097 +#define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098 +#define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099 +#define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A +#define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B + +// TLS v1.2 GCM ciphersuites from RFC 5288 +#define TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 0x0300009C +#define TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 0x0300009D +#define TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256 0x0300009E +#define TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384 0x0300009F +#define TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256 0x030000A0 +#define TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384 0x030000A1 +#define TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256 0x030000A2 +#define TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384 0x030000A3 +#define TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256 0x030000A4 +#define TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384 0x030000A5 +#define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256 0x030000A6 +#define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384 0x030000A7 + +// ECC ciphersuites from RFC 4492 +#define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001 +#define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002 +#define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005 + +#define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006 +#define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007 +#define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A + +#define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B +#define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C +#define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D +#define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E +#define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F + +#define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010 +#define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011 +#define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012 +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013 +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014 + +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0x0300C027 + +#define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015 +#define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016 +#define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017 +#define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018 +#define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019 + +// SRP ciphersuites from RFC 5054 +#define TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0x0300C01A +#define TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0x0300C01B +#define TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0x0300C01C +#define TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA 0x0300C01D +#define TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0x0300C01E +#define TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0x0300C01F +#define TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA 0x0300C020 +#define TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0x0300C021 +#define TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0x0300C022 + +// ECDH HMAC based ciphersuites from RFC 5289 + +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256 0x0300C023 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384 0x0300C024 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256 0x0300C025 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384 0x0300C026 +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 0x0300C027 +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384 0x0300C028 +#define TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256 0x0300C029 +#define TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384 0x0300C02A + +// ECDH GCM based ciphersuites from RFC 5289 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02B +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02C +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02D +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02E +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0x0300C02F +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0x0300C030 +#define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031 +#define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032 + +// ChaCha20-Poly1305 cipher suites from RFC 7905. +#define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA8 +#define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA9 +#define TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0x0300CCAC + +// TLS 1.3 ciphersuites from RFC 8446. +#define TLS1_3_CK_AES_128_GCM_SHA256 0x03001301 +#define TLS1_3_CK_AES_256_GCM_SHA384 0x03001302 +#define TLS1_3_CK_CHACHA20_POLY1305_SHA256 0x03001303 + +// The following constants are legacy aliases of |TLS1_3_CK_*|. +// TODO(davidben): Migrate callers to the new name and remove these. +#define TLS1_CK_AES_128_GCM_SHA256 TLS1_3_CK_AES_128_GCM_SHA256 +#define TLS1_CK_AES_256_GCM_SHA384 TLS1_3_CK_AES_256_GCM_SHA384 +#define TLS1_CK_CHACHA20_POLY1305_SHA256 TLS1_3_CK_CHACHA20_POLY1305_SHA256 + +// XXX +// Inconsistency alert: +// The OpenSSL names of ciphers with ephemeral DH here include the string +// "DHE", while elsewhere it has always been "EDH". +// (The alias for the list of all such ciphers also is "EDH".) +// The specifications speak of "EDH"; maybe we should allow both forms +// for everything. +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 "EXP1024-RC4-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 "EXP1024-RC2-CBC-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DES-CBC-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA \ + "EXP1024-DHE-DSS-DES-CBC-SHA" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA "EXP1024-RC4-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA "EXP1024-DHE-DSS-RC4-SHA" +#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA" + +// AES ciphersuites from RFC 3268 +#define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA" +#define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA" + +#define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA" +#define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA" + +// ECC ciphersuites from RFC 4492 +#define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA" + +#define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA256 "ECDHE-RSA-AES128-SHA256" + +#define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA" +#define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA" +#define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA" +#define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA" + +// PSK ciphersuites from RFC 4279 +#define TLS1_TXT_PSK_WITH_RC4_128_SHA "PSK-RC4-SHA" +#define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA "PSK-3DES-EDE-CBC-SHA" +#define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA "PSK-AES128-CBC-SHA" +#define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA "PSK-AES256-CBC-SHA" + +// PSK ciphersuites from RFC 5489 +#define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA "ECDHE-PSK-AES128-CBC-SHA" +#define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA "ECDHE-PSK-AES256-CBC-SHA" + +// SRP ciphersuite from RFC 5054 +#define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA "SRP-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "SRP-RSA-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "SRP-DSS-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA "SRP-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "SRP-RSA-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "SRP-DSS-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA "SRP-AES-256-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "SRP-RSA-AES-256-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "SRP-DSS-AES-256-CBC-SHA" + +// Camellia ciphersuites from RFC 4132 +#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA" +#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA" + +#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA" +#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA" + +// SEED ciphersuites from RFC 4162 +#define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA" +#define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA" +#define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA" +#define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA" +#define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA" +#define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA" + +// TLS v1.2 ciphersuites +#define TLS1_TXT_RSA_WITH_NULL_SHA256 "NULL-SHA256" +#define TLS1_TXT_RSA_WITH_AES_128_SHA256 "AES128-SHA256" +#define TLS1_TXT_RSA_WITH_AES_256_SHA256 "AES256-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA256 "DH-DSS-AES128-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA256 "DH-RSA-AES128-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256 "DHE-DSS-AES128-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 "DHE-RSA-AES128-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA256 "DH-DSS-AES256-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA256 "DH-RSA-AES256-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256 "DHE-DSS-AES256-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 "DHE-RSA-AES256-SHA256" +#define TLS1_TXT_ADH_WITH_AES_128_SHA256 "ADH-AES128-SHA256" +#define TLS1_TXT_ADH_WITH_AES_256_SHA256 "ADH-AES256-SHA256" + +// TLS v1.2 GCM ciphersuites from RFC 5288 +#define TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256 "AES128-GCM-SHA256" +#define TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384 "AES256-GCM-SHA384" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 "DHE-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 "DHE-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256 "DH-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384 "DH-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256 "DHE-DSS-AES128-GCM-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384 "DHE-DSS-AES256-GCM-SHA384" +#define TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256 "DH-DSS-AES128-GCM-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384 "DH-DSS-AES256-GCM-SHA384" +#define TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256 "ADH-AES128-GCM-SHA256" +#define TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384 "ADH-AES256-GCM-SHA384" + +// ECDH HMAC based ciphersuites from RFC 5289 + +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256 "ECDHE-ECDSA-AES128-SHA256" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384 "ECDHE-ECDSA-AES256-SHA384" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_SHA256 "ECDH-ECDSA-AES128-SHA256" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_SHA384 "ECDH-ECDSA-AES256-SHA384" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 "ECDHE-RSA-AES128-SHA256" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 "ECDHE-RSA-AES256-SHA384" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256 "ECDH-RSA-AES128-SHA256" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384 "ECDH-RSA-AES256-SHA384" + +// ECDH GCM based ciphersuites from RFC 5289 +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 \ + "ECDHE-ECDSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 \ + "ECDHE-ECDSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 \ + "ECDH-ECDSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 \ + "ECDH-ECDSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "ECDHE-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "ECDHE-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384" + +#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 \ + "ECDHE-RSA-CHACHA20-POLY1305" +#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 \ + "ECDHE-ECDSA-CHACHA20-POLY1305" +#define TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 \ + "ECDHE-PSK-CHACHA20-POLY1305" + +// TLS 1.3 ciphersuites from RFC 8446. +#define TLS1_3_RFC_AES_128_GCM_SHA256 "TLS_AES_128_GCM_SHA256" +#define TLS1_3_RFC_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" +#define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" + +// The following constants are legacy aliases of |TLS1_3_CK_*|. +// TODO(bbe): Migrate callers to the new name and remove these. +#define TLS1_TXT_AES_128_GCM_SHA256 TLS1_3_RFC_AES_128_GCM_SHA256 +#define TLS1_TXT_AES_256_GCM_SHA384 TLS1_3_RFC_AES_256_GCM_SHA384 +#define TLS1_TXT_CHACHA20_POLY1305_SHA256 TLS1_3_RFC_CHACHA20_POLY1305_SHA256 + +#define TLS_CT_RSA_SIGN 1 +#define TLS_CT_DSS_SIGN 2 +#define TLS_CT_RSA_FIXED_DH 3 +#define TLS_CT_DSS_FIXED_DH 4 +#define TLS_CT_ECDSA_SIGN 64 +#define TLS_CT_RSA_FIXED_ECDH 65 +#define TLS_CT_ECDSA_FIXED_ECDH 66 + +#define TLS_MD_MAX_CONST_SIZE 20 + + +#ifdef __cplusplus +} // extern C +#endif + +#endif // OPENSSL_HEADER_TLS1_H diff --git a/lib/boringssl/include/openssl/trust_token.h b/lib/boringssl/include/openssl/trust_token.h new file mode 100644 index 00000000..b6aa6b34 --- /dev/null +++ b/lib/boringssl/include/openssl/trust_token.h @@ -0,0 +1,344 @@ +/* Copyright (c) 2020, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_TRUST_TOKEN_H +#define OPENSSL_HEADER_TRUST_TOKEN_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Trust Token implementation. +// +// Trust Token is an implementation of an experimental mechanism similar to +// Privacy Pass which allows issuance and redemption of anonymized tokens with +// limited private metadata. +// +// References: +// https://eprint.iacr.org/2020/072.pdf +// https://github.com/alxdavids/privacy-pass-ietf/tree/master/drafts +// https://github.com/WICG/trust-token-api/blob/master/README.md +// +// WARNING: This API is unstable and subject to change. + +// TRUST_TOKEN_experiment_v1 is an experimental Trust Tokens protocol using +// PMBTokens and P-384. +OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void); + +// TRUST_TOKEN_experiment_v2_voprf is an experimental Trust Tokens protocol +// using VOPRFs and P-384 with up to 6 keys, without RR verification. +OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_voprf(void); + +// TRUST_TOKEN_experiment_v2_pmb is an experimental Trust Tokens protocol using +// PMBTokens and P-384 with up to 3 keys, without RR verification. +OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_pmb(void); + +// TRUST_TOKEN_pst_v1_voprf is an experimental Trust Tokens protocol +// using VOPRFs and P-384 with up to 6 keys, without RR verification. +OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_pst_v1_voprf(void); + +// TRUST_TOKEN_pst_v1_pmb is an experimental Trust Tokens protocol using +// PMBTokens and P-384 with up to 3 keys, without RR verification. +OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_pst_v1_pmb(void); + +// trust_token_st represents a single-use token for the Trust Token protocol. +// For the client, this is the token and its corresponding signature. For the +// issuer, this is the token itself. +struct trust_token_st { + uint8_t *data; + size_t len; +}; + +DEFINE_STACK_OF(TRUST_TOKEN) + +// TRUST_TOKEN_new creates a newly-allocated |TRUST_TOKEN| with value |data| or +// NULL on allocation failure. +OPENSSL_EXPORT TRUST_TOKEN *TRUST_TOKEN_new(const uint8_t *data, size_t len); + +// TRUST_TOKEN_free releases memory associated with |token|. +OPENSSL_EXPORT void TRUST_TOKEN_free(TRUST_TOKEN *token); + +#define TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE 512 +#define TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE 512 + +// TRUST_TOKEN_generate_key creates a new Trust Token keypair labeled with |id| +// and serializes the private and public keys, writing the private key to +// |out_priv_key| and setting |*out_priv_key_len| to the number of bytes +// written, and writing the public key to |out_pub_key| and setting +// |*out_pub_key_len| to the number of bytes written. +// +// At most |max_priv_key_len| and |max_pub_key_len| bytes are written. In order +// to ensure success, these should be at least +// |TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE| and |TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE|. +// +// This function returns one on success or zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_generate_key( + const TRUST_TOKEN_METHOD *method, uint8_t *out_priv_key, + size_t *out_priv_key_len, size_t max_priv_key_len, uint8_t *out_pub_key, + size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id); + +// TRUST_TOKEN_derive_key_from_secret deterministically derives a new Trust +// Token keypair labeled with |id| from an input |secret| and serializes the +// private and public keys, writing the private key to |out_priv_key| and +// setting |*out_priv_key_len| to the number of bytes written, and writing the +// public key to |out_pub_key| and setting |*out_pub_key_len| to the number of +// bytes written. +// +// At most |max_priv_key_len| and |max_pub_key_len| bytes are written. In order +// to ensure success, these should be at least +// |TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE| and |TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE|. +// +// This function returns one on success or zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_derive_key_from_secret( + const TRUST_TOKEN_METHOD *method, uint8_t *out_priv_key, + size_t *out_priv_key_len, size_t max_priv_key_len, uint8_t *out_pub_key, + size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id, + const uint8_t *secret, size_t secret_len); + + +// Trust Token client implementation. +// +// These functions implements the client half of the Trust Token protocol. A +// single |TRUST_TOKEN_CLIENT| can perform a single protocol operation. + +// TRUST_TOKEN_CLIENT_new returns a newly-allocated |TRUST_TOKEN_CLIENT| +// configured to use a max batchsize of |max_batchsize| or NULL on error. +// Issuance requests must be made in batches smaller than |max_batchsize|. This +// function will return an error if |max_batchsize| is too large for Trust +// Tokens. +OPENSSL_EXPORT TRUST_TOKEN_CLIENT *TRUST_TOKEN_CLIENT_new( + const TRUST_TOKEN_METHOD *method, size_t max_batchsize); + +// TRUST_TOKEN_CLIENT_free releases memory associated with |ctx|. +OPENSSL_EXPORT void TRUST_TOKEN_CLIENT_free(TRUST_TOKEN_CLIENT *ctx); + +// TRUST_TOKEN_CLIENT_add_key configures the |ctx| to support the public key +// |key|. It sets |*out_key_index| to the index this key has been configured to. +// It returns one on success or zero on error if the |key| can't be parsed or +// too many keys have been configured. +OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_add_key(TRUST_TOKEN_CLIENT *ctx, + size_t *out_key_index, + const uint8_t *key, + size_t key_len); + +// TRUST_TOKEN_CLIENT_set_srr_key sets the public key used to verify the SRR. It +// returns one on success and zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_set_srr_key(TRUST_TOKEN_CLIENT *ctx, + EVP_PKEY *key); + +// TRUST_TOKEN_CLIENT_begin_issuance produces a request for |count| trust tokens +// and serializes the request into a newly-allocated buffer, setting |*out| to +// that buffer and |*out_len| to its length. The caller takes ownership of the +// buffer and must call |OPENSSL_free| when done. It returns one on success and +// zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_begin_issuance(TRUST_TOKEN_CLIENT *ctx, + uint8_t **out, + size_t *out_len, + size_t count); + +// TRUST_TOKEN_CLIENT_begin_issuance_over_message produces a request for a trust +// token derived from |msg| and serializes the request into a newly-allocated +// buffer, setting |*out| to that buffer and |*out_len| to its length. The +// caller takes ownership of the buffer and must call |OPENSSL_free| when done. +// It returns one on success and zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_begin_issuance_over_message( + TRUST_TOKEN_CLIENT *ctx, uint8_t **out, size_t *out_len, size_t count, + const uint8_t *msg, size_t msg_len); + +// TRUST_TOKEN_CLIENT_finish_issuance consumes |response| from the issuer and +// extracts the tokens, returning a list of tokens and the index of the key used +// to sign the tokens in |*out_key_index|. The caller can use this to determine +// what key was used in an issuance and to drop tokens if a new key commitment +// arrives without the specified key present. The caller takes ownership of the +// list and must call |sk_TRUST_TOKEN_pop_free| when done. The list is empty if +// issuance fails. +OPENSSL_EXPORT STACK_OF(TRUST_TOKEN) * + TRUST_TOKEN_CLIENT_finish_issuance(TRUST_TOKEN_CLIENT *ctx, + size_t *out_key_index, + const uint8_t *response, + size_t response_len); + + +// TRUST_TOKEN_CLIENT_begin_redemption produces a request to redeem a token +// |token| and receive a signature over |data| and serializes the request into +// a newly-allocated buffer, setting |*out| to that buffer and |*out_len| to +// its length. |time| is the number of seconds since the UNIX epoch and used to +// verify the validity of the issuer's response in TrustTokenV1 and ignored in +// other versions. The caller takes ownership of the buffer and must call +// |OPENSSL_free| when done. It returns one on success or zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_begin_redemption( + TRUST_TOKEN_CLIENT *ctx, uint8_t **out, size_t *out_len, + const TRUST_TOKEN *token, const uint8_t *data, size_t data_len, + uint64_t time); + +// TRUST_TOKEN_CLIENT_finish_redemption consumes |response| from the issuer. In +// |TRUST_TOKEN_experiment_v1|, it then verifies the SRR and if valid sets +// |*out_rr| and |*out_rr_len| (respectively, |*out_sig| and |*out_sig_len|) +// to a newly-allocated buffer containing the SRR (respectively, the SRR +// signature). In other versions, it sets |*out_rr| and |*out_rr_len| +// to a newly-allocated buffer containing |response| and leaves all validation +// to the caller. It returns one on success or zero on failure. +OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_finish_redemption( + TRUST_TOKEN_CLIENT *ctx, uint8_t **out_rr, size_t *out_rr_len, + uint8_t **out_sig, size_t *out_sig_len, const uint8_t *response, + size_t response_len); + + +// Trust Token issuer implementation. +// +// These functions implement the issuer half of the Trust Token protocol. A +// |TRUST_TOKEN_ISSUER| can be reused across multiple protocol operations. It +// may be used concurrently on multiple threads by non-mutating functions, +// provided no other thread is concurrently calling a mutating function. +// Functions which take a |const| pointer are non-mutating and functions which +// take a non-|const| pointer are mutating. + +// TRUST_TOKEN_ISSUER_new returns a newly-allocated |TRUST_TOKEN_ISSUER| +// configured to use a max batchsize of |max_batchsize| or NULL on error. +// Issuance requests must be made in batches smaller than |max_batchsize|. This +// function will return an error if |max_batchsize| is too large for Trust +// Tokens. +OPENSSL_EXPORT TRUST_TOKEN_ISSUER *TRUST_TOKEN_ISSUER_new( + const TRUST_TOKEN_METHOD *method, size_t max_batchsize); + +// TRUST_TOKEN_ISSUER_free releases memory associated with |ctx|. +OPENSSL_EXPORT void TRUST_TOKEN_ISSUER_free(TRUST_TOKEN_ISSUER *ctx); + +// TRUST_TOKEN_ISSUER_add_key configures the |ctx| to support the private key +// |key|. It must be a private key returned by |TRUST_TOKEN_generate_key|. It +// returns one on success or zero on error. This function may fail if the |key| +// can't be parsed or too many keys have been configured. +OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_add_key(TRUST_TOKEN_ISSUER *ctx, + const uint8_t *key, + size_t key_len); + +// TRUST_TOKEN_ISSUER_set_srr_key sets the private key used to sign the SRR. It +// returns one on success and zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_set_srr_key(TRUST_TOKEN_ISSUER *ctx, + EVP_PKEY *key); + +// TRUST_TOKEN_ISSUER_set_metadata_key sets the key used to encrypt the private +// metadata. The key is a randomly generated bytestring of at least 32 bytes +// used to encode the private metadata bit in the SRR. It returns one on success +// and zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_set_metadata_key(TRUST_TOKEN_ISSUER *ctx, + const uint8_t *key, + size_t len); + +// TRUST_TOKEN_ISSUER_issue ingests |request| for token issuance +// and generates up to |max_issuance| valid tokens, producing a list of blinded +// tokens and storing the response into a newly-allocated buffer and setting +// |*out| to that buffer, |*out_len| to its length, and |*out_tokens_issued| to +// the number of tokens issued. The tokens are issued with public metadata of +// |public_metadata| and a private metadata value of |private_metadata|. +// |public_metadata| must be one of the previously configured key IDs. +// |private_metadata| must be 0 or 1. The caller takes ownership of the buffer +// and must call |OPENSSL_free| when done. It returns one on success or zero on +// error. +OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_issue( + const TRUST_TOKEN_ISSUER *ctx, uint8_t **out, size_t *out_len, + size_t *out_tokens_issued, const uint8_t *request, size_t request_len, + uint32_t public_metadata, uint8_t private_metadata, size_t max_issuance); + +// TRUST_TOKEN_ISSUER_redeem ingests a |request| for token redemption and +// verifies the token. The public metadata is stored in |*out_public|. The +// private metadata (if any) is stored in |*out_private|. The extracted +// |TRUST_TOKEN| is stored into a newly-allocated buffer and stored in +// |*out_token|. The extracted client data is stored into a newly-allocated +// buffer and stored in |*out_client_data|. The caller takes ownership of each +// output buffer and must call |OPENSSL_free| when done. It returns one on +// success or zero on error. +// +// The caller must keep track of all values of |*out_token| seen globally before +// returning a response to the client. If the value has been reused, the caller +// must report an error to the client. Returning a response with replayed values +// allows an attacker to double-spend tokens. +OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_redeem( + const TRUST_TOKEN_ISSUER *ctx, uint32_t *out_public, uint8_t *out_private, + TRUST_TOKEN **out_token, uint8_t **out_client_data, + size_t *out_client_data_len, const uint8_t *request, size_t request_len); + +// TRUST_TOKEN_ISSUER_redeem_raw is a legacy alias for +// |TRUST_TOKEN_ISSUER_redeem|. +#define TRUST_TOKEN_ISSUER_redeem_raw TRUST_TOKEN_ISSUER_redeem + +// TRUST_TOKEN_ISSUER_redeem_over_message ingests a |request| for token +// redemption and a message and verifies the token and that it is derived from +// the provided |msg|. The public metadata is stored in +// |*out_public|. The private metadata (if any) is stored in |*out_private|. The +// extracted |TRUST_TOKEN| is stored into a newly-allocated buffer and stored in +// |*out_token|. The extracted client data is stored into a newly-allocated +// buffer and stored in |*out_client_data|. The caller takes ownership of each +// output buffer and must call |OPENSSL_free| when done. It returns one on +// success or zero on error. +// +// The caller must keep track of all values of |*out_token| seen globally before +// returning a response to the client. If the value has been reused, the caller +// must report an error to the client. Returning a response with replayed values +// allows an attacker to double-spend tokens. +OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_redeem_over_message( + const TRUST_TOKEN_ISSUER *ctx, uint32_t *out_public, uint8_t *out_private, + TRUST_TOKEN **out_token, uint8_t **out_client_data, + size_t *out_client_data_len, const uint8_t *request, size_t request_len, + const uint8_t *msg, size_t msg_len); + +// TRUST_TOKEN_decode_private_metadata decodes |encrypted_bit| using the +// private metadata key specified by a |key| buffer of length |key_len| and the +// nonce by a |nonce| buffer of length |nonce_len|. The nonce in +// |TRUST_TOKEN_experiment_v1| is the token-hash field of the SRR. |*out_value| +// is set to the decrypted value, either zero or one. It returns one on success +// and zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_decode_private_metadata( + const TRUST_TOKEN_METHOD *method, uint8_t *out_value, const uint8_t *key, + size_t key_len, const uint8_t *nonce, size_t nonce_len, + uint8_t encrypted_bit); + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(TRUST_TOKEN, TRUST_TOKEN_free) +BORINGSSL_MAKE_DELETER(TRUST_TOKEN_CLIENT, TRUST_TOKEN_CLIENT_free) +BORINGSSL_MAKE_DELETER(TRUST_TOKEN_ISSUER, TRUST_TOKEN_ISSUER_free) + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#define TRUST_TOKEN_R_KEYGEN_FAILURE 100 +#define TRUST_TOKEN_R_BUFFER_TOO_SMALL 101 +#define TRUST_TOKEN_R_OVER_BATCHSIZE 102 +#define TRUST_TOKEN_R_DECODE_ERROR 103 +#define TRUST_TOKEN_R_SRR_SIGNATURE_ERROR 104 +#define TRUST_TOKEN_R_DECODE_FAILURE 105 +#define TRUST_TOKEN_R_INVALID_METADATA 106 +#define TRUST_TOKEN_R_TOO_MANY_KEYS 107 +#define TRUST_TOKEN_R_NO_KEYS_CONFIGURED 108 +#define TRUST_TOKEN_R_INVALID_KEY_ID 109 +#define TRUST_TOKEN_R_INVALID_TOKEN 110 +#define TRUST_TOKEN_R_BAD_VALIDITY_CHECK 111 +#define TRUST_TOKEN_R_NO_SRR_KEY_CONFIGURED 112 +#define TRUST_TOKEN_R_INVALID_METADATA_KEY 113 +#define TRUST_TOKEN_R_INVALID_PROOF 114 + +#endif // OPENSSL_HEADER_TRUST_TOKEN_H diff --git a/lib/boringssl/include/openssl/type_check.h b/lib/boringssl/include/openssl/type_check.h new file mode 100644 index 00000000..6460ab14 --- /dev/null +++ b/lib/boringssl/include/openssl/type_check.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_TYPE_CHECK_H +#define OPENSSL_HEADER_TYPE_CHECK_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// CHECKED_CAST casts |p| from type |from| to type |to|. +// +// TODO(davidben): Although this macro is not public API and is unused in +// BoringSSL, wpa_supplicant uses it to define its own stacks. Remove this once +// wpa_supplicant has been fixed. +#define CHECKED_CAST(to, from, p) ((to) (1 ? (p) : (from)0)) + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_TYPE_CHECK_H diff --git a/lib/boringssl/include/openssl/x509.h b/lib/boringssl/include/openssl/x509.h new file mode 100644 index 00000000..8deb767e --- /dev/null +++ b/lib/boringssl/include/openssl/x509.h @@ -0,0 +1,3063 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef OPENSSL_HEADER_X509_H +#define OPENSSL_HEADER_X509_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Legacy X.509 library. +// +// This header is part of OpenSSL's X.509 implementation. It is retained for +// compatibility but should not be used by new code. The functions are difficult +// to use correctly, and have buggy or non-standard behaviors. They are thus +// particularly prone to behavior changes and API removals, as BoringSSL +// iterates on these issues. +// +// In the future, a replacement library will be available. Meanwhile, minimize +// dependencies on this header where possible. +// +// TODO(https://crbug.com/boringssl/426): Documentation for this library is +// still in progress. Some functions have not yet been documented, and some +// functions have not yet been grouped into sections. + + +// Certificates. +// +// An |X509| object represents an X.509 certificate, defined in RFC 5280. +// +// Although an |X509| is a mutable object, mutating an |X509| can give incorrect +// results. Callers typically obtain |X509|s by parsing some input with +// |d2i_X509|, etc. Such objects carry information such as the serialized +// TBSCertificate and decoded extensions, which will become inconsistent when +// mutated. +// +// Instead, mutation functions should only be used when issuing new +// certificates, as described in a later section. + +DEFINE_STACK_OF(X509) + +// X509 is an |ASN1_ITEM| whose ASN.1 type is X.509 Certificate (RFC 5280) and C +// type is |X509*|. +DECLARE_ASN1_ITEM(X509) + +// X509_up_ref adds one to the reference count of |x509| and returns one. +OPENSSL_EXPORT int X509_up_ref(X509 *x509); + +// X509_chain_up_ref returns a newly-allocated |STACK_OF(X509)| containing a +// shallow copy of |chain|, or NULL on error. That is, the return value has the +// same contents as |chain|, and each |X509|'s reference count is incremented by +// one. +OPENSSL_EXPORT STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain); + +// X509_dup returns a newly-allocated copy of |x509|, or NULL on error. This +// function works by serializing the structure, so auxiliary properties (see +// |i2d_X509_AUX|) are not preserved. Additionally, if |x509| is incomplete, +// this function may fail. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |crl| was +// mutated. +OPENSSL_EXPORT X509 *X509_dup(X509 *x509); + +// X509_free decrements |x509|'s reference count and, if zero, releases memory +// associated with |x509|. +OPENSSL_EXPORT void X509_free(X509 *x509); + +// d2i_X509 parses up to |len| bytes from |*inp| as a DER-encoded X.509 +// Certificate (RFC 5280), as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509 *d2i_X509(X509 **out, const uint8_t **inp, long len); + +// X509_parse_from_buffer parses an X.509 structure from |buf| and returns a +// fresh X509 or NULL on error. There must not be any trailing data in |buf|. +// The returned structure (if any) holds a reference to |buf| rather than +// copying parts of it as a normal |d2i_X509| call would do. +OPENSSL_EXPORT X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf); + +// i2d_X509 marshals |x509| as a DER-encoded X.509 Certificate (RFC 5280), as +// described in |i2d_SAMPLE|. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |x509| was +// mutated. +OPENSSL_EXPORT int i2d_X509(X509 *x509, uint8_t **outp); + +// X509_VERSION_* are X.509 version numbers. Note the numerical values of all +// defined X.509 versions are one less than the named version. +#define X509_VERSION_1 0 +#define X509_VERSION_2 1 +#define X509_VERSION_3 2 + +// X509_get_version returns the numerical value of |x509|'s version, which will +// be one of the |X509_VERSION_*| constants. +OPENSSL_EXPORT long X509_get_version(const X509 *x509); + +// X509_get0_serialNumber returns |x509|'s serial number. +OPENSSL_EXPORT const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x509); + +// X509_get0_notBefore returns |x509|'s notBefore time. +OPENSSL_EXPORT const ASN1_TIME *X509_get0_notBefore(const X509 *x509); + +// X509_get0_notAfter returns |x509|'s notAfter time. +OPENSSL_EXPORT const ASN1_TIME *X509_get0_notAfter(const X509 *x509); + +// X509_get_issuer_name returns |x509|'s issuer. +OPENSSL_EXPORT X509_NAME *X509_get_issuer_name(const X509 *x509); + +// X509_get_subject_name returns |x509|'s subject. +OPENSSL_EXPORT X509_NAME *X509_get_subject_name(const X509 *x509); + +// X509_get_X509_PUBKEY returns the public key of |x509|. Note this function is +// not const-correct for legacy reasons. Callers should not modify the returned +// object. +OPENSSL_EXPORT X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x509); + +// X509_get_pubkey returns |x509|'s public key as an |EVP_PKEY|, or NULL if the +// public key was unsupported or could not be decoded. This function returns a +// reference to the |EVP_PKEY|. The caller must release the result with +// |EVP_PKEY_free| when done. +OPENSSL_EXPORT EVP_PKEY *X509_get_pubkey(X509 *x509); + +// X509_get0_pubkey_bitstr returns the BIT STRING portion of |x509|'s public +// key. Note this does not contain the AlgorithmIdentifier portion. +// +// WARNING: This function returns a non-const pointer for OpenSSL compatibility, +// but the caller must not modify the resulting object. Doing so will break +// internal invariants in |x509|. +OPENSSL_EXPORT ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x509); + +// X509_get0_uids sets |*out_issuer_uid| to a non-owning pointer to the +// issuerUID field of |x509|, or NULL if |x509| has no issuerUID. It similarly +// outputs |x509|'s subjectUID field to |*out_subject_uid|. +// +// Callers may pass NULL to either |out_issuer_uid| or |out_subject_uid| to +// ignore the corresponding field. +OPENSSL_EXPORT void X509_get0_uids(const X509 *x509, + const ASN1_BIT_STRING **out_issuer_uid, + const ASN1_BIT_STRING **out_subject_uid); + +// X509_get0_extensions returns |x509|'s extension list, or NULL if |x509| omits +// it. +OPENSSL_EXPORT const STACK_OF(X509_EXTENSION) *X509_get0_extensions( + const X509 *x509); + +// X509_get_ext_count returns the number of extensions in |x|. +OPENSSL_EXPORT int X509_get_ext_count(const X509 *x); + +// X509_get_ext_by_NID behaves like |X509v3_get_ext_by_NID| but searches for +// extensions in |x|. +OPENSSL_EXPORT int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos); + +// X509_get_ext_by_OBJ behaves like |X509v3_get_ext_by_OBJ| but searches for +// extensions in |x|. +OPENSSL_EXPORT int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, + int lastpos); + +// X509_get_ext_by_critical behaves like |X509v3_get_ext_by_critical| but +// searches for extensions in |x|. +OPENSSL_EXPORT int X509_get_ext_by_critical(const X509 *x, int crit, + int lastpos); + +// X509_get_ext returns the extension in |x| at index |loc|, or NULL if |loc| is +// out of bounds. This function returns a non-const pointer for OpenSSL +// compatibility, but callers should not mutate the result. +OPENSSL_EXPORT X509_EXTENSION *X509_get_ext(const X509 *x, int loc); + +// X509_get0_tbs_sigalg returns the signature algorithm in |x509|'s +// TBSCertificate. For the outer signature algorithm, see |X509_get0_signature|. +// +// Certificates with mismatched signature algorithms will successfully parse, +// but they will be rejected when verifying. +OPENSSL_EXPORT const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x509); + +// X509_get0_signature sets |*out_sig| and |*out_alg| to the signature and +// signature algorithm of |x509|, respectively. Either output pointer may be +// NULL to ignore the value. +// +// This function outputs the outer signature algorithm. For the one in the +// TBSCertificate, see |X509_get0_tbs_sigalg|. Certificates with mismatched +// signature algorithms will successfully parse, but they will be rejected when +// verifying. +OPENSSL_EXPORT void X509_get0_signature(const ASN1_BIT_STRING **out_sig, + const X509_ALGOR **out_alg, + const X509 *x509); + +// X509_get_signature_nid returns the NID corresponding to |x509|'s signature +// algorithm, or |NID_undef| if the signature algorithm does not correspond to +// a known NID. +OPENSSL_EXPORT int X509_get_signature_nid(const X509 *x509); + +// i2d_X509_tbs serializes the TBSCertificate portion of |x509|, as described in +// |i2d_SAMPLE|. +// +// This function preserves the original encoding of the TBSCertificate and may +// not reflect modifications made to |x509|. It may be used to manually verify +// the signature of an existing certificate. To generate certificates, use +// |i2d_re_X509_tbs| instead. +OPENSSL_EXPORT int i2d_X509_tbs(X509 *x509, unsigned char **outp); + +// X509_verify checks that |x509| has a valid signature by |pkey|. It returns +// one if the signature is valid and zero otherwise. Note this function only +// checks the signature itself and does not perform a full certificate +// validation. +OPENSSL_EXPORT int X509_verify(X509 *x509, EVP_PKEY *pkey); + + +// Issuing certificates. +// +// An |X509| object may also represent an incomplete certificate. Callers may +// construct empty |X509| objects, fill in fields individually, and finally sign +// the result. The following functions may be used for this purpose. + +// X509_new returns a newly-allocated, empty |X509| object, or NULL on error. +// This produces an incomplete certificate which may be filled in to issue a new +// certificate. +OPENSSL_EXPORT X509 *X509_new(void); + +// X509_set_version sets |x509|'s version to |version|, which should be one of +// the |X509V_VERSION_*| constants. It returns one on success and zero on error. +// +// If unsure, use |X509_VERSION_3|. +OPENSSL_EXPORT int X509_set_version(X509 *x509, long version); + +// X509_set_serialNumber sets |x509|'s serial number to |serial|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int X509_set_serialNumber(X509 *x509, + const ASN1_INTEGER *serial); + +// X509_set1_notBefore sets |x509|'s notBefore time to |tm|. It returns one on +// success and zero on error. +OPENSSL_EXPORT int X509_set1_notBefore(X509 *x509, const ASN1_TIME *tm); + +// X509_set1_notAfter sets |x509|'s notAfter time to |tm|. it returns one on +// success and zero on error. +OPENSSL_EXPORT int X509_set1_notAfter(X509 *x509, const ASN1_TIME *tm); + +// X509_getm_notBefore returns a mutable pointer to |x509|'s notBefore time. +OPENSSL_EXPORT ASN1_TIME *X509_getm_notBefore(X509 *x509); + +// X509_getm_notAfter returns a mutable pointer to |x509|'s notAfter time. +OPENSSL_EXPORT ASN1_TIME *X509_getm_notAfter(X509 *x); + +// X509_set_issuer_name sets |x509|'s issuer to a copy of |name|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int X509_set_issuer_name(X509 *x509, X509_NAME *name); + +// X509_set_subject_name sets |x509|'s subject to a copy of |name|. It returns +// one on success and zero on error. +OPENSSL_EXPORT int X509_set_subject_name(X509 *x509, X509_NAME *name); + +// X509_set_pubkey sets |x509|'s public key to |pkey|. It returns one on success +// and zero on error. This function does not take ownership of |pkey| and +// internally copies and updates reference counts as needed. +OPENSSL_EXPORT int X509_set_pubkey(X509 *x509, EVP_PKEY *pkey); + +// X509_delete_ext removes the extension in |x| at index |loc| and returns the +// removed extension, or NULL if |loc| was out of bounds. If non-NULL, the +// caller must release the result with |X509_EXTENSION_free|. +OPENSSL_EXPORT X509_EXTENSION *X509_delete_ext(X509 *x, int loc); + +// X509_add_ext adds a copy of |ex| to |x|. It returns one on success and zero +// on failure. The caller retains ownership of |ex| and can release it +// independently of |x|. +// +// The new extension is inserted at index |loc|, shifting extensions to the +// right. If |loc| is -1 or out of bounds, the new extension is appended to the +// list. +OPENSSL_EXPORT int X509_add_ext(X509 *x, const X509_EXTENSION *ex, int loc); + +// X509_sign signs |x509| with |pkey| and replaces the signature algorithm and +// signature fields. It returns the length of the signature on success and zero +// on error. This function uses digest algorithm |md|, or |pkey|'s default if +// NULL. Other signing parameters use |pkey|'s defaults. To customize them, use +// |X509_sign_ctx|. +OPENSSL_EXPORT int X509_sign(X509 *x509, EVP_PKEY *pkey, const EVP_MD *md); + +// X509_sign_ctx signs |x509| with |ctx| and replaces the signature algorithm +// and signature fields. It returns the length of the signature on success and +// zero on error. The signature algorithm and parameters come from |ctx|, which +// must have been initialized with |EVP_DigestSignInit|. The caller should +// configure the corresponding |EVP_PKEY_CTX| before calling this function. +OPENSSL_EXPORT int X509_sign_ctx(X509 *x509, EVP_MD_CTX *ctx); + +// i2d_re_X509_tbs serializes the TBSCertificate portion of |x509|, as described +// in |i2d_SAMPLE|. +// +// This function re-encodes the TBSCertificate and may not reflect |x509|'s +// original encoding. It may be used to manually generate a signature for a new +// certificate. To verify certificates, use |i2d_X509_tbs| instead. +OPENSSL_EXPORT int i2d_re_X509_tbs(X509 *x509, unsigned char **outp); + +// X509_set1_signature_algo sets |x509|'s signature algorithm to |algo| and +// returns one on success or zero on error. It updates both the signature field +// of the TBSCertificate structure, and the signatureAlgorithm field of the +// Certificate. +OPENSSL_EXPORT int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo); + +// X509_set1_signature_value sets |x509|'s signature to a copy of the |sig_len| +// bytes pointed by |sig|. It returns one on success and zero on error. +// +// Due to a specification error, X.509 certificates store signatures in ASN.1 +// BIT STRINGs, but signature algorithms return byte strings rather than bit +// strings. This function creates a BIT STRING containing a whole number of +// bytes, with the bit order matching the DER encoding. This matches the +// encoding used by all X.509 signature algorithms. +OPENSSL_EXPORT int X509_set1_signature_value(X509 *x509, const uint8_t *sig, + size_t sig_len); + + +// Auxiliary certificate properties. +// +// |X509| objects optionally maintain auxiliary properties. These are not part +// of the certificates themselves, and thus are not covered by signatures or +// preserved by the standard serialization. They are used as inputs or outputs +// to other functions in this library. + +// i2d_X509_AUX marshals |x509| as a DER-encoded X.509 Certificate (RFC 5280), +// followed optionally by a separate, OpenSSL-specific structure with auxiliary +// properties. It behaves as described in |i2d_SAMPLE|. +// +// Unlike similarly-named functions, this function does not output a single +// ASN.1 element. Directly embedding the output in a larger ASN.1 structure will +// not behave correctly. +OPENSSL_EXPORT int i2d_X509_AUX(X509 *x509, unsigned char **outp); + +// d2i_X509_AUX parses up to |length| bytes from |*inp| as a DER-encoded X.509 +// Certificate (RFC 5280), followed optionally by a separate, OpenSSL-specific +// structure with auxiliary properties. It behaves as described in |d2i_SAMPLE|. +// +// Some auxiliary properties affect trust decisions, so this function should not +// be used with untrusted input. +// +// Unlike similarly-named functions, this function does not parse a single +// ASN.1 element. Trying to parse data directly embedded in a larger ASN.1 +// structure will not behave correctly. +OPENSSL_EXPORT X509 *d2i_X509_AUX(X509 **x509, const unsigned char **inp, + long length); + +// X509_alias_set1 sets |x509|'s alias to |len| bytes from |name|. If |name| is +// NULL, the alias is cleared instead. Aliases are not part of the certificate +// itself and will not be serialized by |i2d_X509|. +OPENSSL_EXPORT int X509_alias_set1(X509 *x509, const unsigned char *name, + ossl_ssize_t len); + +// X509_keyid_set1 sets |x509|'s key ID to |len| bytes from |id|. If |id| is +// NULL, the key ID is cleared instead. Key IDs are not part of the certificate +// itself and will not be serialized by |i2d_X509|. +OPENSSL_EXPORT int X509_keyid_set1(X509 *x509, const unsigned char *id, + ossl_ssize_t len); + +// X509_alias_get0 looks up |x509|'s alias. If found, it sets |*out_len| to the +// alias's length and returns a pointer to a buffer containing the contents. If +// not found, it outputs the empty string by returning NULL and setting +// |*out_len| to zero. +// +// If |x509| was parsed from a PKCS#12 structure (see +// |PKCS12_get_key_and_certs|), the alias will reflect the friendlyName +// attribute (RFC 2985). +// +// WARNING: In OpenSSL, this function did not set |*out_len| when the alias was +// missing. Callers that target both OpenSSL and BoringSSL should set the value +// to zero before calling this function. +OPENSSL_EXPORT unsigned char *X509_alias_get0(X509 *x509, int *out_len); + +// X509_keyid_get0 looks up |x509|'s key ID. If found, it sets |*out_len| to the +// key ID's length and returns a pointer to a buffer containing the contents. If +// not found, it outputs the empty string by returning NULL and setting +// |*out_len| to zero. +// +// WARNING: In OpenSSL, this function did not set |*out_len| when the alias was +// missing. Callers that target both OpenSSL and BoringSSL should set the value +// to zero before calling this function. +OPENSSL_EXPORT unsigned char *X509_keyid_get0(X509 *x509, int *out_len); + + +// Certificate revocation lists. +// +// An |X509_CRL| object represents an X.509 certificate revocation list (CRL), +// defined in RFC 5280. A CRL is a signed list of certificates which are no +// longer considered valid. +// +// Although an |X509_CRL| is a mutable object, mutating an |X509_CRL| can give +// incorrect results. Callers typically obtain |X509_CRL|s by parsing some input +// with |d2i_X509_CRL|, etc. Such objects carry information such as the +// serialized TBSCertList and decoded extensions, which will become inconsistent +// when mutated. +// +// Instead, mutation functions should only be used when issuing new CRLs, as +// described in a later section. + +DEFINE_STACK_OF(X509_CRL) + +// X509_CRL is an |ASN1_ITEM| whose ASN.1 type is X.509 CertificateList (RFC +// 5280) and C type is |X509_CRL*|. +DECLARE_ASN1_ITEM(X509_CRL) + +// X509_CRL_up_ref adds one to the reference count of |crl| and returns one. +OPENSSL_EXPORT int X509_CRL_up_ref(X509_CRL *crl); + +// X509_CRL_dup returns a newly-allocated copy of |crl|, or NULL on error. This +// function works by serializing the structure, so if |crl| is incomplete, it +// may fail. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |crl| was +// mutated. +OPENSSL_EXPORT X509_CRL *X509_CRL_dup(X509_CRL *crl); + +// X509_CRL_free decrements |crl|'s reference count and, if zero, releases +// memory associated with |crl|. +OPENSSL_EXPORT void X509_CRL_free(X509_CRL *crl); + +// d2i_X509_CRL parses up to |len| bytes from |*inp| as a DER-encoded X.509 +// CertificateList (RFC 5280), as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509_CRL *d2i_X509_CRL(X509_CRL **out, const uint8_t **inp, + long len); + +// i2d_X509_CRL marshals |crl| as a X.509 CertificateList (RFC 5280), as +// described in |i2d_SAMPLE|. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |crl| was +// mutated. +OPENSSL_EXPORT int i2d_X509_CRL(X509_CRL *crl, uint8_t **outp); + +#define X509_CRL_VERSION_1 0 +#define X509_CRL_VERSION_2 1 + +// X509_CRL_get_version returns the numerical value of |crl|'s version, which +// will be one of the |X509_CRL_VERSION_*| constants. +OPENSSL_EXPORT long X509_CRL_get_version(const X509_CRL *crl); + +// X509_CRL_get0_lastUpdate returns |crl|'s thisUpdate time. The OpenSSL API +// refers to this field as lastUpdate. +OPENSSL_EXPORT const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl); + +// X509_CRL_get0_nextUpdate returns |crl|'s nextUpdate time, or NULL if |crl| +// has none. +OPENSSL_EXPORT const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl); + +// X509_CRL_get_issuer returns |crl|'s issuer name. Note this function is not +// const-correct for legacy reasons. +OPENSSL_EXPORT X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); + +// X509_CRL_get_REVOKED returns the list of revoked certificates in |crl|, or +// NULL if |crl| omits it. +// +// TOOD(davidben): This function was originally a macro, without clear const +// semantics. It should take a const input and give const output, but the latter +// would break existing callers. For now, we match upstream. +OPENSSL_EXPORT STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl); + +// X509_CRL_get0_extensions returns |crl|'s extension list, or NULL if |crl| +// omits it. +OPENSSL_EXPORT const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions( + const X509_CRL *crl); + +// X509_CRL_get_ext_count returns the number of extensions in |x|. +OPENSSL_EXPORT int X509_CRL_get_ext_count(const X509_CRL *x); + +// X509_CRL_get_ext_by_NID behaves like |X509v3_get_ext_by_NID| but searches for +// extensions in |x|. +OPENSSL_EXPORT int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, + int lastpos); + +// X509_CRL_get_ext_by_OBJ behaves like |X509v3_get_ext_by_OBJ| but searches for +// extensions in |x|. +OPENSSL_EXPORT int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, + const ASN1_OBJECT *obj, int lastpos); + +// X509_CRL_get_ext_by_critical behaves like |X509v3_get_ext_by_critical| but +// searches for extensions in |x|. +OPENSSL_EXPORT int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, + int lastpos); + +// X509_CRL_get_ext returns the extension in |x| at index |loc|, or NULL if +// |loc| is out of bounds. This function returns a non-const pointer for OpenSSL +// compatibility, but callers should not mutate the result. +OPENSSL_EXPORT X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc); + +// X509_CRL_get0_signature sets |*out_sig| and |*out_alg| to the signature and +// signature algorithm of |crl|, respectively. Either output pointer may be NULL +// to ignore the value. +// +// This function outputs the outer signature algorithm, not the one in the +// TBSCertList. CRLs with mismatched signature algorithms will successfully +// parse, but they will be rejected when verifying. +OPENSSL_EXPORT void X509_CRL_get0_signature(const X509_CRL *crl, + const ASN1_BIT_STRING **out_sig, + const X509_ALGOR **out_alg); + +// X509_CRL_get_signature_nid returns the NID corresponding to |crl|'s signature +// algorithm, or |NID_undef| if the signature algorithm does not correspond to +// a known NID. +OPENSSL_EXPORT int X509_CRL_get_signature_nid(const X509_CRL *crl); + +// i2d_X509_CRL_tbs serializes the TBSCertList portion of |crl|, as described in +// |i2d_SAMPLE|. +// +// This function preserves the original encoding of the TBSCertList and may not +// reflect modifications made to |crl|. It may be used to manually verify the +// signature of an existing CRL. To generate CRLs, use |i2d_re_X509_CRL_tbs| +// instead. +OPENSSL_EXPORT int i2d_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp); + +// X509_CRL_verify checks that |crl| has a valid signature by |pkey|. It returns +// one if the signature is valid and zero otherwise. +OPENSSL_EXPORT int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey); + + +// Issuing certificate revocation lists. +// +// An |X509_CRL| object may also represent an incomplete CRL. Callers may +// construct empty |X509_CRL| objects, fill in fields individually, and finally +// sign the result. The following functions may be used for this purpose. + +// X509_CRL_new returns a newly-allocated, empty |X509_CRL| object, or NULL on +// error. This object may be filled in and then signed to construct a CRL. +OPENSSL_EXPORT X509_CRL *X509_CRL_new(void); + +// X509_CRL_set_version sets |crl|'s version to |version|, which should be one +// of the |X509_CRL_VERSION_*| constants. It returns one on success and zero on +// error. +// +// If unsure, use |X509_CRL_VERSION_2|. Note that, unlike certificates, CRL +// versions are only defined up to v2. Callers should not use |X509_VERSION_3|. +OPENSSL_EXPORT int X509_CRL_set_version(X509_CRL *crl, long version); + +// X509_CRL_set_issuer_name sets |crl|'s issuer to a copy of |name|. It returns +// one on success and zero on error. +OPENSSL_EXPORT int X509_CRL_set_issuer_name(X509_CRL *crl, X509_NAME *name); + +// X509_CRL_set1_lastUpdate sets |crl|'s thisUpdate time to |tm|. It returns one +// on success and zero on error. The OpenSSL API refers to this field as +// lastUpdate. +OPENSSL_EXPORT int X509_CRL_set1_lastUpdate(X509_CRL *crl, const ASN1_TIME *tm); + +// X509_CRL_set1_nextUpdate sets |crl|'s nextUpdate time to |tm|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int X509_CRL_set1_nextUpdate(X509_CRL *crl, const ASN1_TIME *tm); + +// X509_CRL_delete_ext removes the extension in |x| at index |loc| and returns +// the removed extension, or NULL if |loc| was out of bounds. If non-NULL, the +// caller must release the result with |X509_EXTENSION_free|. +OPENSSL_EXPORT X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); + +// X509_CRL_add_ext adds a copy of |ex| to |x|. It returns one on success and +// zero on failure. The caller retains ownership of |ex| and can release it +// independently of |x|. +// +// The new extension is inserted at index |loc|, shifting extensions to the +// right. If |loc| is -1 or out of bounds, the new extension is appended to the +// list. +OPENSSL_EXPORT int X509_CRL_add_ext(X509_CRL *x, const X509_EXTENSION *ex, + int loc); + +// X509_CRL_sign signs |crl| with |pkey| and replaces the signature algorithm +// and signature fields. It returns the length of the signature on success and +// zero on error. This function uses digest algorithm |md|, or |pkey|'s default +// if NULL. Other signing parameters use |pkey|'s defaults. To customize them, +// use |X509_CRL_sign_ctx|. +OPENSSL_EXPORT int X509_CRL_sign(X509_CRL *crl, EVP_PKEY *pkey, + const EVP_MD *md); + +// X509_CRL_sign_ctx signs |crl| with |ctx| and replaces the signature algorithm +// and signature fields. It returns the length of the signature on success and +// zero on error. The signature algorithm and parameters come from |ctx|, which +// must have been initialized with |EVP_DigestSignInit|. The caller should +// configure the corresponding |EVP_PKEY_CTX| before calling this function. +OPENSSL_EXPORT int X509_CRL_sign_ctx(X509_CRL *crl, EVP_MD_CTX *ctx); + +// i2d_re_X509_CRL_tbs serializes the TBSCertList portion of |crl|, as described +// in |i2d_SAMPLE|. +// +// This function re-encodes the TBSCertList and may not reflect |crl|'s original +// encoding. It may be used to manually generate a signature for a new CRL. To +// verify CRLs, use |i2d_X509_CRL_tbs| instead. +OPENSSL_EXPORT int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp); + +// X509_CRL_set1_signature_algo sets |crl|'s signature algorithm to |algo| and +// returns one on success or zero on error. It updates both the signature field +// of the TBSCertList structure, and the signatureAlgorithm field of the CRL. +OPENSSL_EXPORT int X509_CRL_set1_signature_algo(X509_CRL *crl, + const X509_ALGOR *algo); + +// X509_CRL_set1_signature_value sets |crl|'s signature to a copy of the +// |sig_len| bytes pointed by |sig|. It returns one on success and zero on +// error. +// +// Due to a specification error, X.509 CRLs store signatures in ASN.1 BIT +// STRINGs, but signature algorithms return byte strings rather than bit +// strings. This function creates a BIT STRING containing a whole number of +// bytes, with the bit order matching the DER encoding. This matches the +// encoding used by all X.509 signature algorithms. +OPENSSL_EXPORT int X509_CRL_set1_signature_value(X509_CRL *crl, + const uint8_t *sig, + size_t sig_len); + + +// Certificate requests. +// +// An |X509_REQ| represents a PKCS #10 certificate request (RFC 2986). These are +// also referred to as certificate signing requests or CSRs. CSRs are a common +// format used to request a certificate from a CA. +// +// Although an |X509_REQ| is a mutable object, mutating an |X509_REQ| can give +// incorrect results. Callers typically obtain |X509_REQ|s by parsing some input +// with |d2i_X509_REQ|, etc. Such objects carry information such as the +// serialized CertificationRequestInfo, which will become inconsistent when +// mutated. +// +// Instead, mutation functions should only be used when issuing new CRLs, as +// described in a later section. + +// X509_REQ is an |ASN1_ITEM| whose ASN.1 type is CertificateRequest (RFC 2986) +// and C type is |X509_REQ*|. +DECLARE_ASN1_ITEM(X509_REQ) + +// X509_REQ_dup returns a newly-allocated copy of |req|, or NULL on error. This +// function works by serializing the structure, so if |req| is incomplete, it +// may fail. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |req| was +// mutated. +OPENSSL_EXPORT X509_REQ *X509_REQ_dup(X509_REQ *req); + +// X509_REQ_free releases memory associated with |req|. +OPENSSL_EXPORT void X509_REQ_free(X509_REQ *req); + +// d2i_X509_REQ parses up to |len| bytes from |*inp| as a DER-encoded +// CertificateRequest (RFC 2986), as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509_REQ *d2i_X509_REQ(X509_REQ **out, const uint8_t **inp, + long len); + +// i2d_X509_REQ marshals |req| as a CertificateRequest (RFC 2986), as described +// in |i2d_SAMPLE|. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |req| was +// mutated. +OPENSSL_EXPORT int i2d_X509_REQ(X509_REQ *req, uint8_t **outp); + +// X509_REQ_VERSION_1 is the version constant for |X509_REQ| objects. No other +// versions are defined. +#define X509_REQ_VERSION_1 0 + +// X509_REQ_get_version returns the numerical value of |req|'s version. This +// will always be |X509_REQ_VERSION_1| for valid CSRs. For compatibility, +// |d2i_X509_REQ| also accepts some invalid version numbers, in which case this +// function may return other values. +OPENSSL_EXPORT long X509_REQ_get_version(const X509_REQ *req); + +// X509_REQ_get_subject_name returns |req|'s subject name. Note this function is +// not const-correct for legacy reasons. +OPENSSL_EXPORT X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req); + +// X509_REQ_get_pubkey returns |req|'s public key as an |EVP_PKEY|, or NULL if +// the public key was unsupported or could not be decoded. This function returns +// a reference to the |EVP_PKEY|. The caller must release the result with +// |EVP_PKEY_free| when done. +OPENSSL_EXPORT EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req); + +// X509_REQ_get_attr_count returns the number of attributes in |req|. +OPENSSL_EXPORT int X509_REQ_get_attr_count(const X509_REQ *req); + +// X509_REQ_get_attr returns the attribute at index |loc| in |req|, or NULL if +// out of bounds. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); + +// X509_REQ_get_attr_by_NID returns the index of the attribute in |req| of type +// |nid|, or a negative number if not found. If found, callers can use +// |X509_REQ_get_attr| to look up the attribute by index. +// +// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers +// can thus loop over all matching attributes by first passing -1 and then +// passing the previously-returned value until no match is returned. +OPENSSL_EXPORT int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, + int lastpos); + +// X509_REQ_get_attr_by_OBJ behaves like |X509_REQ_get_attr_by_NID| but looks +// for attributes of type |obj|. +OPENSSL_EXPORT int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, + const ASN1_OBJECT *obj, + int lastpos); + +// X509_REQ_extension_nid returns one if |nid| is a supported CSR attribute type +// for carrying extensions and zero otherwise. The supported types are +// |NID_ext_req| (pkcs-9-at-extensionRequest from RFC 2985) and |NID_ms_ext_req| +// (a Microsoft szOID_CERT_EXTENSIONS variant). +OPENSSL_EXPORT int X509_REQ_extension_nid(int nid); + +// X509_REQ_get_extensions decodes the list of requested extensions in |req| and +// returns a newly-allocated |STACK_OF(X509_EXTENSION)| containing the result. +// It returns NULL on error, or if |req| did not request extensions. +// +// CSRs do not store extensions directly. Instead there are attribute types +// which are defined to hold extensions. See |X509_REQ_extension_nid|. This +// function supports both pkcs-9-at-extensionRequest from RFC 2985 and the +// Microsoft szOID_CERT_EXTENSIONS variant. If both are present, +// pkcs-9-at-extensionRequest is preferred. +OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); + +// X509_REQ_get0_signature sets |*out_sig| and |*out_alg| to the signature and +// signature algorithm of |req|, respectively. Either output pointer may be NULL +// to ignore the value. +OPENSSL_EXPORT void X509_REQ_get0_signature(const X509_REQ *req, + const ASN1_BIT_STRING **out_sig, + const X509_ALGOR **out_alg); + +// X509_REQ_get_signature_nid returns the NID corresponding to |req|'s signature +// algorithm, or |NID_undef| if the signature algorithm does not correspond to +// a known NID. +OPENSSL_EXPORT int X509_REQ_get_signature_nid(const X509_REQ *req); + +// X509_REQ_verify checks that |req| has a valid signature by |pkey|. It returns +// one if the signature is valid and zero otherwise. +OPENSSL_EXPORT int X509_REQ_verify(X509_REQ *req, EVP_PKEY *pkey); + + +// Issuing certificate requests. +// +// An |X509_REQ| object may also represent an incomplete CSR. Callers may +// construct empty |X509_REQ| objects, fill in fields individually, and finally +// sign the result. The following functions may be used for this purpose. + +// X509_REQ_new returns a newly-allocated, empty |X509_REQ| object, or NULL on +// error. This object may be filled in and then signed to construct a CSR. +OPENSSL_EXPORT X509_REQ *X509_REQ_new(void); + +// X509_REQ_set_version sets |req|'s version to |version|, which should be +// |X509_REQ_VERSION_1|. It returns one on success and zero on error. +// +// The only defined CSR version is |X509_REQ_VERSION_1|, so there is no need to +// call this function. +OPENSSL_EXPORT int X509_REQ_set_version(X509_REQ *req, long version); + +// X509_REQ_set_subject_name sets |req|'s subject to a copy of |name|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); + +// X509_REQ_set_pubkey sets |req|'s public key to |pkey|. It returns one on +// success and zero on error. This function does not take ownership of |pkey| +// and internally copies and updates reference counts as needed. +OPENSSL_EXPORT int X509_REQ_set_pubkey(X509_REQ *req, EVP_PKEY *pkey); + +// X509_REQ_delete_attr removes the attribute at index |loc| in |req|. It +// returns the removed attribute to the caller, or NULL if |loc| was out of +// bounds. If non-NULL, the caller must release the result with +// |X509_ATTRIBUTE_free| when done. It is also safe, but not necessary, to call +// |X509_ATTRIBUTE_free| if the result is NULL. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); + +// X509_REQ_add1_attr appends a copy of |attr| to |req|'s list of attributes. It +// returns one on success and zero on error. +OPENSSL_EXPORT int X509_REQ_add1_attr(X509_REQ *req, + const X509_ATTRIBUTE *attr); + +// X509_REQ_add1_attr_by_OBJ appends a new attribute to |req| with type |obj|. +// It returns one on success and zero on error. The value is determined by +// |X509_ATTRIBUTE_set1_data|. +// +// WARNING: The interpretation of |attrtype|, |data|, and |len| is complex and +// error-prone. See |X509_ATTRIBUTE_set1_data| for details. +OPENSSL_EXPORT int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, + int attrtype, + const unsigned char *data, + int len); + +// X509_REQ_add1_attr_by_NID behaves like |X509_REQ_add1_attr_by_OBJ| except the +// attribute type is determined by |nid|. +OPENSSL_EXPORT int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, + int attrtype, + const unsigned char *data, + int len); + +// X509_REQ_add1_attr_by_txt behaves like |X509_REQ_add1_attr_by_OBJ| except the +// attribute type is determined by calling |OBJ_txt2obj| with |attrname|. +OPENSSL_EXPORT int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int attrtype, + const unsigned char *data, + int len); + +// X509_REQ_add_extensions_nid adds an attribute to |req| of type |nid|, to +// request the certificate extensions in |exts|. It returns one on success and +// zero on error. |nid| should be |NID_ext_req| or |NID_ms_ext_req|. +OPENSSL_EXPORT int X509_REQ_add_extensions_nid( + X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts, int nid); + +// X509_REQ_add_extensions behaves like |X509_REQ_add_extensions_nid|, using the +// standard |NID_ext_req| for the attribute type. +OPENSSL_EXPORT int X509_REQ_add_extensions( + X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts); + +// X509_REQ_sign signs |req| with |pkey| and replaces the signature algorithm +// and signature fields. It returns the length of the signature on success and +// zero on error. This function uses digest algorithm |md|, or |pkey|'s default +// if NULL. Other signing parameters use |pkey|'s defaults. To customize them, +// use |X509_REQ_sign_ctx|. +OPENSSL_EXPORT int X509_REQ_sign(X509_REQ *req, EVP_PKEY *pkey, + const EVP_MD *md); + +// X509_REQ_sign_ctx signs |req| with |ctx| and replaces the signature algorithm +// and signature fields. It returns the length of the signature on success and +// zero on error. The signature algorithm and parameters come from |ctx|, which +// must have been initialized with |EVP_DigestSignInit|. The caller should +// configure the corresponding |EVP_PKEY_CTX| before calling this function. +OPENSSL_EXPORT int X509_REQ_sign_ctx(X509_REQ *req, EVP_MD_CTX *ctx); + +// i2d_re_X509_REQ_tbs serializes the CertificationRequestInfo (see RFC 2986) +// portion of |req|, as described in |i2d_SAMPLE|. +// +// This function re-encodes the CertificationRequestInfo and may not reflect +// |req|'s original encoding. It may be used to manually generate a signature +// for a new certificate request. +OPENSSL_EXPORT int i2d_re_X509_REQ_tbs(X509_REQ *req, uint8_t **outp); + +// X509_REQ_set1_signature_algo sets |req|'s signature algorithm to |algo| and +// returns one on success or zero on error. +OPENSSL_EXPORT int X509_REQ_set1_signature_algo(X509_REQ *req, + const X509_ALGOR *algo); + +// X509_REQ_set1_signature_value sets |req|'s signature to a copy of the +// |sig_len| bytes pointed by |sig|. It returns one on success and zero on +// error. +// +// Due to a specification error, PKCS#10 certificate requests store signatures +// in ASN.1 BIT STRINGs, but signature algorithms return byte strings rather +// than bit strings. This function creates a BIT STRING containing a whole +// number of bytes, with the bit order matching the DER encoding. This matches +// the encoding used by all X.509 signature algorithms. +OPENSSL_EXPORT int X509_REQ_set1_signature_value(X509_REQ *req, + const uint8_t *sig, + size_t sig_len); + + +// Names. +// +// An |X509_NAME| represents an X.509 Name structure (RFC 5280). X.509 names are +// a complex, hierarchical structure over a collection of attributes. Each name +// is sequence of relative distinguished names (RDNs), decreasing in +// specificity. For example, the first RDN may specify the country, while the +// next RDN may specify a locality. Each RDN is, itself, a set of attributes. +// Having more than one attribute in an RDN is uncommon, but possible. Within an +// RDN, attributes have the same level in specificity. Attribute types are +// OBJECT IDENTIFIERs. This determines the ASN.1 type of the value, which is +// commonly a string but may be other types. +// +// The |X509_NAME| representation flattens this two-level structure into a +// single list of attributes. Each attribute is stored in an |X509_NAME_ENTRY|, +// with also maintains the index of the RDN it is part of, accessible via +// |X509_NAME_ENTRY_set|. This can be used to recover the two-level structure. +// +// X.509 names are largely vestigial. Historically, DNS names were parsed out of +// the subject's common name attribute, but this is deprecated and has since +// moved to the subject alternative name extension. In modern usage, X.509 names +// are primarily opaque identifiers to link a certificate with its issuer. + +DEFINE_STACK_OF(X509_NAME_ENTRY) +DEFINE_STACK_OF(X509_NAME) + +// X509_NAME is an |ASN1_ITEM| whose ASN.1 type is X.509 Name (RFC 5280) and C +// type is |X509_NAME*|. +DECLARE_ASN1_ITEM(X509_NAME) + +// X509_NAME_new returns a new, empty |X509_NAME_new|, or NULL on +// error. +OPENSSL_EXPORT X509_NAME *X509_NAME_new(void); + +// X509_NAME_free releases memory associated with |name|. +OPENSSL_EXPORT void X509_NAME_free(X509_NAME *name); + +// d2i_X509_NAME parses up to |len| bytes from |*inp| as a DER-encoded X.509 +// Name (RFC 5280), as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509_NAME *d2i_X509_NAME(X509_NAME **out, const uint8_t **inp, + long len); + +// i2d_X509_NAME marshals |in| as a DER-encoded X.509 Name (RFC 5280), as +// described in |i2d_SAMPLE|. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |in| was +// mutated. +OPENSSL_EXPORT int i2d_X509_NAME(X509_NAME *in, uint8_t **outp); + +// X509_NAME_dup returns a newly-allocated copy of |name|, or NULL on error. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |name| was +// mutated. +OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *name); + +// X509_NAME_get0_der sets |*out_der| and |*out_der_len| +// +// Avoid this function and prefer |i2d_X509_NAME|. It is one of the reasons +// these functions are not consistently thread-safe or const-correct. Depending +// on the resolution of https://crbug.com/boringssl/407, this function may be +// removed or cause poor performance. +OPENSSL_EXPORT int X509_NAME_get0_der(X509_NAME *name, const uint8_t **out_der, + size_t *out_der_len); + +// X509_NAME_set makes a copy of |name|. On success, it frees |*xn|, sets |*xn| +// to the copy, and returns one. Otherwise, it returns zero. +// +// TODO(https://crbug.com/boringssl/407): This function should be const and +// thread-safe but is currently neither in some cases, notably if |name| was +// mutated. +OPENSSL_EXPORT int X509_NAME_set(X509_NAME **xn, X509_NAME *name); + +// X509_NAME_entry_count returns the number of entries in |name|. +OPENSSL_EXPORT int X509_NAME_entry_count(const X509_NAME *name); + +// X509_NAME_get_index_by_NID returns the zero-based index of the first +// attribute in |name| with type |nid|, or -1 if there is none. |nid| should be +// one of the |NID_*| constants. If |lastpos| is non-negative, it begins +// searching at |lastpos+1|. To search all attributes, pass in -1, not zero. +// +// Indices from this function refer to |X509_NAME|'s flattened representation. +OPENSSL_EXPORT int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, + int lastpos); + +// X509_NAME_get_index_by_OBJ behaves like |X509_NAME_get_index_by_NID| but +// looks for attributes with type |obj|. +OPENSSL_EXPORT int X509_NAME_get_index_by_OBJ(const X509_NAME *name, + const ASN1_OBJECT *obj, + int lastpos); + +// X509_NAME_get_entry returns the attribute in |name| at index |loc|, or NULL +// if |loc| is out of range. |loc| is interpreted using |X509_NAME|'s flattened +// representation. This function returns a non-const pointer for OpenSSL +// compatibility, but callers should not mutate the result. Doing so will break +// internal invariants in the library. +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, + int loc); + +// X509_NAME_delete_entry removes and returns the attribute in |name| at index +// |loc|, or NULL if |loc| is out of range. |loc| is interpreted using +// |X509_NAME|'s flattened representation. If the attribute is found, the caller +// is responsible for releasing the result with |X509_NAME_ENTRY_free|. +// +// This function will internally update RDN indices (see |X509_NAME_ENTRY_set|) +// so they continue to be consecutive. +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, + int loc); + +// X509_NAME_add_entry adds a copy of |entry| to |name| and returns one on +// success or zero on error. If |loc| is -1, the entry is appended to |name|. +// Otherwise, it is inserted at index |loc|. If |set| is -1, the entry is added +// to the previous entry's RDN. If it is 0, the entry becomes a singleton RDN. +// If 1, it is added to next entry's RDN. +// +// This function will internally update RDN indices (see |X509_NAME_ENTRY_set|) +// so they continue to be consecutive. +OPENSSL_EXPORT int X509_NAME_add_entry(X509_NAME *name, + const X509_NAME_ENTRY *entry, int loc, + int set); + +// X509_NAME_add_entry_by_OBJ adds a new entry to |name| and returns one on +// success or zero on error. The entry's attribute type is |obj|. The entry's +// attribute value is determined by |type|, |bytes|, and |len|, as in +// |X509_NAME_ENTRY_set_data|. The entry's position is determined by |loc| and +// |set| as in |X509_NAME_add_entry|. +OPENSSL_EXPORT int X509_NAME_add_entry_by_OBJ(X509_NAME *name, + const ASN1_OBJECT *obj, int type, + const uint8_t *bytes, + ossl_ssize_t len, int loc, + int set); + +// X509_NAME_add_entry_by_NID behaves like |X509_NAME_add_entry_by_OBJ| but sets +// the entry's attribute type to |nid|, which should be one of the |NID_*| +// constants. +OPENSSL_EXPORT int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, + int type, const uint8_t *bytes, + ossl_ssize_t len, int loc, + int set); + +// X509_NAME_add_entry_by_txt behaves like |X509_NAME_add_entry_by_OBJ| but sets +// the entry's attribute type to |field|, which is passed to |OBJ_txt2obj|. +OPENSSL_EXPORT int X509_NAME_add_entry_by_txt(X509_NAME *name, + const char *field, int type, + const uint8_t *bytes, + ossl_ssize_t len, int loc, + int set); + +// X509_NAME_ENTRY is an |ASN1_ITEM| whose ASN.1 type is AttributeTypeAndValue +// (RFC 5280) and C type is |X509_NAME_ENTRY*|. +DECLARE_ASN1_ITEM(X509_NAME_ENTRY) + +// X509_NAME_ENTRY_new returns a new, empty |X509_NAME_ENTRY_new|, or NULL on +// error. +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_new(void); + +// X509_NAME_ENTRY_free releases memory associated with |entry|. +OPENSSL_EXPORT void X509_NAME_ENTRY_free(X509_NAME_ENTRY *entry); + +// d2i_X509_NAME_ENTRY parses up to |len| bytes from |*inp| as a DER-encoded +// AttributeTypeAndValue (RFC 5280), as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509_NAME_ENTRY *d2i_X509_NAME_ENTRY(X509_NAME_ENTRY **out, + const uint8_t **inp, + long len); + +// i2d_X509_NAME_ENTRY marshals |in| as a DER-encoded AttributeTypeAndValue (RFC +// 5280), as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_X509_NAME_ENTRY(const X509_NAME_ENTRY *in, + uint8_t **outp); + +// X509_NAME_ENTRY_dup returns a newly-allocated copy of |entry|, or NULL on +// error. +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_dup( + const X509_NAME_ENTRY *entry); + +// X509_NAME_ENTRY_get_object returns |entry|'s attribute type. This function +// returns a non-const pointer for OpenSSL compatibility, but callers should not +// mutate the result. Doing so will break internal invariants in the library. +OPENSSL_EXPORT ASN1_OBJECT *X509_NAME_ENTRY_get_object( + const X509_NAME_ENTRY *entry); + +// X509_NAME_ENTRY_set_object sets |entry|'s attribute type to |obj|. It returns +// one on success and zero on error. +OPENSSL_EXPORT int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *entry, + const ASN1_OBJECT *obj); + +// X509_NAME_ENTRY_get_data returns |entry|'s attribute value, represented as an +// |ASN1_STRING|. This value may have any ASN.1 type, so callers must check the +// type before interpreting the contents. This function returns a non-const +// pointer for OpenSSL compatibility, but callers should not mutate the result. +// Doing so will break internal invariants in the library. +// +// TODO(https://crbug.com/boringssl/412): Although the spec says any ASN.1 type +// is allowed, we currently only allow an ad-hoc set of types. Additionally, it +// is unclear if some types can even be represented by this function. +OPENSSL_EXPORT ASN1_STRING *X509_NAME_ENTRY_get_data( + const X509_NAME_ENTRY *entry); + +// X509_NAME_ENTRY_set_data sets |entry|'s value to |len| bytes from |bytes|. It +// returns one on success and zero on error. If |len| is -1, |bytes| must be a +// NUL-terminated C string and the length is determined by |strlen|. |bytes| is +// converted to an ASN.1 type as follows: +// +// If |type| is a |MBSTRING_*| constant, the value is an ASN.1 string. The +// string is determined by decoding |bytes| in the encoding specified by |type|, +// and then re-encoding it in a form appropriate for |entry|'s attribute type. +// See |ASN1_STRING_set_by_NID| for details. +// +// Otherwise, the value is an |ASN1_STRING| with type |type| and value |bytes|. +// See |ASN1_STRING| for how to format ASN.1 types as an |ASN1_STRING|. If +// |type| is |V_ASN1_UNDEF| the previous |ASN1_STRING| type is reused. +OPENSSL_EXPORT int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *entry, int type, + const uint8_t *bytes, + ossl_ssize_t len); + +// X509_NAME_ENTRY_set returns the zero-based index of the RDN which contains +// |entry|. Consecutive entries with the same index are part of the same RDN. +OPENSSL_EXPORT int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *entry); + +// X509_NAME_ENTRY_create_by_OBJ creates a new |X509_NAME_ENTRY| with attribute +// type |obj|. The attribute value is determined from |type|, |bytes|, and |len| +// as in |X509_NAME_ENTRY_set_data|. It returns the |X509_NAME_ENTRY| on success +// and NULL on error. +// +// If |out| is non-NULL and |*out| is NULL, it additionally sets |*out| to the +// result on success. If both |out| and |*out| are non-NULL, it updates the +// object at |*out| instead of allocating a new one. +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ( + X509_NAME_ENTRY **out, const ASN1_OBJECT *obj, int type, + const uint8_t *bytes, ossl_ssize_t len); + +// X509_NAME_ENTRY_create_by_NID behaves like |X509_NAME_ENTRY_create_by_OBJ| +// except the attribute type is |nid|, which should be one of the |NID_*| +// constants. +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID( + X509_NAME_ENTRY **out, int nid, int type, const uint8_t *bytes, + ossl_ssize_t len); + +// X509_NAME_ENTRY_create_by_txt behaves like |X509_NAME_ENTRY_create_by_OBJ| +// except the attribute type is |field|, which is passed to |OBJ_txt2obj|. +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt( + X509_NAME_ENTRY **out, const char *field, int type, const uint8_t *bytes, + ossl_ssize_t len); + + +// Extensions. +// +// X.509 certificates and CRLs may contain a list of extensions (RFC 5280). +// Extensions have a type, specified by an object identifier (|ASN1_OBJECT|) and +// a byte string value, which should a DER-encoded structure whose type is +// determined by the extension type. This library represents extensions with the +// |X509_EXTENSION| type. + +// X509_EXTENSION is an |ASN1_ITEM| whose ASN.1 type is X.509 Extension (RFC +// 5280) and C type is |X509_EXTENSION*|. +DECLARE_ASN1_ITEM(X509_EXTENSION) + +// X509_EXTENSION_new returns a newly-allocated, empty |X509_EXTENSION| object +// or NULL on error. +OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_new(void); + +// X509_EXTENSION_free releases memory associated with |ex|. +OPENSSL_EXPORT void X509_EXTENSION_free(X509_EXTENSION *ex); + +// d2i_X509_EXTENSION parses up to |len| bytes from |*inp| as a DER-encoded +// X.509 Extension (RFC 5280), as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509_EXTENSION *d2i_X509_EXTENSION(X509_EXTENSION **out, + const uint8_t **inp, + long len); + +// i2d_X509_EXTENSION marshals |ex| as a DER-encoded X.509 Extension (RFC +// 5280), as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_X509_EXTENSION(const X509_EXTENSION *ex, uint8_t **outp); + +// X509_EXTENSION_dup returns a newly-allocated copy of |ex|, or NULL on error. +// This function works by serializing the structure, so if |ex| is incomplete, +// it may fail. +OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_dup(const X509_EXTENSION *ex); + +// X509_EXTENSION_create_by_NID creates a new |X509_EXTENSION| with type |nid|, +// value |data|, and critical bit |crit|. It returns an |X509_EXTENSION| on +// success, and NULL on error. |nid| should be a |NID_*| constant. +// +// If |ex| and |*ex| are both non-NULL, |*ex| is used to hold the result, +// otherwise a new object is allocated. If |ex| is non-NULL and |*ex| is NULL, +// the function sets |*ex| to point to the newly allocated result, in addition +// to returning the result. +OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_create_by_NID( + X509_EXTENSION **ex, int nid, int crit, const ASN1_OCTET_STRING *data); + +// X509_EXTENSION_create_by_OBJ behaves like |X509_EXTENSION_create_by_NID|, but +// the extension type is determined by an |ASN1_OBJECT|. +OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_create_by_OBJ( + X509_EXTENSION **ex, const ASN1_OBJECT *obj, int crit, + const ASN1_OCTET_STRING *data); + +// X509_EXTENSION_get_object returns |ex|'s extension type. This function +// returns a non-const pointer for OpenSSL compatibility, but callers should not +// mutate the result. +OPENSSL_EXPORT ASN1_OBJECT *X509_EXTENSION_get_object(const X509_EXTENSION *ex); + +// X509_EXTENSION_get_data returns |ne|'s extension value. This function returns +// a non-const pointer for OpenSSL compatibility, but callers should not mutate +// the result. +OPENSSL_EXPORT ASN1_OCTET_STRING *X509_EXTENSION_get_data( + const X509_EXTENSION *ne); + +// X509_EXTENSION_get_critical returns one if |ex| is critical and zero +// otherwise. +OPENSSL_EXPORT int X509_EXTENSION_get_critical(const X509_EXTENSION *ex); + +// X509_EXTENSION_set_object sets |ex|'s extension type to |obj|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int X509_EXTENSION_set_object(X509_EXTENSION *ex, + const ASN1_OBJECT *obj); + +// X509_EXTENSION_set_critical sets |ex| to critical if |crit| is non-zero and +// to non-critical if |crit| is zero. +OPENSSL_EXPORT int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); + +// X509_EXTENSION_set_data set's |ex|'s extension value to a copy of |data|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int X509_EXTENSION_set_data(X509_EXTENSION *ex, + const ASN1_OCTET_STRING *data); + + +// Extension lists. +// +// The following functions manipulate lists of extensions. Most of them have +// corresponding functions on the containing |X509|, |X509_CRL|, or +// |X509_REVOKED|. + +DEFINE_STACK_OF(X509_EXTENSION) +typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; + +// X509_EXTENSIONS is an |ASN1_ITEM| whose ASN.1 type is SEQUENCE of Extension +// (RFC 5280) and C type is |STACK_OF(X509_EXTENSION)*|. +DECLARE_ASN1_ITEM(X509_EXTENSIONS) + +// d2i_X509_EXTENSIONS parses up to |len| bytes from |*inp| as a DER-encoded +// SEQUENCE OF Extension (RFC 5280), as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509_EXTENSIONS *d2i_X509_EXTENSIONS(X509_EXTENSIONS **out, + const uint8_t **inp, + long len); + +// i2d_X509_EXTENSIONS marshals |alg| as a DER-encoded SEQUENCE OF Extension +// (RFC 5280), as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_X509_EXTENSIONS(const X509_EXTENSIONS *alg, + uint8_t **outp); + +// X509v3_get_ext_count returns the number of extensions in |x|. +OPENSSL_EXPORT int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); + +// X509v3_get_ext_by_NID returns the index of the first extension in |x| with +// type |nid|, or a negative number if not found. If found, callers can use +// |X509v3_get_ext| to look up the extension by index. +// +// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers +// can thus loop over all matching extensions by first passing -1 and then +// passing the previously-returned value until no match is returned. +OPENSSL_EXPORT int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, + int nid, int lastpos); + +// X509v3_get_ext_by_OBJ behaves like |X509v3_get_ext_by_NID| but looks for +// extensions matching |obj|. +OPENSSL_EXPORT int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, + const ASN1_OBJECT *obj, int lastpos); + +// X509v3_get_ext_by_critical returns the index of the first extension in |x| +// whose critical bit matches |crit|, or a negative number if no such extension +// was found. +// +// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers +// can thus loop over all matching extensions by first passing -1 and then +// passing the previously-returned value until no match is returned. +OPENSSL_EXPORT int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, + int crit, int lastpos); + +// X509v3_get_ext returns the extension in |x| at index |loc|, or NULL if |loc| +// is out of bounds. This function returns a non-const pointer for OpenSSL +// compatibility, but callers should not mutate the result. +OPENSSL_EXPORT X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, + int loc); + +// X509v3_delete_ext removes the extension in |x| at index |loc| and returns the +// removed extension, or NULL if |loc| was out of bounds. If an extension was +// returned, the caller must release it with |X509_EXTENSION_free|. +OPENSSL_EXPORT X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, + int loc); + +// X509v3_add_ext adds a copy of |ex| to the extension list in |*x|. If |*x| is +// NULL, it allocates a new |STACK_OF(X509_EXTENSION)| to hold the copy and sets +// |*x| to the new list. It returns |*x| on success and NULL on error. The +// caller retains ownership of |ex| and can release it independently of |*x|. +// +// The new extension is inserted at index |loc|, shifting extensions to the +// right. If |loc| is -1 or out of bounds, the new extension is appended to the +// list. +OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509v3_add_ext( + STACK_OF(X509_EXTENSION) **x, const X509_EXTENSION *ex, int loc); + + +// Algorithm identifiers. +// +// An |X509_ALGOR| represents an AlgorithmIdentifier structure, used in X.509 +// to represent signature algorithms and public key algorithms. + +DEFINE_STACK_OF(X509_ALGOR) + +// X509_ALGOR is an |ASN1_ITEM| whose ASN.1 type is AlgorithmIdentifier and C +// type is |X509_ALGOR*|. +DECLARE_ASN1_ITEM(X509_ALGOR) + +// X509_ALGOR_new returns a newly-allocated, empty |X509_ALGOR| object, or NULL +// on error. +OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_new(void); + +// X509_ALGOR_dup returns a newly-allocated copy of |alg|, or NULL on error. +// This function works by serializing the structure, so if |alg| is incomplete, +// it may fail. +OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_dup(const X509_ALGOR *alg); + +// X509_ALGOR_free releases memory associated with |alg|. +OPENSSL_EXPORT void X509_ALGOR_free(X509_ALGOR *alg); + +// d2i_X509_ALGOR parses up to |len| bytes from |*inp| as a DER-encoded +// AlgorithmIdentifier, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509_ALGOR *d2i_X509_ALGOR(X509_ALGOR **out, const uint8_t **inp, + long len); + +// i2d_X509_ALGOR marshals |alg| as a DER-encoded AlgorithmIdentifier, as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_X509_ALGOR(const X509_ALGOR *alg, uint8_t **outp); + +// X509_ALGOR_set0 sets |alg| to an AlgorithmIdentifier with algorithm |obj| and +// parameter determined by |param_type| and |param_value|. It returns one on +// success and zero on error. This function takes ownership of |obj| and +// |param_value| on success. +// +// If |param_type| is |V_ASN1_UNDEF|, the parameter is omitted. If |param_type| +// is zero, the parameter is left unchanged. Otherwise, |param_type| and +// |param_value| are interpreted as in |ASN1_TYPE_set|. +// +// Note omitting the parameter (|V_ASN1_UNDEF|) and encoding an explicit NULL +// value (|V_ASN1_NULL|) are different. Some algorithms require one and some the +// other. Consult the relevant specification before calling this function. The +// correct parameter for an RSASSA-PKCS1-v1_5 signature is |V_ASN1_NULL|. The +// correct one for an ECDSA or Ed25519 signature is |V_ASN1_UNDEF|. +OPENSSL_EXPORT int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *obj, + int param_type, void *param_value); + +// X509_ALGOR_get0 sets |*out_obj| to the |alg|'s algorithm. If |alg|'s +// parameter is omitted, it sets |*out_param_type| and |*out_param_value| to +// |V_ASN1_UNDEF| and NULL. Otherwise, it sets |*out_param_type| and +// |*out_param_value| to the parameter, using the same representation as +// |ASN1_TYPE_set0|. See |ASN1_TYPE_set0| and |ASN1_TYPE| for details. +// +// Callers that require the parameter in serialized form should, after checking +// for |V_ASN1_UNDEF|, use |ASN1_TYPE_set1| and |d2i_ASN1_TYPE|, rather than +// inspecting |*out_param_value|. +// +// Each of |out_obj|, |out_param_type|, and |out_param_value| may be NULL to +// ignore the output. If |out_param_type| is NULL, |out_param_value| is ignored. +// +// WARNING: If |*out_param_type| is set to |V_ASN1_UNDEF|, OpenSSL and older +// revisions of BoringSSL leave |*out_param_value| unset rather than setting it +// to NULL. Callers that support both OpenSSL and BoringSSL should not assume +// |*out_param_value| is uniformly initialized. +OPENSSL_EXPORT void X509_ALGOR_get0(const ASN1_OBJECT **out_obj, + int *out_param_type, + const void **out_param_value, + const X509_ALGOR *alg); + +// X509_ALGOR_set_md sets |alg| to the hash function |md|. Note this +// AlgorithmIdentifier represents the hash function itself, not a signature +// algorithm that uses |md|. +OPENSSL_EXPORT void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); + +// X509_ALGOR_cmp returns zero if |a| and |b| are equal, and some non-zero value +// otherwise. Note this function can only be used for equality checks, not an +// ordering. +OPENSSL_EXPORT int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b); + + +// Attributes. +// +// Unlike certificates and CRLs, CSRs use a separate Attribute structure (RFC +// 2985, RFC 2986) for extensibility. This is represented by the library as +// |X509_ATTRIBUTE|. + +DEFINE_STACK_OF(X509_ATTRIBUTE) + +// X509_ATTRIBUTE is an |ASN1_ITEM| whose ASN.1 type is Attribute (RFC 2986) and +// C type is |X509_ATTRIBUTE*|. +DECLARE_ASN1_ITEM(X509_ATTRIBUTE) + +// X509_ATTRIBUTE_new returns a newly-allocated, empty |X509_ATTRIBUTE| object, +// or NULL on error. |X509_ATTRIBUTE_set1_*| may be used to finish initializing +// it. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_new(void); + +// X509_ATTRIBUTE_dup returns a newly-allocated copy of |attr|, or NULL on +// error. This function works by serializing the structure, so if |attr| is +// incomplete, it may fail. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_dup(const X509_ATTRIBUTE *attr); + +// X509_ATTRIBUTE_free releases memory associated with |attr|. +OPENSSL_EXPORT void X509_ATTRIBUTE_free(X509_ATTRIBUTE *attr); + +// d2i_X509_ATTRIBUTE parses up to |len| bytes from |*inp| as a DER-encoded +// Attribute (RFC 2986), as described in |d2i_SAMPLE|. +OPENSSL_EXPORT X509_ATTRIBUTE *d2i_X509_ATTRIBUTE(X509_ATTRIBUTE **out, + const uint8_t **inp, + long len); + +// i2d_X509_ATTRIBUTE marshals |alg| as a DER-encoded Attribute (RFC 2986), as +// described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_X509_ATTRIBUTE(const X509_ATTRIBUTE *alg, + uint8_t **outp); + +// X509_ATTRIBUTE_create returns a newly-allocated |X509_ATTRIBUTE|, or NULL on +// error. The attribute has type |nid| and contains a single value determined by +// |attrtype| and |value|, which are interpreted as in |ASN1_TYPE_set|. Note +// this function takes ownership of |value|. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype, + void *value); + +// X509_ATTRIBUTE_create_by_NID returns a newly-allocated |X509_ATTRIBUTE| of +// type |nid|, or NULL on error. The value is determined as in +// |X509_ATTRIBUTE_set1_data|. +// +// If |attr| is non-NULL, the resulting |X509_ATTRIBUTE| is also written to +// |*attr|. If |*attr| was non-NULL when the function was called, |*attr| is +// reused instead of creating a new object. +// +// WARNING: The interpretation of |attrtype|, |data|, and |len| is complex and +// error-prone. See |X509_ATTRIBUTE_set1_data| for details. +// +// WARNING: The object reuse form is deprecated and may be removed in the +// future. It also currently incorrectly appends to the reused object's value +// set rather than overwriting it. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID( + X509_ATTRIBUTE **attr, int nid, int attrtype, const void *data, int len); + +// X509_ATTRIBUTE_create_by_OBJ behaves like |X509_ATTRIBUTE_create_by_NID| +// except the attribute's type is determined by |obj|. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ( + X509_ATTRIBUTE **attr, const ASN1_OBJECT *obj, int attrtype, + const void *data, int len); + +// X509_ATTRIBUTE_create_by_txt behaves like |X509_ATTRIBUTE_create_by_NID| +// except the attribute's type is determined by calling |OBJ_txt2obj| with +// |attrname|. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt( + X509_ATTRIBUTE **attr, const char *attrname, int type, + const unsigned char *bytes, int len); + +// X509_ATTRIBUTE_set1_object sets |attr|'s type to |obj|. It returns one on +// success and zero on error. +OPENSSL_EXPORT int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, + const ASN1_OBJECT *obj); + +// X509_ATTRIBUTE_set1_data appends a value to |attr|'s value set and returns +// one on success or zero on error. The value is determined as follows: +// +// If |attrtype| is a |MBSTRING_*| constant, the value is an ASN.1 string. The +// string is determined by decoding |len| bytes from |data| in the encoding +// specified by |attrtype|, and then re-encoding it in a form appropriate for +// |attr|'s type. If |len| is -1, |strlen(data)| is used instead. See +// |ASN1_STRING_set_by_NID| for details. +// +// Otherwise, if |len| is not -1, the value is an ASN.1 string. |attrtype| is an +// |ASN1_STRING| type value and the |len| bytes from |data| are copied as the +// type-specific representation of |ASN1_STRING|. See |ASN1_STRING| for details. +// +// WARNING: If this form is used to construct a negative INTEGER or ENUMERATED, +// |attrtype| includes the |V_ASN1_NEG| flag for |ASN1_STRING|, but the function +// forgets to clear the flag for |ASN1_TYPE|. This matches OpenSSL but is +// probably a bug. For now, do not use this form with negative values. +// +// Otherwise, if |len| is -1, the value is constructed by passing |attrtype| and +// |data| to |ASN1_TYPE_set1|. That is, |attrtype| is an |ASN1_TYPE| type value, +// and |data| is cast to the corresponding pointer type. +// +// WARNING: Despite the name, this function appends to |attr|'s value set, +// rather than overwriting it. To overwrite the value set, create a new +// |X509_ATTRIBUTE| with |X509_ATTRIBUTE_new|. +// +// WARNING: If using the |MBSTRING_*| form, pass a length rather than relying on +// |strlen|. In particular, |strlen| will not behave correctly if the input is +// |MBSTRING_BMP| or |MBSTRING_UNIV|. +// +// WARNING: This function currently misinterprets |V_ASN1_OTHER| as an +// |MBSTRING_*| constant. This matches OpenSSL but means it is impossible to +// construct a value with a non-universal tag. +OPENSSL_EXPORT int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, + const void *data, int len); + +// X509_ATTRIBUTE_get0_data returns the |idx|th value of |attr| in a +// type-specific representation to |attrtype|, or NULL if out of bounds or the +// type does not match. |attrtype| is one of the type values in |ASN1_TYPE|. On +// match, the return value uses the same representation as |ASN1_TYPE_set0|. See +// |ASN1_TYPE| for details. +OPENSSL_EXPORT void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, + int attrtype, void *unused); + +// X509_ATTRIBUTE_count returns the number of values in |attr|. +OPENSSL_EXPORT int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr); + +// X509_ATTRIBUTE_get0_object returns the type of |attr|. +OPENSSL_EXPORT ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); + +// X509_ATTRIBUTE_get0_type returns the |idx|th value in |attr|, or NULL if out +// of bounds. Note this function returns one of |attr|'s values, not the type. +OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, + int idx); + + +// SignedPublicKeyAndChallenge structures. +// +// The SignedPublicKeyAndChallenge (SPKAC) is a legacy structure to request +// certificates, primarily in the legacy HTML tag. An SPKAC structure +// is represented by a |NETSCAPE_SPKI| structure. +// +// The structure is described in +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen + +// A Netscape_spki_st, or |NETSCAPE_SPKI|, represents a +// SignedPublicKeyAndChallenge structure. Although this structure contains a +// |spkac| field of type |NETSCAPE_SPKAC|, these are misnamed. The SPKAC is the +// entire structure, not the signed portion. +struct Netscape_spki_st { + NETSCAPE_SPKAC *spkac; + X509_ALGOR *sig_algor; + ASN1_BIT_STRING *signature; +} /* NETSCAPE_SPKI */; + +// NETSCAPE_SPKI is an |ASN1_ITEM| whose ASN.1 type is +// SignedPublicKeyAndChallenge and C type is |NETSCAPE_SPKI*|. +DECLARE_ASN1_ITEM(NETSCAPE_SPKI) + +// NETSCAPE_SPKI_new returns a newly-allocated, empty |NETSCAPE_SPKI| object, or +// NULL on error. +OPENSSL_EXPORT NETSCAPE_SPKI *NETSCAPE_SPKI_new(void); + +// NETSCAPE_SPKI_free releases memory associated with |spki|. +OPENSSL_EXPORT void NETSCAPE_SPKI_free(NETSCAPE_SPKI *spki); + +// d2i_NETSCAPE_SPKI parses up to |len| bytes from |*inp| as a DER-encoded +// SignedPublicKeyAndChallenge structure, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT NETSCAPE_SPKI *d2i_NETSCAPE_SPKI(NETSCAPE_SPKI **out, + const uint8_t **inp, long len); + +// i2d_NETSCAPE_SPKI marshals |spki| as a DER-encoded +// SignedPublicKeyAndChallenge structure, as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_NETSCAPE_SPKI(const NETSCAPE_SPKI *spki, uint8_t **outp); + +// NETSCAPE_SPKI_verify checks that |spki| has a valid signature by |pkey|. It +// returns one if the signature is valid and zero otherwise. +OPENSSL_EXPORT int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *spki, EVP_PKEY *pkey); + +// NETSCAPE_SPKI_b64_decode decodes |len| bytes from |str| as a base64-encoded +// SignedPublicKeyAndChallenge structure. It returns a newly-allocated +// |NETSCAPE_SPKI| structure with the result, or NULL on error. If |len| is 0 or +// negative, the length is calculated with |strlen| and |str| must be a +// NUL-terminated C string. +OPENSSL_EXPORT NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, + ossl_ssize_t len); + +// NETSCAPE_SPKI_b64_encode encodes |spki| as a base64-encoded +// SignedPublicKeyAndChallenge structure. It returns a newly-allocated +// NUL-terminated C string with the result, or NULL on error. The caller must +// release the memory with |OPENSSL_free| when done. +OPENSSL_EXPORT char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki); + +// NETSCAPE_SPKI_get_pubkey decodes and returns the public key in |spki| as an +// |EVP_PKEY|, or NULL on error. The caller takes ownership of the resulting +// pointer and must call |EVP_PKEY_free| when done. +OPENSSL_EXPORT EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *spki); + +// NETSCAPE_SPKI_set_pubkey sets |spki|'s public key to |pkey|. It returns one +// on success or zero on error. This function does not take ownership of |pkey|, +// so the caller may continue to manage its lifetime independently of |spki|. +OPENSSL_EXPORT int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *spki, + EVP_PKEY *pkey); + +// NETSCAPE_SPKI_sign signs |spki| with |pkey| and replaces the signature +// algorithm and signature fields. It returns the length of the signature on +// success and zero on error. This function uses digest algorithm |md|, or +// |pkey|'s default if NULL. Other signing parameters use |pkey|'s defaults. +OPENSSL_EXPORT int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *spki, EVP_PKEY *pkey, + const EVP_MD *md); + +// A Netscape_spkac_st, or |NETSCAPE_SPKAC|, represents a PublicKeyAndChallenge +// structure. This type is misnamed. The full SPKAC includes the signature, +// which is represented with the |NETSCAPE_SPKI| type. +struct Netscape_spkac_st { + X509_PUBKEY *pubkey; + ASN1_IA5STRING *challenge; +} /* NETSCAPE_SPKAC */; + +// NETSCAPE_SPKAC is an |ASN1_ITEM| whose ASN.1 type is PublicKeyAndChallenge +// and C type is |NETSCAPE_SPKAC*|. +DECLARE_ASN1_ITEM(NETSCAPE_SPKAC) + +// NETSCAPE_SPKAC_new returns a newly-allocated, empty |NETSCAPE_SPKAC| object, +// or NULL on error. +OPENSSL_EXPORT NETSCAPE_SPKAC *NETSCAPE_SPKAC_new(void); + +// NETSCAPE_SPKAC_free releases memory associated with |spkac|. +OPENSSL_EXPORT void NETSCAPE_SPKAC_free(NETSCAPE_SPKAC *spkac); + +// d2i_NETSCAPE_SPKAC parses up to |len| bytes from |*inp| as a DER-encoded +// PublicKeyAndChallenge structure, as described in |d2i_SAMPLE|. +OPENSSL_EXPORT NETSCAPE_SPKAC *d2i_NETSCAPE_SPKAC(NETSCAPE_SPKAC **out, + const uint8_t **inp, + long len); + +// i2d_NETSCAPE_SPKAC marshals |spkac| as a DER-encoded PublicKeyAndChallenge +// structure, as described in |i2d_SAMPLE|. +OPENSSL_EXPORT int i2d_NETSCAPE_SPKAC(const NETSCAPE_SPKAC *spkac, + uint8_t **outp); + + +// Printing functions. +// +// The following functions output human-readable representations of +// X.509-related structures. They should only be used for debugging or logging +// and not parsed programmatically. In many cases, the outputs are ambiguous, so +// attempting to parse them can lead to string injection vulnerabilities. + +// The following flags control |X509_print_ex| and |X509_REQ_print_ex|. + +// X509_FLAG_COMPAT disables all flags. It additionally causes names to be +// printed with a 16-byte indent. +#define X509_FLAG_COMPAT 0 + +// X509_FLAG_NO_HEADER skips a header identifying the type of object printed. +#define X509_FLAG_NO_HEADER 1L + +// X509_FLAG_NO_VERSION skips printing the X.509 version number. +#define X509_FLAG_NO_VERSION (1L << 1) + +// X509_FLAG_NO_SERIAL skips printing the serial number. It is ignored in +// |X509_REQ_print_fp|. +#define X509_FLAG_NO_SERIAL (1L << 2) + +// X509_FLAG_NO_SIGNAME skips printing the signature algorithm in the +// TBSCertificate. It is ignored in |X509_REQ_print_fp|. +#define X509_FLAG_NO_SIGNAME (1L << 3) + +// X509_FLAG_NO_ISSUER skips printing the issuer. +#define X509_FLAG_NO_ISSUER (1L << 4) + +// X509_FLAG_NO_VALIDITY skips printing the notBefore and notAfter times. It is +// ignored in |X509_REQ_print_fp|. +#define X509_FLAG_NO_VALIDITY (1L << 5) + +// X509_FLAG_NO_SUBJECT skips printing the subject. +#define X509_FLAG_NO_SUBJECT (1L << 6) + +// X509_FLAG_NO_PUBKEY skips printing the public key. +#define X509_FLAG_NO_PUBKEY (1L << 7) + +// X509_FLAG_NO_EXTENSIONS skips printing the extension list. It is ignored in +// |X509_REQ_print_fp|. CSRs instead have attributes, which is controlled by +// |X509_FLAG_NO_ATTRIBUTES|. +#define X509_FLAG_NO_EXTENSIONS (1L << 8) + +// X509_FLAG_NO_SIGDUMP skips printing the signature and outer signature +// algorithm. +#define X509_FLAG_NO_SIGDUMP (1L << 9) + +// X509_FLAG_NO_AUX skips printing auxiliary properties. (See |d2i_X509_AUX| and +// related functions.) +#define X509_FLAG_NO_AUX (1L << 10) + +// X509_FLAG_NO_ATTRIBUTES skips printing CSR attributes. It does nothing for +// certificates and CRLs. +#define X509_FLAG_NO_ATTRIBUTES (1L << 11) + +// X509_FLAG_NO_IDS skips printing the issuerUniqueID and subjectUniqueID in a +// certificate. It is ignored in |X509_REQ_print_fp|. +#define X509_FLAG_NO_IDS (1L << 12) + +// X509_print_ex writes a human-readable representation of |x| to |bp|. It +// returns one on success and zero on error. |nmflags| is the flags parameter +// for |X509_NAME_print_ex| when printing the subject and issuer. |cflag| should +// be some combination of the |X509_FLAG_*| constants. +OPENSSL_EXPORT int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag, + unsigned long cflag); + +// X509_print_ex_fp behaves like |X509_print_ex| but writes to |fp|. +OPENSSL_EXPORT int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, + unsigned long cflag); + +// X509_print calls |X509_print_ex| with |XN_FLAG_COMPAT| and |X509_FLAG_COMPAT| +// flags. +OPENSSL_EXPORT int X509_print(BIO *bp, X509 *x); + +// X509_print_fp behaves like |X509_print| but writes to |fp|. +OPENSSL_EXPORT int X509_print_fp(FILE *fp, X509 *x); + +// X509_CRL_print writes a human-readable representation of |x| to |bp|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int X509_CRL_print(BIO *bp, X509_CRL *x); + +// X509_CRL_print_fp behaves like |X509_CRL_print| but writes to |fp|. +OPENSSL_EXPORT int X509_CRL_print_fp(FILE *fp, X509_CRL *x); + +// X509_REQ_print_ex writes a human-readable representation of |x| to |bp|. It +// returns one on success and zero on error. |nmflags| is the flags parameter +// for |X509_NAME_print_ex|, when printing the subject. |cflag| should be some +// combination of the |X509_FLAG_*| constants. +OPENSSL_EXPORT int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, + unsigned long cflag); + +// X509_REQ_print calls |X509_REQ_print_ex| with |XN_FLAG_COMPAT| and +// |X509_FLAG_COMPAT| flags. +OPENSSL_EXPORT int X509_REQ_print(BIO *bp, X509_REQ *req); + +// X509_REQ_print_fp behaves like |X509_REQ_print| but writes to |fp|. +OPENSSL_EXPORT int X509_REQ_print_fp(FILE *fp, X509_REQ *req); + +// The following flags are control |X509_NAME_print_ex|. They must not collide +// with |ASN1_STRFLGS_*|. +// +// TODO(davidben): This is far, far too many options and most of them are +// useless. Trim this down. + +// XN_FLAG_COMPAT prints with |X509_NAME_print|'s format and return value +// convention. +#define XN_FLAG_COMPAT 0 + +// XN_FLAG_SEP_MASK determines the separators to use between attributes. +#define XN_FLAG_SEP_MASK (0xf << 16) + +// XN_FLAG_SEP_COMMA_PLUS separates RDNs with "," and attributes within an RDN +// with "+", as in RFC 2253. +#define XN_FLAG_SEP_COMMA_PLUS (1 << 16) + +// XN_FLAG_SEP_CPLUS_SPC behaves like |XN_FLAG_SEP_COMMA_PLUS| but adds spaces +// between the separators. +#define XN_FLAG_SEP_CPLUS_SPC (2 << 16) + +// XN_FLAG_SEP_SPLUS_SPC separates RDNs with "; " and attributes within an RDN +// with " + ". +#define XN_FLAG_SEP_SPLUS_SPC (3 << 16) + +// XN_FLAG_SEP_MULTILINE prints each attribute on one line. +#define XN_FLAG_SEP_MULTILINE (4 << 16) + +// XN_FLAG_DN_REV prints RDNs in reverse, from least significant to most +// significant, as RFC 2253. +#define XN_FLAG_DN_REV (1 << 20) + +// XN_FLAG_FN_MASK determines how attribute types are displayed. +#define XN_FLAG_FN_MASK (0x3 << 21) + +// XN_FLAG_FN_SN uses the attribute type's short name, when available. +#define XN_FLAG_FN_SN 0 + +// XN_FLAG_SPC_EQ wraps the "=" operator with spaces when printing attributes. +#define XN_FLAG_SPC_EQ (1 << 23) + +// XN_FLAG_DUMP_UNKNOWN_FIELDS causes unknown attribute types to be printed in +// hex, as in RFC 2253. +#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) + +// XN_FLAG_RFC2253 prints like RFC 2253. +#define XN_FLAG_RFC2253 \ + (ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_DN_REV | \ + XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS) + +// XN_FLAG_ONELINE prints a one-line representation of the name. +#define XN_FLAG_ONELINE \ + (ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC | \ + XN_FLAG_SPC_EQ | XN_FLAG_FN_SN) + +// X509_NAME_print_ex writes a human-readable representation of |nm| to |out|. +// Each line of output is indented by |indent| spaces. It returns the number of +// bytes written on success, and -1 on error. If |out| is NULL, it returns the +// number of bytes it would have written but does not write anything. |flags| +// should be some combination of |XN_FLAG_*| and |ASN1_STRFLGS_*| values and +// determines the output. If unsure, use |XN_FLAG_RFC2253|. +// +// If |flags| is |XN_FLAG_COMPAT|, or zero, this function calls +// |X509_NAME_print| instead. In that case, it returns one on success, rather +// than the output length. +OPENSSL_EXPORT int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, + unsigned long flags); + +// X509_NAME_print prints a human-readable representation of |name| to |bp|. It +// returns one on success and zero on error. |obase| is ignored. +// +// This function outputs a legacy format that does not correctly handle string +// encodings and other cases. Prefer |X509_NAME_print_ex| if printing a name for +// debugging purposes. +OPENSSL_EXPORT int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase); + +// X509_NAME_oneline writes a human-readable representation to |name| to a +// buffer as a NUL-terminated C string. +// +// If |buf| is NULL, returns a newly-allocated buffer containing the result on +// success, or NULL on error. The buffer must be released with |OPENSSL_free| +// when done. +// +// If |buf| is non-NULL, at most |size| bytes of output are written to |buf| +// instead. |size| includes the trailing NUL. The function then returns |buf| on +// success or NULL on error. If the output does not fit in |size| bytes, the +// output is silently truncated at an attribute boundary. +// +// This function outputs a legacy format that does not correctly handle string +// encodings and other cases. Prefer |X509_NAME_print_ex| if printing a name for +// debugging purposes. +OPENSSL_EXPORT char *X509_NAME_oneline(const X509_NAME *name, char *buf, int size); + +// X509_NAME_print_ex_fp behaves like |X509_NAME_print_ex| but writes to |fp|. +OPENSSL_EXPORT int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, + int indent, unsigned long flags); + +// X509_signature_dump writes a human-readable representation of |sig| to |bio|, +// indented with |indent| spaces. It returns one on success and zero on error. +OPENSSL_EXPORT int X509_signature_dump(BIO *bio, const ASN1_STRING *sig, + int indent); + +// X509_signature_print writes a human-readable representation of |alg| and +// |sig| to |bio|. It returns one on success and zero on error. +OPENSSL_EXPORT int X509_signature_print(BIO *bio, const X509_ALGOR *alg, + const ASN1_STRING *sig); + + +// Convenience functions. + +// X509_pubkey_digest hashes the contents of the BIT STRING in |x509|'s +// subjectPublicKeyInfo field with |md| and writes the result to |out|. +// |EVP_MD_CTX_size| bytes are written, which is at most |EVP_MAX_MD_SIZE|. If +// |out_len| is not NULL, |*out_len| is set to the number of bytes written. This +// function returns one on success and zero on error. +// +// This hash omits the BIT STRING tag, length, and number of unused bits. It +// also omits the AlgorithmIdentifier which describes the key type. It +// corresponds to the OCSP KeyHash definition and is not suitable for other +// purposes. +OPENSSL_EXPORT int X509_pubkey_digest(const X509 *x509, const EVP_MD *md, + uint8_t *out, unsigned *out_len); + +// X509_digest hashes |x509|'s DER encoding with |md| and writes the result to +// |out|. |EVP_MD_CTX_size| bytes are written, which is at most +// |EVP_MAX_MD_SIZE|. If |out_len| is not NULL, |*out_len| is set to the number +// of bytes written. This function returns one on success and zero on error. +// Note this digest covers the entire certificate, not just the signed portion. +OPENSSL_EXPORT int X509_digest(const X509 *x509, const EVP_MD *md, uint8_t *out, + unsigned *out_len); + +// X509_CRL_digest hashes |crl|'s DER encoding with |md| and writes the result +// to |out|. |EVP_MD_CTX_size| bytes are written, which is at most +// |EVP_MAX_MD_SIZE|. If |out_len| is not NULL, |*out_len| is set to the number +// of bytes written. This function returns one on success and zero on error. +// Note this digest covers the entire CRL, not just the signed portion. +OPENSSL_EXPORT int X509_CRL_digest(const X509_CRL *crl, const EVP_MD *md, + uint8_t *out, unsigned *out_len); + +// X509_REQ_digest hashes |req|'s DER encoding with |md| and writes the result +// to |out|. |EVP_MD_CTX_size| bytes are written, which is at most +// |EVP_MAX_MD_SIZE|. If |out_len| is not NULL, |*out_len| is set to the number +// of bytes written. This function returns one on success and zero on error. +// Note this digest covers the entire certificate request, not just the signed +// portion. +OPENSSL_EXPORT int X509_REQ_digest(const X509_REQ *req, const EVP_MD *md, + uint8_t *out, unsigned *out_len); + +// X509_NAME_digest hashes |name|'s DER encoding with |md| and writes the result +// to |out|. |EVP_MD_CTX_size| bytes are written, which is at most +// |EVP_MAX_MD_SIZE|. If |out_len| is not NULL, |*out_len| is set to the number +// of bytes written. This function returns one on success and zero on error. +OPENSSL_EXPORT int X509_NAME_digest(const X509_NAME *name, const EVP_MD *md, + uint8_t *out, unsigned *out_len); + +// The following functions behave like the corresponding unsuffixed |d2i_*| +// functions, but read the result from |bp| instead. Callers using these +// functions with memory |BIO|s to parse structures already in memory should use +// |d2i_*| instead. +OPENSSL_EXPORT X509 *d2i_X509_bio(BIO *bp, X509 **x509); +OPENSSL_EXPORT X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl); +OPENSSL_EXPORT X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req); +OPENSSL_EXPORT RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa); +OPENSSL_EXPORT RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa); +OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa); +OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); +OPENSSL_EXPORT DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); +OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey); +OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey); +OPENSSL_EXPORT X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8); +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio( + BIO *bp, PKCS8_PRIV_KEY_INFO **p8inf); +OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); +OPENSSL_EXPORT DH *d2i_DHparams_bio(BIO *bp, DH **dh); + +// d2i_PrivateKey_bio behaves like |d2i_AutoPrivateKey|, but reads from |bp| +// instead. +OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); + +// The following functions behave like the corresponding unsuffixed |i2d_*| +// functions, but write the result to |bp|. They return one on success and zero +// on error. Callers using them with memory |BIO|s to encode structures to +// memory should use |i2d_*| directly instead. +OPENSSL_EXPORT int i2d_X509_bio(BIO *bp, X509 *x509); +OPENSSL_EXPORT int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl); +OPENSSL_EXPORT int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req); +OPENSSL_EXPORT int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa); +OPENSSL_EXPORT int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa); +OPENSSL_EXPORT int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa); +OPENSSL_EXPORT int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); +OPENSSL_EXPORT int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); +OPENSSL_EXPORT int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey); +OPENSSL_EXPORT int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey); +OPENSSL_EXPORT int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8); +OPENSSL_EXPORT int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO *p8inf); +OPENSSL_EXPORT int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); +OPENSSL_EXPORT int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); +OPENSSL_EXPORT int i2d_DHparams_bio(BIO *bp, const DH *dh); + +// i2d_PKCS8PrivateKeyInfo_bio encodes |key| as a PKCS#8 PrivateKeyInfo +// structure (see |EVP_marshal_private_key|) and writes the result to |bp|. It +// returns one on success and zero on error. +OPENSSL_EXPORT int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key); + +// The following functions behave like the corresponding |d2i_*_bio| functions, +// but read from |fp| instead. +OPENSSL_EXPORT X509 *d2i_X509_fp(FILE *fp, X509 **x509); +OPENSSL_EXPORT X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl); +OPENSSL_EXPORT X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req); +OPENSSL_EXPORT RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa); +OPENSSL_EXPORT RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa); +OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa); +OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); +OPENSSL_EXPORT DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); +OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey); +OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey); +OPENSSL_EXPORT X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8); +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp( + FILE *fp, PKCS8_PRIV_KEY_INFO **p8inf); +OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a); +OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); + +// The following functions behave like the corresponding |i2d_*_bio| functions, +// but write to |fp| instead. +OPENSSL_EXPORT int i2d_X509_fp(FILE *fp, X509 *x509); +OPENSSL_EXPORT int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl); +OPENSSL_EXPORT int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req); +OPENSSL_EXPORT int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa); +OPENSSL_EXPORT int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa); +OPENSSL_EXPORT int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa); +OPENSSL_EXPORT int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); +OPENSSL_EXPORT int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); +OPENSSL_EXPORT int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey); +OPENSSL_EXPORT int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey); +OPENSSL_EXPORT int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8); +OPENSSL_EXPORT int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO *p8inf); +OPENSSL_EXPORT int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key); +OPENSSL_EXPORT int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey); +OPENSSL_EXPORT int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey); + +// X509_find_by_issuer_and_serial returns the first |X509| in |sk| whose issuer +// and serial are |name| and |serial|, respectively. If no match is found, it +// returns NULL. +OPENSSL_EXPORT X509 *X509_find_by_issuer_and_serial(const STACK_OF(X509) *sk, + X509_NAME *name, + const ASN1_INTEGER *serial); + +// X509_find_by_subject returns the first |X509| in |sk| whose subject is +// |name|. If no match is found, it returns NULL. +OPENSSL_EXPORT X509 *X509_find_by_subject(const STACK_OF(X509) *sk, + X509_NAME *name); + +// X509_cmp_time compares |s| against |*t|. On success, it returns a negative +// number if |s| <= |*t| and a positive number if |s| > |*t|. On error, it +// returns zero. If |t| is NULL, it uses the current time instead of |*t|. +// +// WARNING: Unlike most comparison functions, this function returns zero on +// error, not equality. +OPENSSL_EXPORT int X509_cmp_time(const ASN1_TIME *s, time_t *t); + +// X509_cmp_time_posix compares |s| against |t|. On success, it returns a +// negative number if |s| <= |t| and a positive number if |s| > |t|. On error, +// it returns zero. +// +// WARNING: Unlike most comparison functions, this function returns zero on +// error, not equality. +OPENSSL_EXPORT int X509_cmp_time_posix(const ASN1_TIME *s, int64_t t); + +// X509_cmp_current_time behaves like |X509_cmp_time| but compares |s| against +// the current time. +OPENSSL_EXPORT int X509_cmp_current_time(const ASN1_TIME *s); + +// X509_time_adj calls |X509_time_adj_ex| with |offset_day| equal to zero. +OPENSSL_EXPORT ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, + time_t *t); + +// X509_time_adj_ex behaves like |ASN1_TIME_adj|, but adds an offset to |*t|. If +// |t| is NULL, it uses the current time instead of |*t|. +OPENSSL_EXPORT ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, int offset_day, + long offset_sec, time_t *t); + +// X509_gmtime_adj behaves like |X509_time_adj_ex| but adds |offset_sec| to the +// current time. +OPENSSL_EXPORT ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long offset_sec); + + +// ex_data functions. +// +// See |ex_data.h| for details. + +OPENSSL_EXPORT int X509_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int X509_set_ex_data(X509 *r, int idx, void *arg); +OPENSSL_EXPORT void *X509_get_ex_data(X509 *r, int idx); + +OPENSSL_EXPORT int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, + void *data); +OPENSSL_EXPORT void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx); + + +// Deprecated functions. + +// X509_get_notBefore returns |x509|'s notBefore time. Note this function is not +// const-correct for legacy reasons. Use |X509_get0_notBefore| or +// |X509_getm_notBefore| instead. +OPENSSL_EXPORT ASN1_TIME *X509_get_notBefore(const X509 *x509); + +// X509_get_notAfter returns |x509|'s notAfter time. Note this function is not +// const-correct for legacy reasons. Use |X509_get0_notAfter| or +// |X509_getm_notAfter| instead. +OPENSSL_EXPORT ASN1_TIME *X509_get_notAfter(const X509 *x509); + +// X509_set_notBefore calls |X509_set1_notBefore|. Use |X509_set1_notBefore| +// instead. +OPENSSL_EXPORT int X509_set_notBefore(X509 *x509, const ASN1_TIME *tm); + +// X509_set_notAfter calls |X509_set1_notAfter|. Use |X509_set1_notAfter| +// instead. +OPENSSL_EXPORT int X509_set_notAfter(X509 *x509, const ASN1_TIME *tm); + +// X509_CRL_get_lastUpdate returns a mutable pointer to |crl|'s thisUpdate time. +// The OpenSSL API refers to this field as lastUpdate. +// +// Use |X509_CRL_get0_lastUpdate| or |X509_CRL_set1_lastUpdate| instead. +OPENSSL_EXPORT ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl); + +// X509_CRL_get_nextUpdate returns a mutable pointer to |crl|'s nextUpdate time, +// or NULL if |crl| has none. Use |X509_CRL_get0_nextUpdate| or +// |X509_CRL_set1_nextUpdate| instead. +OPENSSL_EXPORT ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl); + +// X509_extract_key is a legacy alias to |X509_get_pubkey|. Use +// |X509_get_pubkey| instead. +#define X509_extract_key(x) X509_get_pubkey(x) + +// X509_REQ_extract_key is a legacy alias for |X509_REQ_get_pubkey|. +#define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) + +// X509_name_cmp is a legacy alias for |X509_NAME_cmp|. +#define X509_name_cmp(a, b) X509_NAME_cmp((a), (b)) + +// The following symbols are deprecated aliases to |X509_CRL_set1_*|. +#define X509_CRL_set_lastUpdate X509_CRL_set1_lastUpdate +#define X509_CRL_set_nextUpdate X509_CRL_set1_nextUpdate + +// X509_get_serialNumber returns a mutable pointer to |x509|'s serial number. +// Prefer |X509_get0_serialNumber|. +OPENSSL_EXPORT ASN1_INTEGER *X509_get_serialNumber(X509 *x509); + +// X509_NAME_get_text_by_OBJ finds the first attribute with type |obj| in +// |name|. If found, it ignores the value's ASN.1 type, writes the raw +// |ASN1_STRING| representation to |buf|, followed by a NUL byte, and +// returns the number of bytes in output, excluding the NUL byte. +// +// This function writes at most |len| bytes, including the NUL byte. If |len| is +// not large enough, it silently truncates the output to fit. If |buf| is NULL, +// it instead writes enough and returns the number of bytes in the output, +// excluding the NUL byte. +// +// WARNING: Do not use this function. It does not return enough information for +// the caller to correctly interpret its output. The attribute value may be of +// any type, including one of several ASN.1 string encodings, but this function +// only outputs the raw |ASN1_STRING| representation. See +// https://crbug.com/boringssl/436. +OPENSSL_EXPORT int X509_NAME_get_text_by_OBJ(const X509_NAME *name, + const ASN1_OBJECT *obj, char *buf, + int len); + +// X509_NAME_get_text_by_NID behaves like |X509_NAME_get_text_by_OBJ| except it +// finds an attribute of type |nid|, which should be one of the |NID_*| +// constants. +OPENSSL_EXPORT int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid, + char *buf, int len); + + +// Private structures. + +struct X509_algor_st { + ASN1_OBJECT *algorithm; + ASN1_TYPE *parameter; +} /* X509_ALGOR */; + + +// Functions below this point have not yet been organized into sections. + +#define X509_FILETYPE_PEM 1 +#define X509_FILETYPE_ASN1 2 +#define X509_FILETYPE_DEFAULT 3 + +#define X509v3_KU_DIGITAL_SIGNATURE 0x0080 +#define X509v3_KU_NON_REPUDIATION 0x0040 +#define X509v3_KU_KEY_ENCIPHERMENT 0x0020 +#define X509v3_KU_DATA_ENCIPHERMENT 0x0010 +#define X509v3_KU_KEY_AGREEMENT 0x0008 +#define X509v3_KU_KEY_CERT_SIGN 0x0004 +#define X509v3_KU_CRL_SIGN 0x0002 +#define X509v3_KU_ENCIPHER_ONLY 0x0001 +#define X509v3_KU_DECIPHER_ONLY 0x8000 +#define X509v3_KU_UNDEF 0xffff + +// This stuff is certificate "auxiliary info" +// it contains details which are useful in certificate +// stores and databases. When used this is tagged onto +// the end of the certificate itself + +DECLARE_STACK_OF(DIST_POINT) +DECLARE_STACK_OF(GENERAL_NAME) + +// This is used for a table of trust checking functions + +struct x509_trust_st { + int trust; + int flags; + int (*check_trust)(struct x509_trust_st *, X509 *, int); + char *name; + int arg1; + void *arg2; +} /* X509_TRUST */; + +DEFINE_STACK_OF(X509_TRUST) + +// standard trust ids + +#define X509_TRUST_DEFAULT (-1) // Only valid in purpose settings + +#define X509_TRUST_COMPAT 1 +#define X509_TRUST_SSL_CLIENT 2 +#define X509_TRUST_SSL_SERVER 3 +#define X509_TRUST_EMAIL 4 +#define X509_TRUST_OBJECT_SIGN 5 +#define X509_TRUST_OCSP_SIGN 6 +#define X509_TRUST_OCSP_REQUEST 7 +#define X509_TRUST_TSA 8 + +// Keep these up to date! +#define X509_TRUST_MIN 1 +#define X509_TRUST_MAX 8 + + +// trust_flags values +#define X509_TRUST_DYNAMIC 1 +#define X509_TRUST_DYNAMIC_NAME 2 + +// check_trust return codes + +#define X509_TRUST_TRUSTED 1 +#define X509_TRUST_REJECTED 2 +#define X509_TRUST_UNTRUSTED 3 + +DEFINE_STACK_OF(X509_REVOKED) + +DECLARE_STACK_OF(GENERAL_NAMES) + +struct private_key_st { + int version; + // The PKCS#8 data types + X509_ALGOR *enc_algor; + ASN1_OCTET_STRING *enc_pkey; // encrypted pub key + + // When decrypted, the following will not be NULL + EVP_PKEY *dec_pkey; + + // used to encrypt and decrypt + int key_length; + char *key_data; + int key_free; // true if we should auto free key_data + + // expanded version of 'enc_algor' + EVP_CIPHER_INFO cipher; +} /* X509_PKEY */; + +struct X509_info_st { + X509 *x509; + X509_CRL *crl; + X509_PKEY *x_pkey; + + EVP_CIPHER_INFO enc_cipher; + int enc_len; + char *enc_data; + +} /* X509_INFO */; + +DEFINE_STACK_OF(X509_INFO) + +// X509_get_pathlen returns path length constraint from the basic constraints +// extension in |x509|. (See RFC 5280, section 4.2.1.9.) It returns -1 if the +// constraint is not present, or if some extension in |x509| was invalid. +// +// Note that decoding an |X509| object will not check for invalid extensions. To +// detect the error case, call |X509_get_extensions_flags| and check the +// |EXFLAG_INVALID| bit. +OPENSSL_EXPORT long X509_get_pathlen(X509 *x509); + +// X509_SIG_get0 sets |*out_alg| and |*out_digest| to non-owning pointers to +// |sig|'s algorithm and digest fields, respectively. Either |out_alg| and +// |out_digest| may be NULL to skip those fields. +OPENSSL_EXPORT void X509_SIG_get0(const X509_SIG *sig, + const X509_ALGOR **out_alg, + const ASN1_OCTET_STRING **out_digest); + +// X509_SIG_getm behaves like |X509_SIG_get0| but returns mutable pointers. +OPENSSL_EXPORT void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **out_alg, + ASN1_OCTET_STRING **out_digest); + +// X509_verify_cert_error_string returns |err| as a human-readable string, where +// |err| should be one of the |X509_V_*| values. If |err| is unknown, it returns +// a default description. +OPENSSL_EXPORT const char *X509_verify_cert_error_string(long err); + +// X509_REVOKED_dup returns a newly-allocated copy of |rev|, or NULL on error. +// This function works by serializing the structure, so if |rev| is incomplete, +// it may fail. +OPENSSL_EXPORT X509_REVOKED *X509_REVOKED_dup(const X509_REVOKED *rev); + +OPENSSL_EXPORT const char *X509_get_default_cert_area(void); +OPENSSL_EXPORT const char *X509_get_default_cert_dir(void); +OPENSSL_EXPORT const char *X509_get_default_cert_file(void); +OPENSSL_EXPORT const char *X509_get_default_cert_dir_env(void); +OPENSSL_EXPORT const char *X509_get_default_cert_file_env(void); +OPENSSL_EXPORT const char *X509_get_default_private_dir(void); + +DECLARE_ASN1_FUNCTIONS_const(X509_PUBKEY) + +// X509_PUBKEY_set serializes |pkey| into a newly-allocated |X509_PUBKEY| +// structure. On success, it frees |*x|, sets |*x| to the new object, and +// returns one. Otherwise, it returns zero. +OPENSSL_EXPORT int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); + +// X509_PUBKEY_get decodes the public key in |key| and returns an |EVP_PKEY| on +// success, or NULL on error. The caller must release the result with +// |EVP_PKEY_free| when done. The |EVP_PKEY| is cached in |key|, so callers must +// not mutate the result. +OPENSSL_EXPORT EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key); + +DECLARE_ASN1_FUNCTIONS_const(X509_SIG) + +OPENSSL_EXPORT int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj); +OPENSSL_EXPORT int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj); +OPENSSL_EXPORT void X509_trust_clear(X509 *x); +OPENSSL_EXPORT void X509_reject_clear(X509 *x); + + +OPENSSL_EXPORT int X509_TRUST_set(int *t, int trust); + +DECLARE_ASN1_FUNCTIONS_const(X509_REVOKED) + +OPENSSL_EXPORT int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); +OPENSSL_EXPORT int X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret, + ASN1_INTEGER *serial); +OPENSSL_EXPORT int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, + X509 *x); + +OPENSSL_EXPORT X509_PKEY *X509_PKEY_new(void); +OPENSSL_EXPORT void X509_PKEY_free(X509_PKEY *a); + +OPENSSL_EXPORT X509_INFO *X509_INFO_new(void); +OPENSSL_EXPORT void X509_INFO_free(X509_INFO *a); + +OPENSSL_EXPORT int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, + unsigned char *md, unsigned int *len); + +OPENSSL_EXPORT int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, + void *data, unsigned char *md, + unsigned int *len); + +OPENSSL_EXPORT int ASN1_item_verify(const ASN1_ITEM *it, + const X509_ALGOR *algor1, + const ASN1_BIT_STRING *signature, + void *data, EVP_PKEY *pkey); + +OPENSSL_EXPORT int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *data, + EVP_PKEY *pkey, const EVP_MD *type); +OPENSSL_EXPORT int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *asn, + EVP_MD_CTX *ctx); + +OPENSSL_EXPORT int X509_CRL_sort(X509_CRL *crl); + +// X509_REVOKED_get0_serialNumber returns the serial number of the certificate +// revoked by |revoked|. +OPENSSL_EXPORT const ASN1_INTEGER *X509_REVOKED_get0_serialNumber( + const X509_REVOKED *revoked); + +// X509_REVOKED_set_serialNumber sets |revoked|'s serial number to |serial|. It +// returns one on success or zero on error. +OPENSSL_EXPORT int X509_REVOKED_set_serialNumber(X509_REVOKED *revoked, + const ASN1_INTEGER *serial); + +// X509_REVOKED_get0_revocationDate returns the revocation time of the +// certificate revoked by |revoked|. +OPENSSL_EXPORT const ASN1_TIME *X509_REVOKED_get0_revocationDate( + const X509_REVOKED *revoked); + +// X509_REVOKED_set_revocationDate sets |revoked|'s revocation time to |tm|. It +// returns one on success or zero on error. +OPENSSL_EXPORT int X509_REVOKED_set_revocationDate(X509_REVOKED *revoked, + const ASN1_TIME *tm); + +// X509_REVOKED_get0_extensions returns |r|'s extensions list, or NULL if |r| +// omits it. +OPENSSL_EXPORT const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions( + const X509_REVOKED *r); + +OPENSSL_EXPORT X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, + EVP_PKEY *skey, const EVP_MD *md, + unsigned int flags); + +OPENSSL_EXPORT int X509_REQ_check_private_key(X509_REQ *x509, EVP_PKEY *pkey); + +OPENSSL_EXPORT int X509_check_private_key(X509 *x509, const EVP_PKEY *pkey); + +OPENSSL_EXPORT int X509_issuer_name_cmp(const X509 *a, const X509 *b); +OPENSSL_EXPORT unsigned long X509_issuer_name_hash(X509 *a); + +OPENSSL_EXPORT int X509_subject_name_cmp(const X509 *a, const X509 *b); +OPENSSL_EXPORT unsigned long X509_subject_name_hash(X509 *x); + +OPENSSL_EXPORT unsigned long X509_issuer_name_hash_old(X509 *a); +OPENSSL_EXPORT unsigned long X509_subject_name_hash_old(X509 *x); + +OPENSSL_EXPORT int X509_cmp(const X509 *a, const X509 *b); +OPENSSL_EXPORT int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); +OPENSSL_EXPORT unsigned long X509_NAME_hash(X509_NAME *x); +OPENSSL_EXPORT unsigned long X509_NAME_hash_old(X509_NAME *x); + +OPENSSL_EXPORT int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); +OPENSSL_EXPORT int X509_CRL_match(const X509_CRL *a, const X509_CRL *b); + +// X509_get_ext_d2i behaves like |X509V3_get_d2i| but looks for the extension in +// |x509|'s extension list. +// +// WARNING: This function is difficult to use correctly. See the documentation +// for |X509V3_get_d2i| for details. +OPENSSL_EXPORT void *X509_get_ext_d2i(const X509 *x509, int nid, + int *out_critical, int *out_idx); + +// X509_add1_ext_i2d behaves like |X509V3_add1_i2d| but adds the extension to +// |x|'s extension list. +// +// WARNING: This function may return zero or -1 on error. The caller must also +// ensure |value|'s type matches |nid|. See the documentation for +// |X509V3_add1_i2d| for details. +OPENSSL_EXPORT int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags); + +// X509_CRL_get_ext_d2i behaves like |X509V3_get_d2i| but looks for the +// extension in |crl|'s extension list. +// +// WARNING: This function is difficult to use correctly. See the documentation +// for |X509V3_get_d2i| for details. +OPENSSL_EXPORT void *X509_CRL_get_ext_d2i(const X509_CRL *crl, int nid, + int *out_critical, int *out_idx); + +// X509_CRL_add1_ext_i2d behaves like |X509V3_add1_i2d| but adds the extension +// to |x|'s extension list. +// +// WARNING: This function may return zero or -1 on error. The caller must also +// ensure |value|'s type matches |nid|. See the documentation for +// |X509V3_add1_i2d| for details. +OPENSSL_EXPORT int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, + int crit, unsigned long flags); + +// X509_REVOKED_get_ext_count returns the number of extensions in |x|. +OPENSSL_EXPORT int X509_REVOKED_get_ext_count(const X509_REVOKED *x); + +// X509_REVOKED_get_ext_by_NID behaves like |X509v3_get_ext_by_NID| but searches +// for extensions in |x|. +OPENSSL_EXPORT int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, + int lastpos); + +// X509_REVOKED_get_ext_by_OBJ behaves like |X509v3_get_ext_by_OBJ| but searches +// for extensions in |x|. +OPENSSL_EXPORT int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, + const ASN1_OBJECT *obj, + int lastpos); + +// X509_REVOKED_get_ext_by_critical behaves like |X509v3_get_ext_by_critical| +// but searches for extensions in |x|. +OPENSSL_EXPORT int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, + int crit, int lastpos); + +// X509_REVOKED_get_ext returns the extension in |x| at index |loc|, or NULL if +// |loc| is out of bounds. This function returns a non-const pointer for OpenSSL +// compatibility, but callers should not mutate the result. +OPENSSL_EXPORT X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, + int loc); + +// X509_REVOKED_delete_ext removes the extension in |x| at index |loc| and +// returns the removed extension, or NULL if |loc| was out of bounds. If +// non-NULL, the caller must release the result with |X509_EXTENSION_free|. +OPENSSL_EXPORT X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, + int loc); + +// X509_REVOKED_add_ext adds a copy of |ex| to |x|. It returns one on success +// and zero on failure. The caller retains ownership of |ex| and can release it +// independently of |x|. +// +// The new extension is inserted at index |loc|, shifting extensions to the +// right. If |loc| is -1 or out of bounds, the new extension is appended to the +// list. +OPENSSL_EXPORT int X509_REVOKED_add_ext(X509_REVOKED *x, + const X509_EXTENSION *ex, int loc); + +// X509_REVOKED_get_ext_d2i behaves like |X509V3_get_d2i| but looks for the +// extension in |revoked|'s extension list. +// +// WARNING: This function is difficult to use correctly. See the documentation +// for |X509V3_get_d2i| for details. +OPENSSL_EXPORT void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *revoked, + int nid, int *out_critical, + int *out_idx); + +// X509_REVOKED_add1_ext_i2d behaves like |X509V3_add1_i2d| but adds the +// extension to |x|'s extension list. +// +// WARNING: This function may return zero or -1 on error. The caller must also +// ensure |value|'s type matches |nid|. See the documentation for +// |X509V3_add1_i2d| for details. +OPENSSL_EXPORT int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, + void *value, int crit, + unsigned long flags); + +OPENSSL_EXPORT int X509_verify_cert(X509_STORE_CTX *ctx); + +// PKCS#8 utilities + +DECLARE_ASN1_FUNCTIONS_const(PKCS8_PRIV_KEY_INFO) + +// EVP_PKCS82PKEY returns |p8| as a newly-allocated |EVP_PKEY|, or NULL if the +// key was unsupported or could not be decoded. If non-NULL, the caller must +// release the result with |EVP_PKEY_free| when done. +// +// Use |EVP_parse_private_key| instead. +OPENSSL_EXPORT EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8); + +// EVP_PKEY2PKCS8 encodes |pkey| as a PKCS#8 PrivateKeyInfo (RFC 5208), +// represented as a newly-allocated |PKCS8_PRIV_KEY_INFO|, or NULL on error. The +// caller must release the result with |PKCS8_PRIV_KEY_INFO_free| when done. +// +// Use |EVP_marshal_private_key| instead. +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(const EVP_PKEY *pkey); + +// X509_PUBKEY_set0_param sets |pub| to a key with AlgorithmIdentifier +// determined by |obj|, |param_type|, and |param_value|, and an encoded +// public key of |key|. On success, it takes ownership of all its parameters and +// returns one. Otherwise, it returns zero. |key| must have been allocated by +// |OPENSSL_malloc|. +// +// |obj|, |param_type|, and |param_value| are interpreted as in +// |X509_ALGOR_set0|. See |X509_ALGOR_set0| for details. +OPENSSL_EXPORT int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, + int param_type, void *param_value, + uint8_t *key, int key_len); + +// X509_PUBKEY_get0_param outputs fields of |pub| and returns one. If |out_obj| +// is not NULL, it sets |*out_obj| to AlgorithmIdentifier's OID. If |out_key| +// is not NULL, it sets |*out_key| and |*out_key_len| to the encoded public key. +// If |out_alg| is not NULL, it sets |*out_alg| to the AlgorithmIdentifier. +// +// Note: X.509 SubjectPublicKeyInfo structures store the encoded public key as a +// BIT STRING. |*out_key| and |*out_key_len| will silently pad the key with zero +// bits if |pub| did not contain a whole number of bytes. Use +// |X509_PUBKEY_get0_public_key| to preserve this information. +OPENSSL_EXPORT int X509_PUBKEY_get0_param(ASN1_OBJECT **out_obj, + const uint8_t **out_key, + int *out_key_len, + X509_ALGOR **out_alg, + X509_PUBKEY *pub); + +// X509_PUBKEY_get0_public_key returns |pub|'s encoded public key. +OPENSSL_EXPORT const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key( + const X509_PUBKEY *pub); + +OPENSSL_EXPORT int X509_check_trust(X509 *x, int id, int flags); +OPENSSL_EXPORT int X509_TRUST_get_count(void); +OPENSSL_EXPORT X509_TRUST *X509_TRUST_get0(int idx); +OPENSSL_EXPORT int X509_TRUST_get_by_id(int id); +OPENSSL_EXPORT int X509_TRUST_add(int id, int flags, + int (*ck)(X509_TRUST *, X509 *, int), + char *name, int arg1, void *arg2); +OPENSSL_EXPORT void X509_TRUST_cleanup(void); +OPENSSL_EXPORT int X509_TRUST_get_flags(const X509_TRUST *xp); +OPENSSL_EXPORT char *X509_TRUST_get0_name(const X509_TRUST *xp); +OPENSSL_EXPORT int X509_TRUST_get_trust(const X509_TRUST *xp); + + +struct rsa_pss_params_st { + X509_ALGOR *hashAlgorithm; + X509_ALGOR *maskGenAlgorithm; + ASN1_INTEGER *saltLength; + ASN1_INTEGER *trailerField; + // OpenSSL caches the MGF hash on |RSA_PSS_PARAMS| in some cases. None of the + // cases apply to BoringSSL, so this is always NULL, but Node expects the + // field to be present. + X509_ALGOR *maskHash; +} /* RSA_PSS_PARAMS */; + +DECLARE_ASN1_FUNCTIONS_const(RSA_PSS_PARAMS) + +/* +SSL_CTX -> X509_STORE + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + +SSL -> X509_STORE_CTX + ->X509_STORE + +The X509_STORE holds the tables etc for verification stuff. +A X509_STORE_CTX is used while validating a single certificate. +The X509_STORE has X509_LOOKUPs for looking up certs. +The X509_STORE then calls a function to actually verify the +certificate chain. +*/ + +#define X509_LU_X509 1 +#define X509_LU_CRL 2 +#define X509_LU_PKEY 3 + +DEFINE_STACK_OF(X509_LOOKUP) +DEFINE_STACK_OF(X509_OBJECT) +DEFINE_STACK_OF(X509_VERIFY_PARAM) + +typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *); +typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *); +typedef int (*X509_STORE_CTX_get_issuer_fn)(X509 **issuer, X509_STORE_CTX *ctx, + X509 *x); +typedef int (*X509_STORE_CTX_check_issued_fn)(X509_STORE_CTX *ctx, X509 *x, + X509 *issuer); +typedef int (*X509_STORE_CTX_check_revocation_fn)(X509_STORE_CTX *ctx); +typedef int (*X509_STORE_CTX_get_crl_fn)(X509_STORE_CTX *ctx, X509_CRL **crl, + X509 *x); +typedef int (*X509_STORE_CTX_check_crl_fn)(X509_STORE_CTX *ctx, X509_CRL *crl); +typedef int (*X509_STORE_CTX_cert_crl_fn)(X509_STORE_CTX *ctx, X509_CRL *crl, + X509 *x); +typedef int (*X509_STORE_CTX_check_policy_fn)(X509_STORE_CTX *ctx); +typedef STACK_OF(X509) *(*X509_STORE_CTX_lookup_certs_fn)(X509_STORE_CTX *ctx, + X509_NAME *nm); +typedef STACK_OF(X509_CRL) *(*X509_STORE_CTX_lookup_crls_fn)( + X509_STORE_CTX *ctx, X509_NAME *nm); +typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx); + +OPENSSL_EXPORT int X509_STORE_set_depth(X509_STORE *store, int depth); + +OPENSSL_EXPORT void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); + +#define X509_STORE_CTX_set_app_data(ctx, data) \ + X509_STORE_CTX_set_ex_data(ctx, 0, data) +#define X509_STORE_CTX_get_app_data(ctx) X509_STORE_CTX_get_ex_data(ctx, 0) + +#define X509_L_FILE_LOAD 1 +#define X509_L_ADD_DIR 2 + +#define X509_LOOKUP_load_file(x, name, type) \ + X509_LOOKUP_ctrl((x), X509_L_FILE_LOAD, (name), (long)(type), NULL) + +#define X509_LOOKUP_add_dir(x, name, type) \ + X509_LOOKUP_ctrl((x), X509_L_ADD_DIR, (name), (long)(type), NULL) + +#define X509_V_OK 0 +#define X509_V_ERR_UNSPECIFIED 1 + +#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 +#define X509_V_ERR_UNABLE_TO_GET_CRL 3 +#define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4 +#define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5 +#define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6 +#define X509_V_ERR_CERT_SIGNATURE_FAILURE 7 +#define X509_V_ERR_CRL_SIGNATURE_FAILURE 8 +#define X509_V_ERR_CERT_NOT_YET_VALID 9 +#define X509_V_ERR_CERT_HAS_EXPIRED 10 +#define X509_V_ERR_CRL_NOT_YET_VALID 11 +#define X509_V_ERR_CRL_HAS_EXPIRED 12 +#define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13 +#define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14 +#define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15 +#define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16 +#define X509_V_ERR_OUT_OF_MEM 17 +#define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 +#define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 +#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 +#define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 +#define X509_V_ERR_CERT_CHAIN_TOO_LONG 22 +#define X509_V_ERR_CERT_REVOKED 23 +#define X509_V_ERR_INVALID_CA 24 +#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25 +#define X509_V_ERR_INVALID_PURPOSE 26 +#define X509_V_ERR_CERT_UNTRUSTED 27 +#define X509_V_ERR_CERT_REJECTED 28 +// These are 'informational' when looking for issuer cert +#define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29 +#define X509_V_ERR_AKID_SKID_MISMATCH 30 +#define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31 +#define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32 + +#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33 +#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34 +#define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35 +#define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36 +#define X509_V_ERR_INVALID_NON_CA 37 +#define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38 +#define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39 +#define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40 + +#define X509_V_ERR_INVALID_EXTENSION 41 +#define X509_V_ERR_INVALID_POLICY_EXTENSION 42 +#define X509_V_ERR_NO_EXPLICIT_POLICY 43 +#define X509_V_ERR_DIFFERENT_CRL_SCOPE 44 +#define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45 + +#define X509_V_ERR_UNNESTED_RESOURCE 46 + +#define X509_V_ERR_PERMITTED_VIOLATION 47 +#define X509_V_ERR_EXCLUDED_VIOLATION 48 +#define X509_V_ERR_SUBTREE_MINMAX 49 +#define X509_V_ERR_APPLICATION_VERIFICATION 50 +#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51 +#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52 +#define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53 +#define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54 + +// Host, email and IP check errors +#define X509_V_ERR_HOSTNAME_MISMATCH 62 +#define X509_V_ERR_EMAIL_MISMATCH 63 +#define X509_V_ERR_IP_ADDRESS_MISMATCH 64 + +// Caller error +#define X509_V_ERR_INVALID_CALL 65 +// Issuer lookup error +#define X509_V_ERR_STORE_LOOKUP 66 + +#define X509_V_ERR_NAME_CONSTRAINTS_WITHOUT_SANS 67 + +// Certificate verify flags + +// Send issuer+subject checks to verify_cb +#define X509_V_FLAG_CB_ISSUER_CHECK 0x1 +// Use check time instead of current time +#define X509_V_FLAG_USE_CHECK_TIME 0x2 +// Lookup CRLs +#define X509_V_FLAG_CRL_CHECK 0x4 +// Lookup CRLs for whole chain +#define X509_V_FLAG_CRL_CHECK_ALL 0x8 +// Ignore unhandled critical extensions +#define X509_V_FLAG_IGNORE_CRITICAL 0x10 +// Does nothing as its functionality has been enabled by default. +#define X509_V_FLAG_X509_STRICT 0x00 +// This flag does nothing as proxy certificate support has been removed. +#define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40 +// Does nothing as its functionality has been enabled by default. +#define X509_V_FLAG_POLICY_CHECK 0x80 +// Policy variable require-explicit-policy +#define X509_V_FLAG_EXPLICIT_POLICY 0x100 +// Policy variable inhibit-any-policy +#define X509_V_FLAG_INHIBIT_ANY 0x200 +// Policy variable inhibit-policy-mapping +#define X509_V_FLAG_INHIBIT_MAP 0x400 +// Notify callback that policy is OK +#define X509_V_FLAG_NOTIFY_POLICY 0x800 +// Extended CRL features such as indirect CRLs, alternate CRL signing keys +#define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000 +// Delta CRL support +#define X509_V_FLAG_USE_DELTAS 0x2000 +// Check selfsigned CA signature +#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 +// Use trusted store first +#define X509_V_FLAG_TRUSTED_FIRST 0x8000 + +// Allow partial chains if at least one certificate is in trusted store +#define X509_V_FLAG_PARTIAL_CHAIN 0x80000 + +// If the initial chain is not trusted, do not attempt to build an alternative +// chain. Alternate chain checking was introduced in 1.0.2b. Setting this flag +// will force the behaviour to match that of previous versions. +#define X509_V_FLAG_NO_ALT_CHAINS 0x100000 + +// X509_V_FLAG_NO_CHECK_TIME disables all time checks in certificate +// verification. +#define X509_V_FLAG_NO_CHECK_TIME 0x200000 + +#define X509_VP_FLAG_DEFAULT 0x1 +#define X509_VP_FLAG_OVERWRITE 0x2 +#define X509_VP_FLAG_RESET_FLAGS 0x4 +#define X509_VP_FLAG_LOCKED 0x8 +#define X509_VP_FLAG_ONCE 0x10 + +OPENSSL_EXPORT int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, + int type, X509_NAME *name); +OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_by_subject( + STACK_OF(X509_OBJECT) *h, int type, X509_NAME *name); +OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, + X509_OBJECT *x); +OPENSSL_EXPORT int X509_OBJECT_up_ref_count(X509_OBJECT *a); +OPENSSL_EXPORT void X509_OBJECT_free_contents(X509_OBJECT *a); +OPENSSL_EXPORT int X509_OBJECT_get_type(const X509_OBJECT *a); +OPENSSL_EXPORT X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a); +OPENSSL_EXPORT X509_STORE *X509_STORE_new(void); +OPENSSL_EXPORT int X509_STORE_up_ref(X509_STORE *store); +OPENSSL_EXPORT void X509_STORE_free(X509_STORE *v); + +OPENSSL_EXPORT STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st); +OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *st, + X509_NAME *nm); +OPENSSL_EXPORT STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *st, + X509_NAME *nm); +OPENSSL_EXPORT int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); +OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); +OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *ctx, int trust); +OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *ctx, + X509_VERIFY_PARAM *pm); +OPENSSL_EXPORT X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx); + +OPENSSL_EXPORT void X509_STORE_set_verify(X509_STORE *ctx, + X509_STORE_CTX_verify_fn verify); +#define X509_STORE_set_verify_func(ctx, func) \ + X509_STORE_set_verify((ctx), (func)) +OPENSSL_EXPORT void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_fn verify); +OPENSSL_EXPORT X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_verify_cb( + X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb); +#define X509_STORE_set_verify_cb_func(ctx, func) \ + X509_STORE_set_verify_cb((ctx), (func)) +OPENSSL_EXPORT X509_STORE_CTX_verify_cb +X509_STORE_get_verify_cb(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_get_issuer( + X509_STORE *ctx, X509_STORE_CTX_get_issuer_fn get_issuer); +OPENSSL_EXPORT X509_STORE_CTX_get_issuer_fn +X509_STORE_get_get_issuer(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_check_issued( + X509_STORE *ctx, X509_STORE_CTX_check_issued_fn check_issued); +OPENSSL_EXPORT X509_STORE_CTX_check_issued_fn +X509_STORE_get_check_issued(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_check_revocation( + X509_STORE *ctx, X509_STORE_CTX_check_revocation_fn check_revocation); +OPENSSL_EXPORT X509_STORE_CTX_check_revocation_fn +X509_STORE_get_check_revocation(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_get_crl(X509_STORE *ctx, + X509_STORE_CTX_get_crl_fn get_crl); +OPENSSL_EXPORT X509_STORE_CTX_get_crl_fn +X509_STORE_get_get_crl(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_check_crl( + X509_STORE *ctx, X509_STORE_CTX_check_crl_fn check_crl); +OPENSSL_EXPORT X509_STORE_CTX_check_crl_fn +X509_STORE_get_check_crl(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_cert_crl( + X509_STORE *ctx, X509_STORE_CTX_cert_crl_fn cert_crl); +OPENSSL_EXPORT X509_STORE_CTX_cert_crl_fn +X509_STORE_get_cert_crl(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_lookup_certs( + X509_STORE *ctx, X509_STORE_CTX_lookup_certs_fn lookup_certs); +OPENSSL_EXPORT X509_STORE_CTX_lookup_certs_fn +X509_STORE_get_lookup_certs(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_lookup_crls( + X509_STORE *ctx, X509_STORE_CTX_lookup_crls_fn lookup_crls); +#define X509_STORE_set_lookup_crls_cb(ctx, func) \ + X509_STORE_set_lookup_crls((ctx), (func)) +OPENSSL_EXPORT X509_STORE_CTX_lookup_crls_fn +X509_STORE_get_lookup_crls(X509_STORE *ctx); +OPENSSL_EXPORT void X509_STORE_set_cleanup(X509_STORE *ctx, + X509_STORE_CTX_cleanup_fn cleanup); +OPENSSL_EXPORT X509_STORE_CTX_cleanup_fn +X509_STORE_get_cleanup(X509_STORE *ctx); + +OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_new(void); + +OPENSSL_EXPORT int X509_STORE_CTX_get1_issuer(X509 **issuer, + X509_STORE_CTX *ctx, X509 *x); + +OPENSSL_EXPORT void X509_STORE_CTX_zero(X509_STORE_CTX *ctx); +OPENSSL_EXPORT void X509_STORE_CTX_free(X509_STORE_CTX *ctx); +OPENSSL_EXPORT int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); + +// X509_STORE_CTX_set0_trusted_stack configures |ctx| to trust the certificates +// in |sk|. |sk| must remain valid for the duration of |ctx|. +// +// WARNING: This function differs from most |set0| functions in that it does not +// take ownership of its input. The caller is required to ensure the lifetimes +// are consistent. +OPENSSL_EXPORT void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, + STACK_OF(X509) *sk); + +// X509_STORE_CTX_trusted_stack is a deprecated alias for +// |X509_STORE_CTX_set0_trusted_stack|. +OPENSSL_EXPORT void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, + STACK_OF(X509) *sk); + +OPENSSL_EXPORT void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); + +OPENSSL_EXPORT X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx); + +OPENSSL_EXPORT X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, + X509_LOOKUP_METHOD *m); + +OPENSSL_EXPORT X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); +OPENSSL_EXPORT X509_LOOKUP_METHOD *X509_LOOKUP_file(void); + +OPENSSL_EXPORT int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); +OPENSSL_EXPORT int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + +OPENSSL_EXPORT int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, + X509_NAME *name, X509_OBJECT *ret); + +OPENSSL_EXPORT int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); + +#ifndef OPENSSL_NO_STDIO +OPENSSL_EXPORT int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, + int type); +OPENSSL_EXPORT int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, + int type); +OPENSSL_EXPORT int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, + int type); +#endif + +OPENSSL_EXPORT X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); +OPENSSL_EXPORT void X509_LOOKUP_free(X509_LOOKUP *ctx); +OPENSSL_EXPORT int X509_LOOKUP_init(X509_LOOKUP *ctx); +OPENSSL_EXPORT int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, + X509_NAME *name, X509_OBJECT *ret); +OPENSSL_EXPORT int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); + +#ifndef OPENSSL_NO_STDIO +OPENSSL_EXPORT int X509_STORE_load_locations(X509_STORE *ctx, const char *file, + const char *dir); +OPENSSL_EXPORT int X509_STORE_set_default_paths(X509_STORE *ctx); +#endif +OPENSSL_EXPORT int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); +OPENSSL_EXPORT void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s); +OPENSSL_EXPORT int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx( + X509_STORE_CTX *ctx); +OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); +OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx); +OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); +OPENSSL_EXPORT void X509_STORE_CTX_set_cert(X509_STORE_CTX *c, X509 *x); +OPENSSL_EXPORT void X509_STORE_CTX_set_chain(X509_STORE_CTX *c, + STACK_OF(X509) *sk); +OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get0_untrusted( + X509_STORE_CTX *ctx); +OPENSSL_EXPORT void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, + STACK_OF(X509_CRL) *sk); +OPENSSL_EXPORT int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); +OPENSSL_EXPORT int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); +OPENSSL_EXPORT int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, + int def_purpose, int purpose, + int trust); +OPENSSL_EXPORT void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, + unsigned long flags); +OPENSSL_EXPORT void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, + unsigned long flags, time_t t); +OPENSSL_EXPORT void X509_STORE_CTX_set_time_posix(X509_STORE_CTX *ctx, + unsigned long flags, + int64_t t); +OPENSSL_EXPORT void X509_STORE_CTX_set_verify_cb( + X509_STORE_CTX *ctx, int (*verify_cb)(int, X509_STORE_CTX *)); + +OPENSSL_EXPORT X509_VERIFY_PARAM *X509_STORE_CTX_get0_param( + X509_STORE_CTX *ctx); +OPENSSL_EXPORT void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, + X509_VERIFY_PARAM *param); +OPENSSL_EXPORT int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, + const char *name); + +// X509_VERIFY_PARAM functions + +OPENSSL_EXPORT X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); +OPENSSL_EXPORT void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); +OPENSSL_EXPORT int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, + const char *name); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +OPENSSL_EXPORT int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +OPENSSL_EXPORT unsigned long X509_VERIFY_PARAM_get_flags( + X509_VERIFY_PARAM *param); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, + int purpose); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, + int trust); +OPENSSL_EXPORT void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, + int depth); +OPENSSL_EXPORT void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, + time_t t); +OPENSSL_EXPORT void X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM *param, + int64_t t); +OPENSSL_EXPORT int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, + ASN1_OBJECT *policy); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_policies( + X509_VERIFY_PARAM *param, const STACK_OF(ASN1_OBJECT) *policies); + +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, + size_t namelen); +OPENSSL_EXPORT int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, + size_t namelen); +OPENSSL_EXPORT void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags); +OPENSSL_EXPORT char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, + const char *email, + size_t emaillen); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, + const unsigned char *ip, + size_t iplen); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, + const char *ipasc); + +OPENSSL_EXPORT int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); +OPENSSL_EXPORT const char *X509_VERIFY_PARAM_get0_name( + const X509_VERIFY_PARAM *param); + +OPENSSL_EXPORT const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup( + const char *name); + + +#if defined(__cplusplus) +} // extern C +#endif + +#if !defined(BORINGSSL_NO_CXX) +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(NETSCAPE_SPKI, NETSCAPE_SPKI_free) +BORINGSSL_MAKE_DELETER(RSA_PSS_PARAMS, RSA_PSS_PARAMS_free) +BORINGSSL_MAKE_DELETER(X509, X509_free) +BORINGSSL_MAKE_UP_REF(X509, X509_up_ref) +BORINGSSL_MAKE_DELETER(X509_ALGOR, X509_ALGOR_free) +BORINGSSL_MAKE_DELETER(X509_ATTRIBUTE, X509_ATTRIBUTE_free) +BORINGSSL_MAKE_DELETER(X509_CRL, X509_CRL_free) +BORINGSSL_MAKE_UP_REF(X509_CRL, X509_CRL_up_ref) +BORINGSSL_MAKE_DELETER(X509_EXTENSION, X509_EXTENSION_free) +BORINGSSL_MAKE_DELETER(X509_INFO, X509_INFO_free) +BORINGSSL_MAKE_DELETER(X509_LOOKUP, X509_LOOKUP_free) +BORINGSSL_MAKE_DELETER(X509_NAME, X509_NAME_free) +BORINGSSL_MAKE_DELETER(X509_NAME_ENTRY, X509_NAME_ENTRY_free) +BORINGSSL_MAKE_DELETER(X509_PKEY, X509_PKEY_free) +BORINGSSL_MAKE_DELETER(X509_PUBKEY, X509_PUBKEY_free) +BORINGSSL_MAKE_DELETER(X509_REQ, X509_REQ_free) +BORINGSSL_MAKE_DELETER(X509_REVOKED, X509_REVOKED_free) +BORINGSSL_MAKE_DELETER(X509_SIG, X509_SIG_free) +BORINGSSL_MAKE_DELETER(X509_STORE, X509_STORE_free) +BORINGSSL_MAKE_UP_REF(X509_STORE, X509_STORE_up_ref) +BORINGSSL_MAKE_DELETER(X509_STORE_CTX, X509_STORE_CTX_free) +BORINGSSL_MAKE_DELETER(X509_VERIFY_PARAM, X509_VERIFY_PARAM_free) + +BSSL_NAMESPACE_END + +} // extern C++ +#endif // !BORINGSSL_NO_CXX + +#define X509_R_AKID_MISMATCH 100 +#define X509_R_BAD_PKCS7_VERSION 101 +#define X509_R_BAD_X509_FILETYPE 102 +#define X509_R_BASE64_DECODE_ERROR 103 +#define X509_R_CANT_CHECK_DH_KEY 104 +#define X509_R_CERT_ALREADY_IN_HASH_TABLE 105 +#define X509_R_CRL_ALREADY_DELTA 106 +#define X509_R_CRL_VERIFY_FAILURE 107 +#define X509_R_IDP_MISMATCH 108 +#define X509_R_INVALID_BIT_STRING_BITS_LEFT 109 +#define X509_R_INVALID_DIRECTORY 110 +#define X509_R_INVALID_FIELD_NAME 111 +#define X509_R_INVALID_PSS_PARAMETERS 112 +#define X509_R_INVALID_TRUST 113 +#define X509_R_ISSUER_MISMATCH 114 +#define X509_R_KEY_TYPE_MISMATCH 115 +#define X509_R_KEY_VALUES_MISMATCH 116 +#define X509_R_LOADING_CERT_DIR 117 +#define X509_R_LOADING_DEFAULTS 118 +#define X509_R_NEWER_CRL_NOT_NEWER 119 +#define X509_R_NOT_PKCS7_SIGNED_DATA 120 +#define X509_R_NO_CERTIFICATES_INCLUDED 121 +#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 122 +#define X509_R_NO_CRLS_INCLUDED 123 +#define X509_R_NO_CRL_NUMBER 124 +#define X509_R_PUBLIC_KEY_DECODE_ERROR 125 +#define X509_R_PUBLIC_KEY_ENCODE_ERROR 126 +#define X509_R_SHOULD_RETRY 127 +#define X509_R_UNKNOWN_KEY_TYPE 128 +#define X509_R_UNKNOWN_NID 129 +#define X509_R_UNKNOWN_PURPOSE_ID 130 +#define X509_R_UNKNOWN_TRUST_ID 131 +#define X509_R_UNSUPPORTED_ALGORITHM 132 +#define X509_R_WRONG_LOOKUP_TYPE 133 +#define X509_R_WRONG_TYPE 134 +#define X509_R_NAME_TOO_LONG 135 +#define X509_R_INVALID_PARAMETER 136 +#define X509_R_SIGNATURE_ALGORITHM_MISMATCH 137 +#define X509_R_DELTA_CRL_WITHOUT_CRL_NUMBER 138 +#define X509_R_INVALID_FIELD_FOR_VERSION 139 +#define X509_R_INVALID_VERSION 140 +#define X509_R_NO_CERTIFICATE_FOUND 141 +#define X509_R_NO_CERTIFICATE_OR_CRL_FOUND 142 +#define X509_R_NO_CRL_FOUND 143 +#define X509_R_INVALID_POLICY_EXTENSION 144 + +#endif // OPENSSL_HEADER_X509_H diff --git a/lib/boringssl/include/openssl/x509_vfy.h b/lib/boringssl/include/openssl/x509_vfy.h new file mode 100644 index 00000000..04bc8dd1 --- /dev/null +++ b/lib/boringssl/include/openssl/x509_vfy.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2021, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "x509.h" diff --git a/lib/boringssl/include/openssl/x509v3.h b/lib/boringssl/include/openssl/x509v3.h new file mode 100644 index 00000000..d9c862da --- /dev/null +++ b/lib/boringssl/include/openssl/x509v3.h @@ -0,0 +1,1047 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_X509V3_H +#define OPENSSL_HEADER_X509V3_H + +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// Legacy X.509 library. +// +// This header is part of OpenSSL's X.509 implementation. It is retained for +// compatibility but otherwise underdocumented and not actively maintained. In +// the future, a replacement library will be available. Meanwhile, minimize +// dependencies on this header where possible. + + +// Forward reference +struct v3_ext_method; +struct v3_ext_ctx; + +// Useful typedefs + +typedef struct v3_ext_method X509V3_EXT_METHOD; + +typedef void *(*X509V3_EXT_NEW)(void); +typedef void (*X509V3_EXT_FREE)(void *); +typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long); +typedef int (*X509V3_EXT_I2D)(void *, unsigned char **); +typedef STACK_OF(CONF_VALUE) *(*X509V3_EXT_I2V)(const X509V3_EXT_METHOD *method, + void *ext, + STACK_OF(CONF_VALUE) *extlist); +typedef void *(*X509V3_EXT_V2I)(const X509V3_EXT_METHOD *method, + const X509V3_CTX *ctx, + const STACK_OF(CONF_VALUE) *values); +typedef char *(*X509V3_EXT_I2S)(const X509V3_EXT_METHOD *method, void *ext); +typedef void *(*X509V3_EXT_S2I)(const X509V3_EXT_METHOD *method, + const X509V3_CTX *ctx, const char *str); +typedef int (*X509V3_EXT_I2R)(const X509V3_EXT_METHOD *method, void *ext, + BIO *out, int indent); +typedef void *(*X509V3_EXT_R2I)(const X509V3_EXT_METHOD *method, + const X509V3_CTX *ctx, const char *str); + +// V3 extension structure + +struct v3_ext_method { + int ext_nid; + int ext_flags; + + // it determines how values of this extension are allocated, released, parsed, + // and marshalled. This must be non-NULL. + ASN1_ITEM_EXP *it; + + // The following functions are ignored in favor of |it|. They are retained in + // the struct only for source compatibility with existing struct definitions. + X509V3_EXT_NEW ext_new; + X509V3_EXT_FREE ext_free; + X509V3_EXT_D2I d2i; + X509V3_EXT_I2D i2d; + + // The following pair is used for string extensions + X509V3_EXT_I2S i2s; + X509V3_EXT_S2I s2i; + + // The following pair is used for multi-valued extensions + X509V3_EXT_I2V i2v; + X509V3_EXT_V2I v2i; + + // The following are used for raw extensions + X509V3_EXT_I2R i2r; + X509V3_EXT_R2I r2i; + + void *usr_data; // Any extension specific data +}; + +DEFINE_STACK_OF(X509V3_EXT_METHOD) + +// ext_flags values +#define X509V3_EXT_CTX_DEP 0x2 +#define X509V3_EXT_MULTILINE 0x4 + +struct BASIC_CONSTRAINTS_st { + int ca; + ASN1_INTEGER *pathlen; +}; + + +typedef struct otherName_st { + ASN1_OBJECT *type_id; + ASN1_TYPE *value; +} OTHERNAME; + +typedef struct EDIPartyName_st { + ASN1_STRING *nameAssigner; + ASN1_STRING *partyName; +} EDIPARTYNAME; + +typedef struct GENERAL_NAME_st { +#define GEN_OTHERNAME 0 +#define GEN_EMAIL 1 +#define GEN_DNS 2 +#define GEN_X400 3 +#define GEN_DIRNAME 4 +#define GEN_EDIPARTY 5 +#define GEN_URI 6 +#define GEN_IPADD 7 +#define GEN_RID 8 + + int type; + union { + char *ptr; + OTHERNAME *otherName; // otherName + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; + ASN1_STRING *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; + ASN1_OCTET_STRING *iPAddress; + ASN1_OBJECT *registeredID; + + // Old names + ASN1_OCTET_STRING *ip; // iPAddress + X509_NAME *dirn; // dirn + ASN1_IA5STRING *ia5; // rfc822Name, dNSName, uniformResourceIdentifier + ASN1_OBJECT *rid; // registeredID + } d; +} GENERAL_NAME; + +DEFINE_STACK_OF(GENERAL_NAME) + +typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; + +DEFINE_STACK_OF(GENERAL_NAMES) + +typedef struct ACCESS_DESCRIPTION_st { + ASN1_OBJECT *method; + GENERAL_NAME *location; +} ACCESS_DESCRIPTION; + +DEFINE_STACK_OF(ACCESS_DESCRIPTION) + +typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; + +typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE; + +typedef struct DIST_POINT_NAME_st { + int type; + union { + GENERAL_NAMES *fullname; + STACK_OF(X509_NAME_ENTRY) *relativename; + } name; + // If relativename then this contains the full distribution point name + X509_NAME *dpname; +} DIST_POINT_NAME; +// All existing reasons +#define CRLDP_ALL_REASONS 0x807f + +#define CRL_REASON_NONE (-1) +#define CRL_REASON_UNSPECIFIED 0 +#define CRL_REASON_KEY_COMPROMISE 1 +#define CRL_REASON_CA_COMPROMISE 2 +#define CRL_REASON_AFFILIATION_CHANGED 3 +#define CRL_REASON_SUPERSEDED 4 +#define CRL_REASON_CESSATION_OF_OPERATION 5 +#define CRL_REASON_CERTIFICATE_HOLD 6 +#define CRL_REASON_REMOVE_FROM_CRL 8 +#define CRL_REASON_PRIVILEGE_WITHDRAWN 9 +#define CRL_REASON_AA_COMPROMISE 10 + +struct DIST_POINT_st { + DIST_POINT_NAME *distpoint; + ASN1_BIT_STRING *reasons; + GENERAL_NAMES *CRLissuer; + int dp_reasons; +}; + +typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS; + +DEFINE_STACK_OF(DIST_POINT) + +struct AUTHORITY_KEYID_st { + ASN1_OCTET_STRING *keyid; + GENERAL_NAMES *issuer; + ASN1_INTEGER *serial; +}; + +typedef struct NOTICEREF_st { + ASN1_STRING *organization; + STACK_OF(ASN1_INTEGER) *noticenos; +} NOTICEREF; + +typedef struct USERNOTICE_st { + NOTICEREF *noticeref; + ASN1_STRING *exptext; +} USERNOTICE; + +typedef struct POLICYQUALINFO_st { + ASN1_OBJECT *pqualid; + union { + ASN1_IA5STRING *cpsuri; + USERNOTICE *usernotice; + ASN1_TYPE *other; + } d; +} POLICYQUALINFO; + +DEFINE_STACK_OF(POLICYQUALINFO) + +typedef struct POLICYINFO_st { + ASN1_OBJECT *policyid; + STACK_OF(POLICYQUALINFO) *qualifiers; +} POLICYINFO; + +typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES; + +DEFINE_STACK_OF(POLICYINFO) + +typedef struct POLICY_MAPPING_st { + ASN1_OBJECT *issuerDomainPolicy; + ASN1_OBJECT *subjectDomainPolicy; +} POLICY_MAPPING; + +DEFINE_STACK_OF(POLICY_MAPPING) + +typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS; + +typedef struct GENERAL_SUBTREE_st { + GENERAL_NAME *base; + ASN1_INTEGER *minimum; + ASN1_INTEGER *maximum; +} GENERAL_SUBTREE; + +DEFINE_STACK_OF(GENERAL_SUBTREE) + +struct NAME_CONSTRAINTS_st { + STACK_OF(GENERAL_SUBTREE) *permittedSubtrees; + STACK_OF(GENERAL_SUBTREE) *excludedSubtrees; +}; + +typedef struct POLICY_CONSTRAINTS_st { + ASN1_INTEGER *requireExplicitPolicy; + ASN1_INTEGER *inhibitPolicyMapping; +} POLICY_CONSTRAINTS; + +struct ISSUING_DIST_POINT_st { + DIST_POINT_NAME *distpoint; + int onlyuser; + int onlyCA; + ASN1_BIT_STRING *onlysomereasons; + int indirectCRL; + int onlyattr; +}; + +// Values in idp_flags field +// IDP present +#define IDP_PRESENT 0x1 +// IDP values inconsistent +#define IDP_INVALID 0x2 +// onlyuser true +#define IDP_ONLYUSER 0x4 +// onlyCA true +#define IDP_ONLYCA 0x8 +// onlyattr true +#define IDP_ONLYATTR 0x10 +// indirectCRL true +#define IDP_INDIRECT 0x20 +// onlysomereasons present +#define IDP_REASONS 0x40 + + + +// X509_PURPOSE stuff + +#define EXFLAG_BCONS 0x1 +#define EXFLAG_KUSAGE 0x2 +#define EXFLAG_XKUSAGE 0x4 +#define EXFLAG_NSCERT 0x8 + +#define EXFLAG_CA 0x10 +// Really self issued not necessarily self signed +#define EXFLAG_SI 0x20 +#define EXFLAG_V1 0x40 +#define EXFLAG_INVALID 0x80 +#define EXFLAG_SET 0x100 +#define EXFLAG_CRITICAL 0x200 + +#define EXFLAG_FRESHEST 0x1000 +// Self signed +#define EXFLAG_SS 0x2000 + +#define KU_DIGITAL_SIGNATURE 0x0080 +#define KU_NON_REPUDIATION 0x0040 +#define KU_KEY_ENCIPHERMENT 0x0020 +#define KU_DATA_ENCIPHERMENT 0x0010 +#define KU_KEY_AGREEMENT 0x0008 +#define KU_KEY_CERT_SIGN 0x0004 +#define KU_CRL_SIGN 0x0002 +#define KU_ENCIPHER_ONLY 0x0001 +#define KU_DECIPHER_ONLY 0x8000 + +#define NS_SSL_CLIENT 0x80 +#define NS_SSL_SERVER 0x40 +#define NS_SMIME 0x20 +#define NS_OBJSIGN 0x10 +#define NS_SSL_CA 0x04 +#define NS_SMIME_CA 0x02 +#define NS_OBJSIGN_CA 0x01 +#define NS_ANY_CA (NS_SSL_CA | NS_SMIME_CA | NS_OBJSIGN_CA) + +#define XKU_SSL_SERVER 0x1 +#define XKU_SSL_CLIENT 0x2 +#define XKU_SMIME 0x4 +#define XKU_CODE_SIGN 0x8 +#define XKU_SGC 0x10 +#define XKU_OCSP_SIGN 0x20 +#define XKU_TIMESTAMP 0x40 +#define XKU_DVCS 0x80 +#define XKU_ANYEKU 0x100 + +#define X509_PURPOSE_DYNAMIC 0x1 +#define X509_PURPOSE_DYNAMIC_NAME 0x2 + +typedef struct x509_purpose_st { + int purpose; + int trust; // Default trust ID + int flags; + int (*check_purpose)(const struct x509_purpose_st *, const X509 *, int); + char *name; + char *sname; + void *usr_data; +} X509_PURPOSE; + +#define X509_PURPOSE_SSL_CLIENT 1 +#define X509_PURPOSE_SSL_SERVER 2 +#define X509_PURPOSE_NS_SSL_SERVER 3 +#define X509_PURPOSE_SMIME_SIGN 4 +#define X509_PURPOSE_SMIME_ENCRYPT 5 +#define X509_PURPOSE_CRL_SIGN 6 +#define X509_PURPOSE_ANY 7 +#define X509_PURPOSE_OCSP_HELPER 8 +#define X509_PURPOSE_TIMESTAMP_SIGN 9 + +#define X509_PURPOSE_MIN 1 +#define X509_PURPOSE_MAX 9 + +DEFINE_STACK_OF(X509_PURPOSE) + +DECLARE_ASN1_FUNCTIONS_const(BASIC_CONSTRAINTS) + +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID) + +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(GENERAL_NAME) +OPENSSL_EXPORT GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a); + +// i2v_GENERAL_NAME serializes |gen| as a |CONF_VALUE|. If |ret| is non-NULL, it +// appends the value to |ret| and returns |ret| on success or NULL on error. If +// it returns NULL, the caller is still responsible for freeing |ret|. If |ret| +// is NULL, it returns a newly-allocated |STACK_OF(CONF_VALUE)| containing the +// result. |method| is ignored. +// +// Do not use this function. This is an internal implementation detail of the +// human-readable print functions. If extracting a SAN list from a certificate, +// look at |gen| directly. +OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME( + const X509V3_EXT_METHOD *method, const GENERAL_NAME *gen, + STACK_OF(CONF_VALUE) *ret); + +// GENERAL_NAME_print prints a human-readable representation of |gen| to |out|. +// It returns one on success and zero on error. +// +// TODO(davidben): Actually, it just returns one and doesn't check for I/O or +// allocation errors. But it should return zero on error. +OPENSSL_EXPORT int GENERAL_NAME_print(BIO *out, const GENERAL_NAME *gen); + +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES) + +// i2v_GENERAL_NAMES serializes |gen| as a list of |CONF_VALUE|s. If |ret| is +// non-NULL, it appends the values to |ret| and returns |ret| on success or NULL +// on error. If it returns NULL, the caller is still responsible for freeing +// |ret|. If |ret| is NULL, it returns a newly-allocated |STACK_OF(CONF_VALUE)| +// containing the results. |method| is ignored. +// +// Do not use this function. This is an internal implementation detail of the +// human-readable print functions. If extracting a SAN list from a certificate, +// look at |gen| directly. +OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES( + const X509V3_EXT_METHOD *method, const GENERAL_NAMES *gen, + STACK_OF(CONF_VALUE) *extlist); +OPENSSL_EXPORT GENERAL_NAMES *v2i_GENERAL_NAMES( + const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx, + const STACK_OF(CONF_VALUE) *nval); + +DECLARE_ASN1_FUNCTIONS_const(OTHERNAME) +DECLARE_ASN1_FUNCTIONS_const(EDIPARTYNAME) +OPENSSL_EXPORT void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, + void *value); +OPENSSL_EXPORT void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype); +OPENSSL_EXPORT int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, + ASN1_OBJECT *oid, + ASN1_TYPE *value); +OPENSSL_EXPORT int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, + ASN1_OBJECT **poid, + ASN1_TYPE **pvalue); + +// i2s_ASN1_OCTET_STRING returns a human-readable representation of |oct| as a +// newly-allocated, NUL-terminated string, or NULL on error. |method| is +// ignored. The caller must release the result with |OPENSSL_free| when done. +OPENSSL_EXPORT char *i2s_ASN1_OCTET_STRING(const X509V3_EXT_METHOD *method, + const ASN1_OCTET_STRING *oct); + +OPENSSL_EXPORT ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING( + const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx, const char *str); + +DECLARE_ASN1_FUNCTIONS_const(EXTENDED_KEY_USAGE) +OPENSSL_EXPORT int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a); + +DECLARE_ASN1_FUNCTIONS_const(CERTIFICATEPOLICIES) +DECLARE_ASN1_FUNCTIONS_const(POLICYINFO) +DECLARE_ASN1_FUNCTIONS_const(POLICYQUALINFO) +DECLARE_ASN1_FUNCTIONS_const(USERNOTICE) +DECLARE_ASN1_FUNCTIONS_const(NOTICEREF) + +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS) +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(DIST_POINT) +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME) +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT) + +OPENSSL_EXPORT int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, + X509_NAME *iname); + +OPENSSL_EXPORT int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc); + +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) +// TODO(https://crbug.com/boringssl/407): This is not const because it contains +// an |X509_NAME|. +DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) + +DECLARE_ASN1_ITEM(POLICY_MAPPING) +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING) +DECLARE_ASN1_ITEM(POLICY_MAPPINGS) + +DECLARE_ASN1_ITEM(GENERAL_SUBTREE) +DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE) + +DECLARE_ASN1_ITEM(NAME_CONSTRAINTS) +DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS) + +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS) +DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS) + +OPENSSL_EXPORT GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + const X509V3_CTX *ctx, int gen_type, + const char *value, int is_nc); + +OPENSSL_EXPORT GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, + const X509V3_CTX *ctx, + const CONF_VALUE *cnf); +OPENSSL_EXPORT GENERAL_NAME *v2i_GENERAL_NAME_ex( + GENERAL_NAME *out, const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx, + const CONF_VALUE *cnf, int is_nc); +OPENSSL_EXPORT void X509V3_conf_free(CONF_VALUE *val); + + +// Deprecated config-based extension creation. +// +// The following functions allow specifying X.509 extensions using OpenSSL's +// config file syntax, from the OpenSSL command-line tool. They are retained, +// for now, for compatibility with legacy software but may be removed in the +// future. Construct the extensions using the typed C APIs instead. +// +// Callers should especially avoid these functions if passing in non-constant +// values. They use ad-hoc, string-based formats which are prone to injection +// vulnerabilities. For a CA, this means using them risks misissuance. +// +// These functions are not safe to use with untrusted inputs. The string formats +// may implicitly reference context information and, in OpenSSL (though not +// BoringSSL), one even allows reading arbitrary files. They additionally see +// much less testing and review than most of the library and may have bugs +// including memory leaks or crashes. + +// v3_ext_ctx, aka |X509V3_CTX|, contains additional context information for +// constructing extensions. Some string formats reference additional values in +// these objects. It must be initialized with |X509V3_set_ctx| or +// |X509V3_set_ctx_test| before use. +struct v3_ext_ctx { + int flags; + const X509 *issuer_cert; + const X509 *subject_cert; + const X509_REQ *subject_req; + const X509_CRL *crl; + const CONF *db; +}; + +#define X509V3_CTX_TEST 0x1 + +// X509V3_set_ctx initializes |ctx| with the specified objects. Some string +// formats will reference fields in these objects. Each object may be NULL to +// omit it, in which case those formats cannot be used. |flags| should be zero, +// unless called via |X509V3_set_ctx_test|. +// +// |issuer|, |subject|, |req|, and |crl|, if non-NULL, must outlive |ctx|. +OPENSSL_EXPORT void X509V3_set_ctx(X509V3_CTX *ctx, const X509 *issuer, + const X509 *subject, const X509_REQ *req, + const X509_CRL *crl, int flags); + +// X509V3_set_ctx_test calls |X509V3_set_ctx| without any reference objects and +// mocks out some features that use them. The resulting extensions may be +// incomplete and should be discarded. This can be used to partially validate +// syntax. +// +// TODO(davidben): Can we remove this? +#define X509V3_set_ctx_test(ctx) \ + X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, X509V3_CTX_TEST) + +// X509V3_set_nconf sets |ctx| to use |conf| as the config database. |ctx| must +// have previously been initialized by |X509V3_set_ctx| or +// |X509V3_set_ctx_test|. Some string formats will reference sections in |conf|. +// |conf| may be NULL, in which case these formats cannot be used. If non-NULL, +// |conf| must outlive |ctx|. +OPENSSL_EXPORT void X509V3_set_nconf(X509V3_CTX *ctx, const CONF *conf); + +// X509V3_set_ctx_nodb calls |X509V3_set_nconf| with no config database. +#define X509V3_set_ctx_nodb(ctx) X509V3_set_nconf(ctx, NULL) + +// X509V3_EXT_nconf constructs an extension of type specified by |name|, and +// value specified by |value|. It returns a newly-allocated |X509_EXTENSION| +// object on success, or NULL on error. |conf| and |ctx| specify additional +// information referenced by some formats. Either |conf| or |ctx| may be NULL, +// in which case features which use it will be disabled. +// +// If non-NULL, |ctx| must be initialized with |X509V3_set_ctx| or +// |X509V3_set_ctx_test|. +// +// Both |conf| and |ctx| provide a |CONF| object. When |ctx| is non-NULL, most +// features use the |ctx| copy, configured with |X509V3_set_ctx|, but some use +// |conf|. Callers should ensure the two match to avoid surprisingly behavior. +OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf(const CONF *conf, + const X509V3_CTX *ctx, + const char *name, + const char *value); + +// X509V3_EXT_nconf_nid behaves like |X509V3_EXT_nconf|, except the extension +// type is specified as a NID. +OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf_nid(const CONF *conf, + const X509V3_CTX *ctx, + int ext_nid, + const char *value); + +// X509V3_EXT_conf_nid calls |X509V3_EXT_nconf_nid|. |conf| must be NULL. +// +// TODO(davidben): This is the only exposed instance of an LHASH in our public +// headers. cryptography.io wraps this function so we cannot, yet, replace the +// type with a dummy struct. +OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, + const X509V3_CTX *ctx, + int ext_nid, + const char *value); + +// X509V3_EXT_add_nconf_sk looks up the section named |section| in |conf|. For +// each |CONF_VALUE| in the section, it constructs an extension as in +// |X509V3_EXT_nconf|, taking |name| and |value| from the |CONF_VALUE|. Each new +// extension is appended to |*sk|. If |*sk| is non-NULL, and at least one +// extension is added, it sets |*sk| to a newly-allocated +// |STACK_OF(X509_EXTENSION)|. It returns one on success and zero on error. +OPENSSL_EXPORT int X509V3_EXT_add_nconf_sk(const CONF *conf, + const X509V3_CTX *ctx, + const char *section, + STACK_OF(X509_EXTENSION) **sk); + +// X509V3_EXT_add_nconf adds extensions to |cert| as in +// |X509V3_EXT_add_nconf_sk|. It returns one on success and zero on error. +OPENSSL_EXPORT int X509V3_EXT_add_nconf(const CONF *conf, const X509V3_CTX *ctx, + const char *section, X509 *cert); + +// X509V3_EXT_REQ_add_nconf adds extensions to |req| as in +// |X509V3_EXT_add_nconf_sk|. It returns one on success and zero on error. +OPENSSL_EXPORT int X509V3_EXT_REQ_add_nconf(const CONF *conf, + const X509V3_CTX *ctx, + const char *section, X509_REQ *req); + +// X509V3_EXT_CRL_add_nconf adds extensions to |crl| as in +// |X509V3_EXT_add_nconf_sk|. It returns one on success and zero on error. +OPENSSL_EXPORT int X509V3_EXT_CRL_add_nconf(const CONF *conf, + const X509V3_CTX *ctx, + const char *section, X509_CRL *crl); + + +OPENSSL_EXPORT char *i2s_ASN1_INTEGER(const X509V3_EXT_METHOD *meth, + const ASN1_INTEGER *aint); +OPENSSL_EXPORT ASN1_INTEGER *s2i_ASN1_INTEGER(const X509V3_EXT_METHOD *meth, + const char *value); +OPENSSL_EXPORT char *i2s_ASN1_ENUMERATED(const X509V3_EXT_METHOD *meth, + const ASN1_ENUMERATED *aint); + +// X509V3_EXT_add registers |ext| as a custom extension for the extension type +// |ext->ext_nid|. |ext| must be valid for the remainder of the address space's +// lifetime. It returns one on success and zero on error. +// +// WARNING: This function modifies global state. If other code in the same +// address space also registers an extension with type |ext->ext_nid|, the two +// registrations will conflict. Which registration takes effect is undefined. If +// the two registrations use incompatible in-memory representations, code +// expecting the other registration will then cast a type to the wrong type, +// resulting in a potentially exploitable memory error. This conflict can also +// occur if BoringSSL later adds support for |ext->ext_nid|, with a different +// in-memory representation than the one expected by |ext|. +// +// This function, additionally, is not thread-safe and cannot be called +// concurrently with any other BoringSSL function. +// +// As a result, it is impossible to safely use this function. Registering a +// custom extension has no impact on certificate verification so, instead, +// callers should simply handle the custom extension with the byte-based +// |X509_EXTENSION| APIs directly. Registering |ext| with the library has little +// practical value. +OPENSSL_EXPORT OPENSSL_DEPRECATED int X509V3_EXT_add(X509V3_EXT_METHOD *ext); + +// X509V3_EXT_add_alias registers a custom extension with NID |nid_to|. The +// corresponding ASN.1 type is copied from |nid_from|. It returns one on success +// and zero on error. +// +// WARNING: Do not use this function. See |X509V3_EXT_add|. +OPENSSL_EXPORT OPENSSL_DEPRECATED int X509V3_EXT_add_alias(int nid_to, + int nid_from); + +OPENSSL_EXPORT const X509V3_EXT_METHOD *X509V3_EXT_get( + const X509_EXTENSION *ext); +OPENSSL_EXPORT const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid); +OPENSSL_EXPORT int X509V3_add_standard_extensions(void); + +// X509V3_EXT_d2i decodes |ext| and returns a pointer to a newly-allocated +// structure, with type dependent on the type of the extension. It returns NULL +// if |ext| is an unsupported extension or if there was a syntax error in the +// extension. The caller should cast the return value to the expected type and +// free the structure when done. +// +// WARNING: Casting the return value to the wrong type is a potentially +// exploitable memory error, so callers must not use this function before +// checking |ext| is of a known type. +OPENSSL_EXPORT void *X509V3_EXT_d2i(const X509_EXTENSION *ext); + +// X509V3_get_d2i finds and decodes the extension in |extensions| of type |nid|. +// If found, it decodes it and returns a newly-allocated structure, with type +// dependent on |nid|. If the extension is not found or on error, it returns +// NULL. The caller may distinguish these cases using the |out_critical| value. +// +// If |out_critical| is not NULL, this function sets |*out_critical| to one if +// the extension is found and critical, zero if it is found and not critical, -1 +// if it is not found, and -2 if there is an invalid duplicate extension. Note +// this function may set |*out_critical| to one or zero and still return NULL if +// the extension is found but has a syntax error. +// +// If |out_idx| is not NULL, this function looks for the first occurrence of the +// extension after |*out_idx|. It then sets |*out_idx| to the index of the +// extension, or -1 if not found. If |out_idx| is non-NULL, duplicate extensions +// are not treated as an error. Callers, however, should not rely on this +// behavior as it may be removed in the future. Duplicate extensions are +// forbidden in RFC 5280. +// +// WARNING: This function is difficult to use correctly. Callers should pass a +// non-NULL |out_critical| and check both the return value and |*out_critical| +// to handle errors. If the return value is NULL and |*out_critical| is not -1, +// there was an error. Otherwise, the function succeeded and but may return NULL +// for a missing extension. Callers should pass NULL to |out_idx| so that +// duplicate extensions are handled correctly. +// +// Additionally, casting the return value to the wrong type is a potentially +// exploitable memory error, so callers must ensure the cast and |nid| match. +OPENSSL_EXPORT void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *extensions, + int nid, int *out_critical, int *out_idx); + +// X509V3_EXT_free casts |ext_data| into the type that corresponds to |nid| and +// releases memory associated with it. It returns one on success and zero if +// |nid| is not a known extension. +// +// WARNING: Casting |ext_data| to the wrong type is a potentially exploitable +// memory error, so callers must ensure |ext_data|'s type matches |nid|. +// +// TODO(davidben): OpenSSL upstream no longer exposes this function. Remove it? +OPENSSL_EXPORT int X509V3_EXT_free(int nid, void *ext_data); + +// X509V3_EXT_i2d casts |ext_struc| into the type that corresponds to +// |ext_nid|, serializes it, and returns a newly-allocated |X509_EXTENSION| +// object containing the serialization, or NULL on error. The |X509_EXTENSION| +// has OID |ext_nid| and is critical if |crit| is one. +// +// WARNING: Casting |ext_struc| to the wrong type is a potentially exploitable +// memory error, so callers must ensure |ext_struct|'s type matches |ext_nid|. +OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, + void *ext_struc); + +// The following constants control the behavior of |X509V3_add1_i2d| and related +// functions. + +// X509V3_ADD_OP_MASK can be ANDed with the flags to determine how duplicate +// extensions are processed. +#define X509V3_ADD_OP_MASK 0xfL + +// X509V3_ADD_DEFAULT causes the function to fail if the extension was already +// present. +#define X509V3_ADD_DEFAULT 0L + +// X509V3_ADD_APPEND causes the function to unconditionally appended the new +// extension to to the extensions list, even if there is a duplicate. +#define X509V3_ADD_APPEND 1L + +// X509V3_ADD_REPLACE causes the function to replace the existing extension, or +// append if it is not present. +#define X509V3_ADD_REPLACE 2L + +// X509V3_ADD_REPLACE causes the function to replace the existing extension and +// fail if it is not present. +#define X509V3_ADD_REPLACE_EXISTING 3L + +// X509V3_ADD_KEEP_EXISTING causes the function to succeed without replacing the +// extension if already present. +#define X509V3_ADD_KEEP_EXISTING 4L + +// X509V3_ADD_DELETE causes the function to remove the matching extension. No +// new extension is added. If there is no matching extension, the function +// fails. The |value| parameter is ignored in this mode. +#define X509V3_ADD_DELETE 5L + +// X509V3_ADD_SILENT may be ORed into one of the values above to indicate the +// function should not add to the error queue on duplicate or missing extension. +// The function will continue to return zero in those cases, and it will +// continue to return -1 and add to the error queue on other errors. +#define X509V3_ADD_SILENT 0x10 + +// X509V3_add1_i2d casts |value| to the type that corresponds to |nid|, +// serializes it, and appends it to the extension list in |*x|. If |*x| is NULL, +// it will set |*x| to a newly-allocated |STACK_OF(X509_EXTENSION)| as needed. +// The |crit| parameter determines whether the new extension is critical. +// |flags| may be some combination of the |X509V3_ADD_*| constants to control +// the function's behavior on duplicate extension. +// +// This function returns one on success, zero if the operation failed due to a +// missing or duplicate extension, and -1 on other errors. +// +// WARNING: Casting |value| to the wrong type is a potentially exploitable +// memory error, so callers must ensure |value|'s type matches |nid|. +OPENSSL_EXPORT int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, + void *value, int crit, unsigned long flags); + +#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) + +// X509V3_EXT_DEFAULT causes unknown extensions or syntax errors to return +// failure. +#define X509V3_EXT_DEFAULT 0 +// X509V3_EXT_ERROR_UNKNOWN causes unknown extensions or syntax errors to print +// as "" or "", respectively. +#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +// X509V3_EXT_PARSE_UNKNOWN is deprecated and behaves like +// |X509V3_EXT_DUMP_UNKNOWN|. +#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +// X509V3_EXT_DUMP_UNKNOWN causes unknown extensions to be displayed as a +// hexdump. +#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +OPENSSL_EXPORT void X509V3_EXT_val_prn(BIO *out, + const STACK_OF(CONF_VALUE) *val, + int indent, int ml); +OPENSSL_EXPORT int X509V3_EXT_print(BIO *out, const X509_EXTENSION *ext, + unsigned long flag, int indent); +OPENSSL_EXPORT int X509V3_EXT_print_fp(FILE *out, const X509_EXTENSION *ext, + int flag, int indent); + +// X509V3_extensions_print prints |title|, followed by a human-readable +// representation of |exts| to |out|. It returns one on success and zero on +// error. The output is indented by |indent| spaces. |flag| is one of the +// |X509V3_EXT_*| constants and controls printing of unknown extensions and +// syntax errors. +OPENSSL_EXPORT int X509V3_extensions_print(BIO *out, const char *title, + const STACK_OF(X509_EXTENSION) *exts, + unsigned long flag, int indent); + +OPENSSL_EXPORT int X509_check_ca(X509 *x); +OPENSSL_EXPORT int X509_check_purpose(X509 *x, int id, int ca); +OPENSSL_EXPORT int X509_supported_extension(const X509_EXTENSION *ex); +OPENSSL_EXPORT int X509_PURPOSE_set(int *p, int purpose); +OPENSSL_EXPORT int X509_check_issued(X509 *issuer, X509 *subject); +OPENSSL_EXPORT int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid); + +OPENSSL_EXPORT uint32_t X509_get_extension_flags(X509 *x); +OPENSSL_EXPORT uint32_t X509_get_key_usage(X509 *x); +OPENSSL_EXPORT uint32_t X509_get_extended_key_usage(X509 *x); + +// X509_get0_subject_key_id returns |x509|'s subject key identifier, if present. +// (See RFC 5280, section 4.2.1.2.) It returns NULL if the extension is not +// present or if some extension in |x509| was invalid. +// +// Note that decoding an |X509| object will not check for invalid extensions. To +// detect the error case, call |X509_get_extensions_flags| and check the +// |EXFLAG_INVALID| bit. +OPENSSL_EXPORT const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x509); + +// X509_get0_authority_key_id returns keyIdentifier of |x509|'s authority key +// identifier, if the extension and field are present. (See RFC 5280, +// section 4.2.1.1.) It returns NULL if the extension is not present, if it is +// present but lacks a keyIdentifier field, or if some extension in |x509| was +// invalid. +// +// Note that decoding an |X509| object will not check for invalid extensions. To +// detect the error case, call |X509_get_extensions_flags| and check the +// |EXFLAG_INVALID| bit. +OPENSSL_EXPORT const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x509); + +// X509_get0_authority_issuer returns the authorityCertIssuer of |x509|'s +// authority key identifier, if the extension and field are present. (See +// RFC 5280, section 4.2.1.1.) It returns NULL if the extension is not present, +// if it is present but lacks a authorityCertIssuer field, or if some extension +// in |x509| was invalid. +// +// Note that decoding an |X509| object will not check for invalid extensions. To +// detect the error case, call |X509_get_extensions_flags| and check the +// |EXFLAG_INVALID| bit. +OPENSSL_EXPORT const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x509); + +// X509_get0_authority_serial returns the authorityCertSerialNumber of |x509|'s +// authority key identifier, if the extension and field are present. (See +// RFC 5280, section 4.2.1.1.) It returns NULL if the extension is not present, +// if it is present but lacks a authorityCertSerialNumber field, or if some +// extension in |x509| was invalid. +// +// Note that decoding an |X509| object will not check for invalid extensions. To +// detect the error case, call |X509_get_extensions_flags| and check the +// |EXFLAG_INVALID| bit. +OPENSSL_EXPORT const ASN1_INTEGER *X509_get0_authority_serial(X509 *x509); + +OPENSSL_EXPORT int X509_PURPOSE_get_count(void); +OPENSSL_EXPORT X509_PURPOSE *X509_PURPOSE_get0(int idx); +OPENSSL_EXPORT int X509_PURPOSE_get_by_sname(char *sname); +OPENSSL_EXPORT int X509_PURPOSE_get_by_id(int id); +OPENSSL_EXPORT int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck)(const X509_PURPOSE *, + const X509 *, int), + char *name, char *sname, void *arg); +OPENSSL_EXPORT char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp); +OPENSSL_EXPORT char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp); +OPENSSL_EXPORT int X509_PURPOSE_get_trust(const X509_PURPOSE *xp); +OPENSSL_EXPORT void X509_PURPOSE_cleanup(void); +OPENSSL_EXPORT int X509_PURPOSE_get_id(const X509_PURPOSE *); + +OPENSSL_EXPORT STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x); +OPENSSL_EXPORT STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x); +OPENSSL_EXPORT void X509_email_free(STACK_OF(OPENSSL_STRING) *sk); +OPENSSL_EXPORT STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x); +// Flags for X509_check_* functions + +// Deprecated: this flag does nothing +#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0 +// Disable wildcard matching for dnsName fields and common name. +#define X509_CHECK_FLAG_NO_WILDCARDS 0x2 +// X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS does nothing, but is necessary in +// OpenSSL to enable standard wildcard matching. In BoringSSL, this behavior is +// always enabled. +#define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0 +// Deprecated: this flag does nothing +#define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0 +// Deprecated: this flag does nothing +#define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0 +// Skip the subject common name fallback if subjectAltNames is missing. +#define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20 + +OPENSSL_EXPORT int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername); +OPENSSL_EXPORT int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags); +OPENSSL_EXPORT int X509_check_ip(X509 *x, const unsigned char *chk, + size_t chklen, unsigned int flags); +OPENSSL_EXPORT int X509_check_ip_asc(X509 *x, const char *ipasc, + unsigned int flags); + +OPENSSL_EXPORT ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); +OPENSSL_EXPORT ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc); + +// BEGIN ERROR CODES +// The following lines are auto generated by the script mkerr.pl. Any changes +// made after this point may be overwritten when the script is next run. + + +#if defined(__cplusplus) +} // extern C + +extern "C++" { + +BSSL_NAMESPACE_BEGIN + +BORINGSSL_MAKE_DELETER(ACCESS_DESCRIPTION, ACCESS_DESCRIPTION_free) +BORINGSSL_MAKE_DELETER(AUTHORITY_KEYID, AUTHORITY_KEYID_free) +BORINGSSL_MAKE_DELETER(BASIC_CONSTRAINTS, BASIC_CONSTRAINTS_free) +// TODO(davidben): Move this to conf.h and rename to CONF_VALUE_free. +BORINGSSL_MAKE_DELETER(CONF_VALUE, X509V3_conf_free) +BORINGSSL_MAKE_DELETER(DIST_POINT, DIST_POINT_free) +BORINGSSL_MAKE_DELETER(GENERAL_NAME, GENERAL_NAME_free) +BORINGSSL_MAKE_DELETER(GENERAL_SUBTREE, GENERAL_SUBTREE_free) +BORINGSSL_MAKE_DELETER(NAME_CONSTRAINTS, NAME_CONSTRAINTS_free) +BORINGSSL_MAKE_DELETER(POLICY_MAPPING, POLICY_MAPPING_free) +BORINGSSL_MAKE_DELETER(POLICYINFO, POLICYINFO_free) + +BSSL_NAMESPACE_END + +} // extern C++ +#endif + +#define X509V3_R_BAD_IP_ADDRESS 100 +#define X509V3_R_BAD_OBJECT 101 +#define X509V3_R_BN_DEC2BN_ERROR 102 +#define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 103 +#define X509V3_R_CANNOT_FIND_FREE_FUNCTION 104 +#define X509V3_R_DIRNAME_ERROR 105 +#define X509V3_R_DISTPOINT_ALREADY_SET 106 +#define X509V3_R_DUPLICATE_ZONE_ID 107 +#define X509V3_R_ERROR_CONVERTING_ZONE 108 +#define X509V3_R_ERROR_CREATING_EXTENSION 109 +#define X509V3_R_ERROR_IN_EXTENSION 110 +#define X509V3_R_EXPECTED_A_SECTION_NAME 111 +#define X509V3_R_EXTENSION_EXISTS 112 +#define X509V3_R_EXTENSION_NAME_ERROR 113 +#define X509V3_R_EXTENSION_NOT_FOUND 114 +#define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 115 +#define X509V3_R_EXTENSION_VALUE_ERROR 116 +#define X509V3_R_ILLEGAL_EMPTY_EXTENSION 117 +#define X509V3_R_ILLEGAL_HEX_DIGIT 118 +#define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 119 +#define X509V3_R_INVALID_BOOLEAN_STRING 120 +#define X509V3_R_INVALID_EXTENSION_STRING 121 +#define X509V3_R_INVALID_MULTIPLE_RDNS 122 +#define X509V3_R_INVALID_NAME 123 +#define X509V3_R_INVALID_NULL_ARGUMENT 124 +#define X509V3_R_INVALID_NULL_NAME 125 +#define X509V3_R_INVALID_NULL_VALUE 126 +#define X509V3_R_INVALID_NUMBER 127 +#define X509V3_R_INVALID_NUMBERS 128 +#define X509V3_R_INVALID_OBJECT_IDENTIFIER 129 +#define X509V3_R_INVALID_OPTION 130 +#define X509V3_R_INVALID_POLICY_IDENTIFIER 131 +#define X509V3_R_INVALID_PROXY_POLICY_SETTING 132 +#define X509V3_R_INVALID_PURPOSE 133 +#define X509V3_R_INVALID_SECTION 134 +#define X509V3_R_INVALID_SYNTAX 135 +#define X509V3_R_ISSUER_DECODE_ERROR 136 +#define X509V3_R_MISSING_VALUE 137 +#define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 138 +#define X509V3_R_NO_CONFIG_DATABASE 139 +#define X509V3_R_NO_ISSUER_CERTIFICATE 140 +#define X509V3_R_NO_ISSUER_DETAILS 141 +#define X509V3_R_NO_POLICY_IDENTIFIER 142 +#define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 143 +#define X509V3_R_NO_PUBLIC_KEY 144 +#define X509V3_R_NO_SUBJECT_DETAILS 145 +#define X509V3_R_ODD_NUMBER_OF_DIGITS 146 +#define X509V3_R_OPERATION_NOT_DEFINED 147 +#define X509V3_R_OTHERNAME_ERROR 148 +#define X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED 149 +#define X509V3_R_POLICY_PATH_LENGTH 150 +#define X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED 151 +#define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 152 +#define X509V3_R_SECTION_NOT_FOUND 153 +#define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 154 +#define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 155 +#define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 156 +#define X509V3_R_UNKNOWN_EXTENSION 157 +#define X509V3_R_UNKNOWN_EXTENSION_NAME 158 +#define X509V3_R_UNKNOWN_OPTION 159 +#define X509V3_R_UNSUPPORTED_OPTION 160 +#define X509V3_R_UNSUPPORTED_TYPE 161 +#define X509V3_R_USER_TOO_LONG 162 +#define X509V3_R_INVALID_VALUE 163 +#define X509V3_R_TRAILING_DATA_IN_EXTENSION 164 + +#endif // OPENSSL_HEADER_X509V3_H diff --git a/lib/boringssl/x86_64-apple-darwin/build/libcrypto.a b/lib/boringssl/x86_64-apple-darwin/build/libcrypto.a new file mode 100644 index 00000000..1641215a Binary files /dev/null and b/lib/boringssl/x86_64-apple-darwin/build/libcrypto.a differ diff --git a/lib/boringssl/x86_64-apple-darwin/build/libssl.a b/lib/boringssl/x86_64-apple-darwin/build/libssl.a new file mode 100644 index 00000000..8b1be062 Binary files /dev/null and b/lib/boringssl/x86_64-apple-darwin/build/libssl.a differ diff --git a/lib/boringssl/x86_64-apple-darwin/include b/lib/boringssl/x86_64-apple-darwin/include new file mode 120000 index 00000000..f5030fe8 --- /dev/null +++ b/lib/boringssl/x86_64-apple-darwin/include @@ -0,0 +1 @@ +../include \ No newline at end of file diff --git a/lib/boringssl/x86_64-pc-windows-msvc/build/crypto.lib b/lib/boringssl/x86_64-pc-windows-msvc/build/crypto.lib new file mode 100644 index 00000000..4f7d2fd6 Binary files /dev/null and b/lib/boringssl/x86_64-pc-windows-msvc/build/crypto.lib differ diff --git a/lib/boringssl/x86_64-pc-windows-msvc/build/ssl.lib b/lib/boringssl/x86_64-pc-windows-msvc/build/ssl.lib new file mode 100644 index 00000000..ccd4d0f6 Binary files /dev/null and b/lib/boringssl/x86_64-pc-windows-msvc/build/ssl.lib differ diff --git a/lib/boringssl/x86_64-pc-windows-msvc/include b/lib/boringssl/x86_64-pc-windows-msvc/include new file mode 120000 index 00000000..f5030fe8 --- /dev/null +++ b/lib/boringssl/x86_64-pc-windows-msvc/include @@ -0,0 +1 @@ +../include \ No newline at end of file diff --git a/lib/boringssl/x86_64-unknown-linux-gnu/build/libcrypto.a b/lib/boringssl/x86_64-unknown-linux-gnu/build/libcrypto.a new file mode 100644 index 00000000..2d1f9e28 Binary files /dev/null and b/lib/boringssl/x86_64-unknown-linux-gnu/build/libcrypto.a differ diff --git a/lib/boringssl/x86_64-unknown-linux-gnu/build/libssl.a b/lib/boringssl/x86_64-unknown-linux-gnu/build/libssl.a new file mode 100644 index 00000000..c23af8b0 Binary files /dev/null and b/lib/boringssl/x86_64-unknown-linux-gnu/build/libssl.a differ diff --git a/lib/boringssl/x86_64-unknown-linux-gnu/include b/lib/boringssl/x86_64-unknown-linux-gnu/include new file mode 120000 index 00000000..f5030fe8 --- /dev/null +++ b/lib/boringssl/x86_64-unknown-linux-gnu/include @@ -0,0 +1 @@ +../include \ No newline at end of file diff --git a/lib/boringssl/x86_64-unknown-linux-musl/build/libcrypto.a b/lib/boringssl/x86_64-unknown-linux-musl/build/libcrypto.a new file mode 100644 index 00000000..d894035d Binary files /dev/null and b/lib/boringssl/x86_64-unknown-linux-musl/build/libcrypto.a differ diff --git a/lib/boringssl/x86_64-unknown-linux-musl/build/libssl.a b/lib/boringssl/x86_64-unknown-linux-musl/build/libssl.a new file mode 100644 index 00000000..5814f4ee Binary files /dev/null and b/lib/boringssl/x86_64-unknown-linux-musl/build/libssl.a differ diff --git a/lib/boringssl/x86_64-unknown-linux-musl/include b/lib/boringssl/x86_64-unknown-linux-musl/include new file mode 120000 index 00000000..f5030fe8 --- /dev/null +++ b/lib/boringssl/x86_64-unknown-linux-musl/include @@ -0,0 +1 @@ +../include \ No newline at end of file diff --git a/scripts/build-boringssl.sh b/scripts/build-boringssl.sh new file mode 100755 index 00000000..dd999dc1 --- /dev/null +++ b/scripts/build-boringssl.sh @@ -0,0 +1,350 @@ +#!/bin/bash +# Pre-build BoringSSL for multiple targets using boring-sys's vendored source +# +# This script builds BoringSSL static libraries compatible with boring-sys. +# It uses the EXACT BoringSSL source that boring-sys bundles to ensure ABI compatibility. +# +# Structure created: +# lib/boringssl/ +# ├── include/openssl/ (headers from boring-sys's vendored source) +# ├── aarch64-apple-darwin/ +# │ ├── include -> ../include (symlink) +# │ ├── libcrypto.a +# │ └── libssl.a +# └── x86_64-pc-windows-msvc/ +# ├── include -> ../include (symlink) +# ├── crypto.lib +# └── ssl.lib +# +# Usage: +# ./scripts/build-boringssl.sh [target...] +# ./scripts/build-boringssl.sh # Build all targets +# ./scripts/build-boringssl.sh aarch64-apple-darwin +# +# Prerequisites: +# - cmake, ninja (or make) +# - boring-sys in cargo cache (run `cargo fetch` first) +# - Cross-compilation: zig (Linux targets), cargo-xwin (Windows targets) +# +# In your build, set: +# export BORING_BSSL_PATH=$PWD/lib/boringssl//build + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +LIB_DIR="$PROJECT_ROOT/lib/boringssl" + +# boring-sys version must match Cargo.lock +BORING_SYS_VERSION="4.19.0" + +# All supported targets +ALL_TARGETS=( + "aarch64-apple-darwin" + "x86_64-apple-darwin" + "x86_64-unknown-linux-gnu" + "x86_64-unknown-linux-musl" + "aarch64-unknown-linux-gnu" + "aarch64-unknown-linux-musl" + "x86_64-pc-windows-msvc" + "aarch64-pc-windows-msvc" +) + +log() { echo "[$(date '+%H:%M:%S')] $*"; } +error() { echo "[ERROR] $*" >&2; exit 1; } + +find_boring_sys_source() { + local cargo_home="${CARGO_HOME:-$HOME/.cargo}" + local registry_src="$cargo_home/registry/src" + + # Find boring-sys directory + local boring_sys_dir + boring_sys_dir=$(find "$registry_src" -maxdepth 2 -type d -name "boring-sys-$BORING_SYS_VERSION" 2>/dev/null | head -1) + + if [[ -z "$boring_sys_dir" ]] || [[ ! -d "$boring_sys_dir/deps/boringssl" ]]; then + log "boring-sys $BORING_SYS_VERSION not in cargo cache. Fetching..." + (cd "$PROJECT_ROOT" && cargo fetch) + boring_sys_dir=$(find "$registry_src" -maxdepth 2 -type d -name "boring-sys-$BORING_SYS_VERSION" 2>/dev/null | head -1) + fi + + if [[ -z "$boring_sys_dir" ]]; then + error "Could not find boring-sys $BORING_SYS_VERSION in cargo cache" + fi + + echo "$boring_sys_dir" +} + +copy_headers() { + local boring_sys_dir="$1" + local include_src="$boring_sys_dir/deps/boringssl/src/include" + local include_dst="$LIB_DIR/include" + + log "Copying headers from boring-sys vendored source..." + rm -rf "$include_dst" + mkdir -p "$include_dst" + cp -r "$include_src/openssl" "$include_dst/" + log "Headers installed to $include_dst" +} + +get_generator() { + if command -v ninja &>/dev/null; then + echo "Ninja" + else + echo "Unix Makefiles" + fi +} + +build_native_macos() { + local target="$1" + local boring_sys_dir="$2" + local build_dir="$3" + local output_dir="$LIB_DIR/$target" + + log "Building $target (native macOS)..." + + local arch + case "$target" in + aarch64-apple-darwin) arch="arm64" ;; + x86_64-apple-darwin) arch="x86_64" ;; + esac + + local src_dir="$boring_sys_dir/deps/boringssl" + + rm -rf "$build_dir" + mkdir -p "$build_dir" + cd "$build_dir" + + local generator=$(get_generator) + + cmake -G "$generator" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_OSX_ARCHITECTURES="$arch" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \ + "$src_dir" + + if [[ "$generator" == "Ninja" ]]; then + ninja crypto ssl + else + make -j"$(sysctl -n hw.ncpu)" crypto ssl + fi + + mkdir -p "$output_dir/build" + cp libcrypto.a "$output_dir/build/" 2>/dev/null || cp crypto/libcrypto.a "$output_dir/build/" + cp libssl.a "$output_dir/build/" 2>/dev/null || cp ssl/libssl.a "$output_dir/build/" + + # Symlink to shared headers + ln -sf ../include "$output_dir/include" + + log "Built: $output_dir/build/{libcrypto.a, libssl.a}" +} + +build_linux_zig() { + local target="$1" + local boring_sys_dir="$2" + local build_dir="$3" + local output_dir="$LIB_DIR/$target" + + if ! command -v zig &>/dev/null; then + log "SKIP $target: zig not found (brew install zig)" + return 0 + fi + + log "Building $target (cross-compile with zig)..." + + local zig_target + case "$target" in + x86_64-unknown-linux-gnu) zig_target="x86_64-linux-gnu" ;; + x86_64-unknown-linux-musl) zig_target="x86_64-linux-musl" ;; + aarch64-unknown-linux-gnu) zig_target="aarch64-linux-gnu" ;; + aarch64-unknown-linux-musl) zig_target="aarch64-linux-musl" ;; + esac + + local src_dir="$boring_sys_dir/deps/boringssl" + + rm -rf "$build_dir" + mkdir -p "$build_dir" + cd "$build_dir" + + # Create zig wrapper scripts + cat > zig-cc << EOF +#!/bin/bash +exec zig cc -target $zig_target "\$@" +EOF + cat > zig-cxx << EOF +#!/bin/bash +exec zig c++ -target $zig_target "\$@" +EOF + cat > zig-ar << EOF +#!/bin/bash +exec zig ar "\$@" +EOF + cat > zig-ranlib << EOF +#!/bin/bash +exec zig ranlib "\$@" +EOF + chmod +x zig-cc zig-cxx zig-ar zig-ranlib + + local generator=$(get_generator) + local arch="${target%%-*}" + + CC="$build_dir/zig-cc" CXX="$build_dir/zig-cxx" \ + cmake -G "$generator" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DCMAKE_SYSTEM_PROCESSOR="$arch" \ + -DCMAKE_C_COMPILER="$build_dir/zig-cc" \ + -DCMAKE_CXX_COMPILER="$build_dir/zig-cxx" \ + -DCMAKE_AR="$build_dir/zig-ar" \ + -DCMAKE_RANLIB="$build_dir/zig-ranlib" \ + "$src_dir" + + if [[ "$generator" == "Ninja" ]]; then + ninja crypto ssl + else + make -j"$(nproc 2>/dev/null || sysctl -n hw.ncpu)" crypto ssl + fi + + mkdir -p "$output_dir/build" + cp libcrypto.a "$output_dir/build/" 2>/dev/null || cp crypto/libcrypto.a "$output_dir/build/" + cp libssl.a "$output_dir/build/" 2>/dev/null || cp ssl/libssl.a "$output_dir/build/" + ln -sf ../include "$output_dir/include" + + log "Built: $output_dir/build/{libcrypto.a, libssl.a}" +} + +build_windows_xwin() { + local target="$1" + local boring_sys_dir="$2" + local build_dir="$3" + local output_dir="$LIB_DIR/$target" + + log "Building $target (Windows via cargo-xwin)..." + + # For Windows, the easiest approach is to let cargo-xwin build boring-sys + # and then extract the libraries from the target directory + + if ! command -v cargo &>/dev/null; then + log "SKIP $target: cargo not found" + return 0 + fi + + # Check if we already have libs from a previous cargo xwin build + local cargo_target="${CARGO_TARGET_DIR:-$HOME/.cache/cargo/target}" + local existing_lib + existing_lib=$(ls -t "$cargo_target/$target/release/build"/boring-sys-*/out/build/crypto.lib 2>/dev/null | head -1 || true) + + if [[ -n "$existing_lib" ]]; then + local lib_dir + lib_dir=$(dirname "$existing_lib") + log "Found existing build at $lib_dir" + mkdir -p "$output_dir/build" + cp "$lib_dir/crypto.lib" "$output_dir/build/" + cp "$lib_dir/ssl.lib" "$output_dir/build/" + ln -sf ../include "$output_dir/include" + log "Copied: $output_dir/build/{crypto.lib, ssl.lib}" + return 0 + fi + + # Need to trigger a cargo xwin build + log "No cached build found. Run: cargo xwin build --release --target $target" + log "Then re-run this script to extract the libraries." + + mkdir -p "$output_dir" + ln -sf ../include "$output_dir/include" + + return 0 +} + +build_target() { + local target="$1" + local boring_sys_dir="$2" + local build_dir="$PROJECT_ROOT/.boringssl-build/$target" + + case "$target" in + aarch64-apple-darwin|x86_64-apple-darwin) + build_native_macos "$target" "$boring_sys_dir" "$build_dir" + ;; + x86_64-unknown-linux-*|aarch64-unknown-linux-*) + build_linux_zig "$target" "$boring_sys_dir" "$build_dir" + ;; + *-pc-windows-msvc) + build_windows_xwin "$target" "$boring_sys_dir" "$build_dir" + ;; + *) + log "SKIP $target: unsupported" + ;; + esac +} + +print_usage() { + cat << 'EOF' +Usage: ./scripts/build-boringssl.sh [OPTIONS] [TARGET...] + +Build BoringSSL static libraries from boring-sys's vendored source. + +OPTIONS: + --help Show this help + --list List available targets + --clean Remove build artifacts + +TARGETS: + aarch64-apple-darwin macOS ARM64 + x86_64-apple-darwin macOS x86_64 + x86_64-unknown-linux-gnu Linux x86_64 (glibc) + x86_64-unknown-linux-musl Linux x86_64 (musl) + aarch64-unknown-linux-gnu Linux ARM64 (glibc) + aarch64-unknown-linux-musl Linux ARM64 (musl) + x86_64-pc-windows-msvc Windows x86_64 + aarch64-pc-windows-msvc Windows ARM64 + +USAGE IN BUILD: + export BORING_BSSL_PATH=$PWD/lib/boringssl//build + cargo build --target +EOF +} + +main() { + local targets=() + + while [[ $# -gt 0 ]]; do + case "$1" in + --help|-h) print_usage; exit 0 ;; + --list) printf '%s\n' "${ALL_TARGETS[@]}"; exit 0 ;; + --clean) + log "Cleaning..." + rm -rf "$PROJECT_ROOT/.boringssl-build" + rm -rf "$LIB_DIR" + exit 0 + ;; + -*) error "Unknown option: $1" ;; + *) targets+=("$1"); shift ;; + esac + done + + [[ ${#targets[@]} -eq 0 ]] && targets=("${ALL_TARGETS[@]}") + + local boring_sys_dir + boring_sys_dir=$(find_boring_sys_source) + log "Using boring-sys source: $boring_sys_dir" + + mkdir -p "$LIB_DIR" + copy_headers "$boring_sys_dir" + + log "Building ${#targets[@]} target(s)..." + + for target in "${targets[@]}"; do + log "" + log "=== $target ===" + build_target "$target" "$boring_sys_dir" + done + + log "" + log "=== Complete ===" + log "Libraries: $LIB_DIR//" + log "" + log "Usage:" + log " export BORING_BSSL_PATH=\$PWD/lib/boringssl//build" + log " cargo build" +} + +main "$@" diff --git a/scripts/env.sh b/scripts/env.sh new file mode 100644 index 00000000..ca32422e --- /dev/null +++ b/scripts/env.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# Source this file to configure environment for prebuilt BoringSSL +# +# Usage: +# source scripts/env.sh # Auto-detect target +# source scripts/env.sh # Specific target +# +# Examples: +# source scripts/env.sh +# source scripts/env.sh x86_64-pc-windows-msvc +# source scripts/env.sh aarch64-unknown-linux-gnu + +# Handle both bash and zsh +if [[ -n "${BASH_SOURCE[0]:-}" ]]; then + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +elif [[ -n "${(%):-%x}" ]]; then + # zsh + SCRIPT_DIR="$(cd "$(dirname "${(%):-%x}")" && pwd)" +else + # Fallback: assume we're in the project root + SCRIPT_DIR="$(pwd)/scripts" +fi +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +LIB_DIR="$PROJECT_ROOT/lib/boringssl" + +# Detect current target if not specified +detect_target() { + local arch os + + arch=$(uname -m) + os=$(uname -s) + + case "$os" in + Darwin) + case "$arch" in + arm64) echo "aarch64-apple-darwin" ;; + x86_64) echo "x86_64-apple-darwin" ;; + *) echo "unknown" ;; + esac + ;; + Linux) + # Check if musl or glibc + if ldd --version 2>&1 | grep -q musl; then + case "$arch" in + x86_64) echo "x86_64-unknown-linux-musl" ;; + aarch64) echo "aarch64-unknown-linux-musl" ;; + *) echo "unknown" ;; + esac + else + case "$arch" in + x86_64) echo "x86_64-unknown-linux-gnu" ;; + aarch64) echo "aarch64-unknown-linux-gnu" ;; + *) echo "unknown" ;; + esac + fi + ;; + MINGW*|MSYS*|CYGWIN*) + case "$arch" in + x86_64) echo "x86_64-pc-windows-msvc" ;; + aarch64) echo "aarch64-pc-windows-msvc" ;; + *) echo "unknown" ;; + esac + ;; + *) + echo "unknown" + ;; + esac +} + +# Get target from argument or auto-detect +TARGET="${1:-$(detect_target)}" + +if [[ "$TARGET" == "unknown" ]]; then + echo "Error: Could not detect target platform" >&2 + echo "Please specify target: source scripts/env.sh " >&2 + return 1 2>/dev/null || exit 1 +fi + +# Check if prebuilt libraries exist for this target +TARGET_LIB_DIR="$LIB_DIR/$TARGET" +TARGET_BUILD_DIR="$TARGET_LIB_DIR/build" +INCLUDE_DIR="$LIB_DIR/include" + +# Check if directory exists AND contains library files +has_libs() { + local dir="$1" + [[ -d "$dir" ]] || return 1 + # Use find to avoid zsh nomatch errors + [[ -n "$(find "$dir" -maxdepth 1 \( -name '*.a' -o -name '*.lib' \) 2>/dev/null | head -1)" ]] +} + +if has_libs "$TARGET_BUILD_DIR"; then + BORING_LINK_DIR="$TARGET_BUILD_DIR" +elif has_libs "$TARGET_LIB_DIR"; then + BORING_LINK_DIR="$TARGET_LIB_DIR" +else + echo "Warning: No prebuilt BoringSSL for $TARGET" >&2 + echo "Available targets:" >&2 + for d in "$LIB_DIR"/*/; do + [[ "$(basename "$d")" == "include" ]] && continue + if has_libs "$d/build" || has_libs "$d"; then + echo " $(basename "$d")" >&2 + fi + done + echo "" >&2 + echo "Build with: ./scripts/build-boringssl.sh $TARGET" >&2 + return 1 2>/dev/null || exit 1 +fi + +if [[ ! -d "$INCLUDE_DIR" ]]; then + echo "Warning: No BoringSSL headers found at $INCLUDE_DIR" >&2 + echo "Run: ./scripts/build-boringssl.sh to build headers" >&2 + return 1 2>/dev/null || exit 1 +fi + +# Export environment variables for boring-sys +export BORING_BSSL_PATH="$BORING_LINK_DIR" +export BORING_BSSL_INCLUDE_PATH="$INCLUDE_DIR" + +echo "BoringSSL configured for: $TARGET" +echo " BORING_BSSL_PATH=$BORING_BSSL_PATH" +echo " BORING_BSSL_INCLUDE_PATH=$BORING_BSSL_INCLUDE_PATH" + +# For cross-compilation, also set target-specific vars +case "$TARGET" in + *-linux-gnu|*-linux-musl) + # These help with cross-compilation from macOS + export "BORING_BSSL_PATH_${TARGET//-/_}"="$BORING_LINK_DIR" + ;; +esac diff --git a/scripts/extract-boringssl.sh b/scripts/extract-boringssl.sh new file mode 100644 index 00000000..95762ca6 --- /dev/null +++ b/scripts/extract-boringssl.sh @@ -0,0 +1,261 @@ +#!/bin/bash +# Extract prebuilt BoringSSL libraries from cargo build cache +# +# This script runs cargo build for specter and extracts the BoringSSL libraries +# that boring-sys builds. This ensures ABI compatibility with boring-sys. +# +# Usage: +# ./scripts/extract-boringssl.sh # Build for host target +# ./scripts/extract-boringssl.sh aarch64-apple-darwin +# ./scripts/extract-boringssl.sh --all # Build all targets +# +# Prerequisites: +# - Rust toolchain with targets installed +# - zig (for Linux cross-compilation) +# - cargo-xwin (for Windows cross-compilation) + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +LIB_DIR="$PROJECT_ROOT/lib/boringssl" +CARGO_TARGET="${CARGO_TARGET_DIR:-$HOME/.cache/cargo/target}" + +# All supported targets +ALL_TARGETS=( + "aarch64-apple-darwin" + "x86_64-apple-darwin" + "x86_64-unknown-linux-gnu" + "x86_64-unknown-linux-musl" + "aarch64-unknown-linux-gnu" + "x86_64-pc-windows-msvc" + "aarch64-pc-windows-msvc" +) + +log() { + echo "[$(date '+%H:%M:%S')] $*" +} + +error() { + echo "[ERROR] $*" >&2 + exit 1 +} + +detect_host_target() { + local arch os + arch=$(uname -m) + os=$(uname -s) + + case "$os-$arch" in + Darwin-arm64) echo "aarch64-apple-darwin" ;; + Darwin-x86_64) echo "x86_64-apple-darwin" ;; + Linux-x86_64) echo "x86_64-unknown-linux-gnu" ;; + Linux-aarch64) echo "aarch64-unknown-linux-gnu" ;; + *) echo "unknown" ;; + esac +} + +build_and_extract() { + local target="$1" + local output_dir="$LIB_DIR/$target" + local is_windows=false + + [[ "$target" == *windows* ]] && is_windows=true + + log "Building for $target..." + + mkdir -p "$output_dir" + + # Build with cargo (or cargo-xwin for Windows) + cd "$PROJECT_ROOT" + + case "$target" in + *-apple-darwin) + cargo build --release --target "$target" -p specter 2>&1 | tail -5 + ;; + *-unknown-linux-gnu|*-unknown-linux-musl) + # Use zigbuild for Linux cross-compilation + if ! command -v cargo-zigbuild &>/dev/null; then + log "Installing cargo-zigbuild..." + cargo install cargo-zigbuild + fi + cargo zigbuild --release --target "$target" -p specter 2>&1 | tail -5 + ;; + *-pc-windows-msvc) + # Use cargo-xwin for Windows + if ! command -v cargo-xwin &>/dev/null; then + log "Installing cargo-xwin..." + cargo install cargo-xwin + fi + cargo xwin build --release --target "$target" -p specter 2>&1 | tail -5 + ;; + *) + error "Unknown target: $target" + ;; + esac + + # Find and extract the built BoringSSL libraries + local boring_build_dir + boring_build_dir=$(ls -td "$CARGO_TARGET/$target/release/build/boring-sys-"*/out/build 2>/dev/null | head -1) + + if [[ -z "$boring_build_dir" || ! -d "$boring_build_dir" ]]; then + error "BoringSSL build output not found for $target in $CARGO_TARGET" + fi + + log "Extracting from: $boring_build_dir" + + if $is_windows; then + cp "$boring_build_dir/crypto.lib" "$output_dir/" 2>/dev/null || \ + cp "$boring_build_dir/Release/crypto.lib" "$output_dir/" 2>/dev/null || \ + error "crypto.lib not found" + + cp "$boring_build_dir/ssl.lib" "$output_dir/" 2>/dev/null || \ + cp "$boring_build_dir/Release/ssl.lib" "$output_dir/" 2>/dev/null || \ + error "ssl.lib not found" + + log "Extracted: $output_dir/crypto.lib, $output_dir/ssl.lib" + else + cp "$boring_build_dir/libcrypto.a" "$output_dir/" 2>/dev/null || \ + error "libcrypto.a not found" + + cp "$boring_build_dir/libssl.a" "$output_dir/" 2>/dev/null || \ + error "libssl.a not found" + + log "Extracted: $output_dir/libcrypto.a, $output_dir/libssl.a" + fi + + # Create include symlink + ln -sf ../include "$output_dir/include" 2>/dev/null || true +} + +extract_headers() { + local include_dir="$LIB_DIR/include" + + # Get headers from boring-sys's vendored source + local boring_sys_dir + boring_sys_dir=$(find "${CARGO_HOME:-$HOME/.cargo}/registry/src" -maxdepth 2 -type d -name "boring-sys-4.*" 2>/dev/null | sort -V | tail -1) + + if [[ -z "$boring_sys_dir" ]]; then + log "Fetching boring-sys..." + cargo fetch -p boring-sys + boring_sys_dir=$(find "${CARGO_HOME:-$HOME/.cargo}/registry/src" -maxdepth 2 -type d -name "boring-sys-4.*" 2>/dev/null | sort -V | tail -1) + fi + + local vendored_include="$boring_sys_dir/deps/boringssl/src/include" + if [[ ! -d "$vendored_include" ]]; then + error "BoringSSL headers not found in $vendored_include" + fi + + log "Copying headers from boring-sys..." + rm -rf "$include_dir" + mkdir -p "$include_dir" + cp -r "$vendored_include/openssl" "$include_dir/" + + log "Headers in: $include_dir" +} + +print_usage() { + cat << 'EOF' +Usage: ./scripts/extract-boringssl.sh [OPTIONS] [TARGET...] + +Extract prebuilt BoringSSL from cargo build cache. + +OPTIONS: + --help Show this help + --all Build and extract for all targets + --clean Remove all extracted libraries + --headers-only Only extract headers + +TARGETS: + aarch64-apple-darwin macOS ARM64 (Apple Silicon) + x86_64-apple-darwin macOS x86_64 + x86_64-unknown-linux-gnu Linux x86_64 (glibc) + x86_64-unknown-linux-musl Linux x86_64 (musl) + aarch64-unknown-linux-gnu Linux ARM64 (glibc) + x86_64-pc-windows-msvc Windows x86_64 + aarch64-pc-windows-msvc Windows ARM64 + +EXAMPLES: + ./scripts/extract-boringssl.sh # Host target only + ./scripts/extract-boringssl.sh --all # All targets + ./scripts/extract-boringssl.sh aarch64-apple-darwin x86_64-apple-darwin + +After extraction, set this env var when building with boring-sys: + export BORING_BSSL_PATH=$PWD/lib/boringssl//build +EOF +} + +main() { + local targets=() + local headers_only=false + + while [[ $# -gt 0 ]]; do + case "$1" in + --help|-h) + print_usage + exit 0 + ;; + --all) + targets=("${ALL_TARGETS[@]}") + shift + ;; + --clean) + log "Cleaning $LIB_DIR..." + rm -rf "$LIB_DIR" + log "Done" + exit 0 + ;; + --headers-only) + headers_only=true + shift + ;; + -*) + error "Unknown option: $1" + ;; + *) + targets+=("$1") + shift + ;; + esac + done + + # Default to host target if none specified + if [[ ${#targets[@]} -eq 0 && "$headers_only" == "false" ]]; then + targets=("$(detect_host_target)") + fi + + mkdir -p "$LIB_DIR" + + # Always extract headers first + extract_headers + + if $headers_only; then + exit 0 + fi + + local success=0 + local failed=0 + + for target in "${targets[@]}"; do + log "" + log "=== $target ===" + if build_and_extract "$target"; then + ((success++)) + else + ((failed++)) + fi + done + + log "" + log "=== Summary ===" + log "Success: $success" + log "Failed: $failed" + log "" + log "Libraries: $LIB_DIR//" + log "Headers: $LIB_DIR/include/" + log "" + log "To use with boring-sys:" + log " export BORING_BSSL_PATH=$LIB_DIR//build" +} + +main "$@" diff --git a/scripts/zig-cc-aarch64-linux-gnu b/scripts/zig-cc-aarch64-linux-gnu new file mode 100755 index 00000000..1b9cd7e0 --- /dev/null +++ b/scripts/zig-cc-aarch64-linux-gnu @@ -0,0 +1,19 @@ +#!/bin/bash +# Wrapper script for zig cc that: +# 1. Uses the correct Zig target (aarch64-linux-gnu) +# 2. Strips conflicting --target=aarch64-unknown-linux-gnu flags from cmake/boring-sys +# 3. Handles both compilation and assembly + +args=() +for arg in "$@"; do + case "$arg" in + --target=aarch64-unknown-linux-gnu) ;; # Strip Rust-style target + --target=*-unknown-linux-*) ;; # Strip any Rust-style Linux target + -target) ;; # Skip standalone -target (zig uses different format) + aarch64-unknown-linux-gnu) ;; # Skip if target is passed as separate arg + cc) ;; # Skip stray 'cc' argument passed by Cargo/build scripts + *) args+=("$arg") ;; + esac +done + +exec zig cc -target aarch64-linux-gnu "${args[@]}" diff --git a/scripts/zig-cc-aarch64-linux-musl b/scripts/zig-cc-aarch64-linux-musl new file mode 100755 index 00000000..4c5568c1 --- /dev/null +++ b/scripts/zig-cc-aarch64-linux-musl @@ -0,0 +1,19 @@ +#!/bin/bash +# Wrapper script for zig cc that: +# 1. Uses the correct Zig target (aarch64-linux-musl) +# 2. Strips conflicting --target=aarch64-unknown-linux-musl flags from cmake/boring-sys +# 3. Handles both compilation and assembly + +args=() +for arg in "$@"; do + case "$arg" in + --target=aarch64-unknown-linux-musl) ;; # Strip Rust-style target + --target=*-unknown-linux-*) ;; # Strip any Rust-style Linux target + -target) ;; # Skip standalone -target (zig uses different format) + aarch64-unknown-linux-musl) ;; # Skip if target is passed as separate arg + cc) ;; # Skip stray 'cc' argument passed by Cargo/build scripts + *) args+=("$arg") ;; + esac +done + +exec zig cc -target aarch64-linux-musl "${args[@]}" diff --git a/scripts/zig-cc-x86_64-linux-gnu b/scripts/zig-cc-x86_64-linux-gnu new file mode 100755 index 00000000..a8f12ac9 --- /dev/null +++ b/scripts/zig-cc-x86_64-linux-gnu @@ -0,0 +1,19 @@ +#!/bin/bash +# Wrapper script for zig cc that: +# 1. Uses the correct Zig target (x86_64-linux-gnu) +# 2. Strips conflicting --target=x86_64-unknown-linux-gnu flags from cmake/boring-sys +# 3. Handles both compilation and assembly + +args=() +for arg in "$@"; do + case "$arg" in + --target=x86_64-unknown-linux-gnu) ;; # Strip Rust-style target + --target=*-unknown-linux-*) ;; # Strip any Rust-style Linux target + -target) ;; # Skip standalone -target (zig uses different format) + x86_64-unknown-linux-gnu) ;; # Skip if target is passed as separate arg + cc) ;; # Skip stray 'cc' argument passed by Cargo/build scripts + *) args+=("$arg") ;; + esac +done + +exec zig cc -target x86_64-linux-gnu "${args[@]}" diff --git a/scripts/zig-cc-x86_64-linux-musl b/scripts/zig-cc-x86_64-linux-musl new file mode 100755 index 00000000..3a692257 --- /dev/null +++ b/scripts/zig-cc-x86_64-linux-musl @@ -0,0 +1,19 @@ +#!/bin/bash +# Wrapper script for zig cc that: +# 1. Uses the correct Zig target (x86_64-linux-musl) +# 2. Strips conflicting --target=x86_64-unknown-linux-musl flags from cmake/boring-sys +# 3. Handles both compilation and assembly + +args=() +for arg in "$@"; do + case "$arg" in + --target=x86_64-unknown-linux-musl) ;; # Strip Rust-style target + --target=*-unknown-linux-*) ;; # Strip any Rust-style Linux target + -target) ;; # Skip standalone -target (zig uses different format) + x86_64-unknown-linux-musl) ;; # Skip if target is passed as separate arg + cc) ;; # Skip stray 'cc' argument passed by Cargo/build scripts + *) args+=("$arg") ;; + esac +done + +exec zig cc -target x86_64-linux-musl "${args[@]}" diff --git a/scripts/zig-cxx-aarch64-linux-gnu b/scripts/zig-cxx-aarch64-linux-gnu new file mode 100755 index 00000000..8e1dc1ed --- /dev/null +++ b/scripts/zig-cxx-aarch64-linux-gnu @@ -0,0 +1,18 @@ +#!/bin/bash +# Wrapper script for zig c++ that: +# 1. Uses the correct Zig target (aarch64-linux-gnu) +# 2. Strips conflicting --target=aarch64-unknown-linux-gnu flags from cmake/boring-sys +# 3. Handles both compilation and assembly + +args=() +for arg in "$@"; do + case "$arg" in + --target=aarch64-unknown-linux-gnu) ;; # Strip Rust-style target + --target=*-unknown-linux-*) ;; # Strip any Rust-style Linux target + -target) ;; # Skip standalone -target (zig uses different format) + aarch64-unknown-linux-gnu) ;; # Skip if target is passed as separate arg + *) args+=("$arg") ;; + esac +done + +exec zig c++ -target aarch64-linux-gnu "${args[@]}" diff --git a/scripts/zig-cxx-aarch64-linux-musl b/scripts/zig-cxx-aarch64-linux-musl new file mode 100755 index 00000000..50f58962 --- /dev/null +++ b/scripts/zig-cxx-aarch64-linux-musl @@ -0,0 +1,18 @@ +#!/bin/bash +# Wrapper script for zig c++ that: +# 1. Uses the correct Zig target (aarch64-linux-musl) +# 2. Strips conflicting --target=aarch64-unknown-linux-musl flags from cmake/boring-sys +# 3. Handles both compilation and assembly + +args=() +for arg in "$@"; do + case "$arg" in + --target=aarch64-unknown-linux-musl) ;; # Strip Rust-style target + --target=*-unknown-linux-*) ;; # Strip any Rust-style Linux target + -target) ;; # Skip standalone -target (zig uses different format) + aarch64-unknown-linux-musl) ;; # Skip if target is passed as separate arg + *) args+=("$arg") ;; + esac +done + +exec zig c++ -target aarch64-linux-musl "${args[@]}" diff --git a/scripts/zig-cxx-x86_64-linux-gnu b/scripts/zig-cxx-x86_64-linux-gnu new file mode 100755 index 00000000..3089355c --- /dev/null +++ b/scripts/zig-cxx-x86_64-linux-gnu @@ -0,0 +1,18 @@ +#!/bin/bash +# Wrapper script for zig c++ that: +# 1. Uses the correct Zig target (x86_64-linux-gnu) +# 2. Strips conflicting --target=x86_64-unknown-linux-gnu flags from cmake/boring-sys +# 3. Handles both compilation and assembly + +args=() +for arg in "$@"; do + case "$arg" in + --target=x86_64-unknown-linux-gnu) ;; # Strip Rust-style target + --target=*-unknown-linux-*) ;; # Strip any Rust-style Linux target + -target) ;; # Skip standalone -target (zig uses different format) + x86_64-unknown-linux-gnu) ;; # Skip if target is passed as separate arg + *) args+=("$arg") ;; + esac +done + +exec zig c++ -target x86_64-linux-gnu "${args[@]}" diff --git a/scripts/zig-cxx-x86_64-linux-musl b/scripts/zig-cxx-x86_64-linux-musl new file mode 100755 index 00000000..f7e183cd --- /dev/null +++ b/scripts/zig-cxx-x86_64-linux-musl @@ -0,0 +1,18 @@ +#!/bin/bash +# Wrapper script for zig c++ that: +# 1. Uses the correct Zig target (x86_64-linux-musl) +# 2. Strips conflicting --target=x86_64-unknown-linux-musl flags from cmake/boring-sys +# 3. Handles both compilation and assembly + +args=() +for arg in "$@"; do + case "$arg" in + --target=x86_64-unknown-linux-musl) ;; # Strip Rust-style target + --target=*-unknown-linux-*) ;; # Strip any Rust-style Linux target + -target) ;; # Skip standalone -target (zig uses different format) + x86_64-unknown-linux-musl) ;; # Skip if target is passed as separate arg + *) args+=("$arg") ;; + esac +done + +exec zig c++ -target x86_64-linux-musl "${args[@]}" diff --git a/src/cookie.rs b/src/cookie.rs index b90768b3..b7b1ed44 100644 --- a/src/cookie.rs +++ b/src/cookie.rs @@ -11,6 +11,7 @@ use chrono::{DateTime, TimeZone, Utc}; use url::Url; use crate::error::{Error, Result}; +use crate::headers::Headers; /// SameSite attribute for cookies (RFC 6265bis). /// @@ -430,12 +431,9 @@ impl CookieJar { ) } - pub fn store_from_headers(&mut self, headers: &[String], request_url: &str) { - for header in headers { - if let Some(value) = header - .strip_prefix("Set-Cookie:") - .or_else(|| header.strip_prefix("set-cookie:")) - { + pub fn store_from_headers(&mut self, headers: &Headers, request_url: &str) { + for (name, value) in headers.iter() { + if name.eq_ignore_ascii_case("set-cookie") { if let Ok(cookie) = Cookie::from_set_cookie_header(value.trim(), request_url) { self.store(cookie); } diff --git a/src/error.rs b/src/error.rs index 66f98ca0..9ca6b9ee 100644 --- a/src/error.rs +++ b/src/error.rs @@ -40,6 +40,10 @@ pub enum Error { #[error("JSON error: {0}")] Json(#[from] serde_json::Error), + /// URL encoding error. + #[error("URL encoding error: {0}")] + UrlEncode(#[from] serde_urlencoded::ser::Error), + /// IO error. #[error("IO error: {0}")] Io(#[from] io::Error), @@ -88,6 +92,18 @@ pub enum Error { #[error("QUIC error: {0}")] Quic(String), + /// SOCKS5 proxy error. + #[error("SOCKS5 proxy error: {0}")] + Socks5(String), + + /// HTTP CONNECT proxy error. + #[error("HTTP CONNECT proxy error: {0}")] + HttpConnectProxy(String), + + /// Generic proxy error. + #[error("Proxy error: {0}")] + Proxy(String), + /// HTTP/2 SETTINGS_TIMEOUT error (RFC 9113 Section 7). #[error("SETTINGS_TIMEOUT (0x04): No SETTINGS frame received within {0:?}")] SettingsTimeout(std::time::Duration), @@ -136,4 +152,19 @@ impl Error { pub fn quic(message: impl Into) -> Self { Self::Quic(message.into()) } + + /// Create a SOCKS5 proxy error. + pub fn socks5(message: impl Into) -> Self { + Self::Socks5(message.into()) + } + + /// Create an HTTP CONNECT proxy error. + pub fn http_connect_proxy(message: impl Into) -> Self { + Self::HttpConnectProxy(message.into()) + } + + /// Create a proxy error. + pub fn proxy(message: impl Into) -> Self { + Self::Proxy(message.into()) + } } diff --git a/src/fingerprint/profiles.rs b/src/fingerprint/profiles.rs index 4219e6f7..2f8c2ce7 100644 --- a/src/fingerprint/profiles.rs +++ b/src/fingerprint/profiles.rs @@ -10,11 +10,17 @@ use super::tls::TlsFingerprint; /// systems use JA4 which sorts extensions alphabetically for stable fingerprints. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum FingerprintProfile { - /// Chrome 142 on macOS - basic fingerprint (cipher suites, curves, sigalgs) - /// TLS extension order is randomized by Chrome, so this fingerprint - /// will not match real Chrome exactly. + /// Chrome 142 on macOS #[default] Chrome142, + /// Chrome 143 on macOS + Chrome143, + /// Chrome 144 on macOS + Chrome144, + /// Chrome 145 on macOS + Chrome145, + /// Chrome 146 on macOS (current stable, March 2026) + Chrome146, /// Firefox 133 on macOS - basic fingerprint (cipher suites, curves, sigalgs) /// TLS extension order is randomized by Firefox, so this fingerprint /// will not match real Firefox exactly. Firefox does NOT use GREASE. @@ -30,6 +36,18 @@ impl FingerprintProfile { Self::Chrome142 => { "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" } + Self::Chrome143 => { + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" + } + Self::Chrome144 => { + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36" + } + Self::Chrome145 => { + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36" + } + Self::Chrome146 => { + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36" + } Self::Firefox133 => { "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0" } @@ -40,7 +58,11 @@ impl FingerprintProfile { /// Get the TLS fingerprint for this profile. pub fn tls_fingerprint(&self) -> TlsFingerprint { match self { - FingerprintProfile::Chrome142 => TlsFingerprint::chrome_142(), + FingerprintProfile::Chrome142 + | FingerprintProfile::Chrome143 + | FingerprintProfile::Chrome144 + | FingerprintProfile::Chrome145 + | FingerprintProfile::Chrome146 => TlsFingerprint::chrome(), FingerprintProfile::Firefox133 => TlsFingerprint::firefox_133(), FingerprintProfile::None => TlsFingerprint::default(), } @@ -49,7 +71,11 @@ impl FingerprintProfile { /// Get the HTTP/2 settings for this profile. pub fn http2_settings(&self) -> Http2Settings { match self { - FingerprintProfile::Chrome142 => Http2Settings::default(), + FingerprintProfile::Chrome142 + | FingerprintProfile::Chrome143 + | FingerprintProfile::Chrome144 + | FingerprintProfile::Chrome145 + | FingerprintProfile::Chrome146 => Http2Settings::default(), FingerprintProfile::Firefox133 => Http2Settings::firefox(), FingerprintProfile::None => Http2Settings::default(), } diff --git a/src/fingerprint/tls.rs b/src/fingerprint/tls.rs index 9d50da28..2a9008ec 100644 --- a/src/fingerprint/tls.rs +++ b/src/fingerprint/tls.rs @@ -6,7 +6,7 @@ //! signature algorithm, and curve ordering - but extension ordering may not //! match real browsers. //! -//! Current implementation: Chrome 142 (Dec 2025) +//! Current implementation: Chrome 142-146, Firefox 133 //! //! ## Post-Quantum Cryptography (Kyber) //! @@ -18,8 +18,9 @@ //! To verify Kyber support, check if connections show "X25519Kyber768" in the key //! exchange algorithm when connecting to servers that support it (e.g., Google, Cloudflare). -/// Chrome 142 cipher suites in exact order. -pub const CHROME_142_CIPHER_SUITES: &[&str] = &[ +/// Chrome 142-146 cipher suites in exact order. +/// Unchanged across Chrome 142 through 146. +pub const CHROME_CIPHER_SUITES: &[&str] = &[ "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256", @@ -37,8 +38,12 @@ pub const CHROME_142_CIPHER_SUITES: &[&str] = &[ "TLS_RSA_WITH_AES_256_CBC_SHA", ]; -/// Chrome 142 signature algorithms. -pub const CHROME_142_SIGNATURE_ALGORITHMS: &[&str] = &[ +/// Backwards-compatible alias for Chrome 142 cipher suites. +pub const CHROME_142_CIPHER_SUITES: &[&str] = CHROME_CIPHER_SUITES; + +/// Chrome 142-146 signature algorithms. +/// Unchanged across Chrome 142 through 146. +pub const CHROME_SIGNATURE_ALGORITHMS: &[&str] = &[ "ecdsa_secp256r1_sha256", "rsa_pss_rsae_sha256", "rsa_pkcs1_sha256", @@ -49,13 +54,24 @@ pub const CHROME_142_SIGNATURE_ALGORITHMS: &[&str] = &[ "rsa_pkcs1_sha512", ]; -/// Chrome 142 supported curves. -pub const CHROME_142_CURVES: &[&str] = &["x25519", "P-256", "P-384"]; +/// Backwards-compatible alias for Chrome 142 signature algorithms. +pub const CHROME_142_SIGNATURE_ALGORITHMS: &[&str] = CHROME_SIGNATURE_ALGORITHMS; + +/// Chrome 142-146 supported curves. +/// Unchanged across Chrome 142 through 146. +pub const CHROME_CURVES: &[&str] = &["x25519", "P-256", "P-384"]; + +/// Backwards-compatible alias for Chrome 142 curves. +pub const CHROME_142_CURVES: &[&str] = CHROME_CURVES; -/// Chrome 142 extension IDs in exact order. -pub const CHROME_142_EXTENSION_IDS: &[u16] = +/// Chrome 142-146 extension IDs in exact order. +/// Unchanged across Chrome 142 through 146. +pub const CHROME_EXTENSION_IDS: &[u16] = &[0, 23, 65281, 10, 11, 35, 16, 5, 13, 18, 51, 45, 43, 27, 21]; +/// Backwards-compatible alias for Chrome 142 extension IDs. +pub const CHROME_142_EXTENSION_IDS: &[u16] = CHROME_EXTENSION_IDS; + /// Firefox 133 cipher suites in exact order. /// Firefox prefers AES-GCM over ChaCha20 (unlike some mobile-optimized builds). pub const FIREFOX_133_CIPHER_SUITES: &[&str] = &[ @@ -155,20 +171,46 @@ impl Default for TlsFingerprint { } impl TlsFingerprint { - /// Create a TLS fingerprint for Chrome 142. - pub fn chrome_142() -> Self { + /// Create a TLS fingerprint matching Chrome 142-146. + /// The TLS configuration is identical across these versions. + pub fn chrome() -> Self { Self { - cipher_list: CHROME_142_CIPHER_SUITES.to_vec(), - sigalgs: CHROME_142_SIGNATURE_ALGORITHMS.to_vec(), - curves: CHROME_142_CURVES.to_vec(), - extensions: CHROME_142_EXTENSION_IDS.to_vec(), - extension_order: CHROME_142_EXTENSION_IDS.to_vec(), + cipher_list: CHROME_CIPHER_SUITES.to_vec(), + sigalgs: CHROME_SIGNATURE_ALGORITHMS.to_vec(), + curves: CHROME_CURVES.to_vec(), + extensions: CHROME_EXTENSION_IDS.to_vec(), + extension_order: CHROME_EXTENSION_IDS.to_vec(), grease: true, - cert_compression: CertCompression::Brotli, // Chrome uses Brotli certificate compression - enable_kyber: true, // Chrome 124+ enables post-quantum Kyber by default + cert_compression: CertCompression::Brotli, + enable_kyber: true, } } + /// Create a TLS fingerprint for Chrome 142. + pub fn chrome_142() -> Self { + Self::chrome() + } + + /// Create a TLS fingerprint for Chrome 143. + pub fn chrome_143() -> Self { + Self::chrome() + } + + /// Create a TLS fingerprint for Chrome 144. + pub fn chrome_144() -> Self { + Self::chrome() + } + + /// Create a TLS fingerprint for Chrome 145. + pub fn chrome_145() -> Self { + Self::chrome() + } + + /// Create a TLS fingerprint for Chrome 146. + pub fn chrome_146() -> Self { + Self::chrome() + } + /// Create a TLS fingerprint for Firefox 133. /// /// Firefox differs from Chrome in: diff --git a/src/headers.rs b/src/headers.rs index 474197fa..b8d185c7 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -1,8 +1,10 @@ //! Browser header presets for HTTP requests. //! -//! Current implementation: Chrome 142 (Dec 2025) +//! Supported Chrome versions: 142, 143, 144, 145, 146 +//! Supported Firefox versions: 133 use crate::cookie::CookieJar; +use http::HeaderMap; /// Chrome 142 browser headers for page navigation. pub fn chrome_142_headers() -> Vec<(&'static str, &'static str)> { @@ -74,42 +76,305 @@ pub fn chrome_142_form_headers() -> Vec<(&'static str, &'static str)> { ] } +/// Chrome 143 browser headers for page navigation. +pub fn chrome_143_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"), + ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Sec-Fetch-Dest", "document"), + ("Sec-Fetch-Mode", "navigate"), + ("Sec-Fetch-Site", "none"), + ("Sec-Fetch-User", "?1"), + ("Sec-Ch-Ua", r#""Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="99""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Sec-Ch-Ua-Arch", r#""arm64""#), + ("Sec-Ch-Ua-Bitness", r#""64""#), + ("Sec-Ch-Ua-Full-Version-List", r#""Google Chrome";v="143.0.7499.40", "Chromium";v="143.0.7499.40", "Not A(Brand";v="99.0.0.0""#), + ("Sec-Ch-Ua-Model", r#""""#), + ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#), + ("Sec-Ch-Ua-Wow64", "?0"), + ("Upgrade-Insecure-Requests", "1"), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 143 headers for AJAX/API requests. +pub fn chrome_143_ajax_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"), + ("Accept", "application/json, text/plain, */*"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Content-Type", "application/json"), + ("Sec-Fetch-Dest", "empty"), + ("Sec-Fetch-Mode", "cors"), + ("Sec-Fetch-Site", "same-origin"), + ("Sec-Ch-Ua", r#""Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="99""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 143 headers for form submissions. +pub fn chrome_143_form_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"), + ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Content-Type", "application/x-www-form-urlencoded"), + ("Sec-Fetch-Dest", "document"), + ("Sec-Fetch-Mode", "navigate"), + ("Sec-Fetch-Site", "same-origin"), + ("Sec-Ch-Ua", r#""Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="99""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Sec-Ch-Ua-Arch", r#""arm64""#), + ("Sec-Ch-Ua-Bitness", r#""64""#), + ("Sec-Ch-Ua-Full-Version-List", r#""Google Chrome";v="143.0.7499.40", "Chromium";v="143.0.7499.40", "Not A(Brand";v="99.0.0.0""#), + ("Sec-Ch-Ua-Model", r#""""#), + ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#), + ("Sec-Ch-Ua-Wow64", "?0"), + ("Upgrade-Insecure-Requests", "1"), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 144 browser headers for page navigation. +pub fn chrome_144_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36"), + ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Sec-Fetch-Dest", "document"), + ("Sec-Fetch-Mode", "navigate"), + ("Sec-Fetch-Site", "none"), + ("Sec-Fetch-User", "?1"), + ("Sec-Ch-Ua", r#""Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Sec-Ch-Ua-Arch", r#""arm64""#), + ("Sec-Ch-Ua-Bitness", r#""64""#), + ("Sec-Ch-Ua-Full-Version-List", r#""Not(A:Brand";v="8.0.0.0", "Chromium";v="144.0.7559.133", "Google Chrome";v="144.0.7559.133""#), + ("Sec-Ch-Ua-Model", r#""""#), + ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#), + ("Sec-Ch-Ua-Wow64", "?0"), + ("Upgrade-Insecure-Requests", "1"), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 144 headers for AJAX/API requests. +pub fn chrome_144_ajax_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36"), + ("Accept", "application/json, text/plain, */*"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Content-Type", "application/json"), + ("Sec-Fetch-Dest", "empty"), + ("Sec-Fetch-Mode", "cors"), + ("Sec-Fetch-Site", "same-origin"), + ("Sec-Ch-Ua", r#""Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 144 headers for form submissions. +pub fn chrome_144_form_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36"), + ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Content-Type", "application/x-www-form-urlencoded"), + ("Sec-Fetch-Dest", "document"), + ("Sec-Fetch-Mode", "navigate"), + ("Sec-Fetch-Site", "same-origin"), + ("Sec-Ch-Ua", r#""Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Sec-Ch-Ua-Arch", r#""arm64""#), + ("Sec-Ch-Ua-Bitness", r#""64""#), + ("Sec-Ch-Ua-Full-Version-List", r#""Not(A:Brand";v="8.0.0.0", "Chromium";v="144.0.7559.133", "Google Chrome";v="144.0.7559.133""#), + ("Sec-Ch-Ua-Model", r#""""#), + ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#), + ("Sec-Ch-Ua-Wow64", "?0"), + ("Upgrade-Insecure-Requests", "1"), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 145 browser headers for page navigation. +pub fn chrome_145_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"), + ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Sec-Fetch-Dest", "document"), + ("Sec-Fetch-Mode", "navigate"), + ("Sec-Fetch-Site", "none"), + ("Sec-Fetch-User", "?1"), + ("Sec-Ch-Ua", r#""Not:A-Brand";v="24", "Google Chrome";v="145", "Chromium";v="145""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Sec-Ch-Ua-Arch", r#""arm64""#), + ("Sec-Ch-Ua-Bitness", r#""64""#), + ("Sec-Ch-Ua-Full-Version-List", r#""Not:A-Brand";v="24.0.0.0", "Google Chrome";v="145.0.7632.117", "Chromium";v="145.0.7632.117""#), + ("Sec-Ch-Ua-Model", r#""""#), + ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#), + ("Sec-Ch-Ua-Wow64", "?0"), + ("Upgrade-Insecure-Requests", "1"), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 145 headers for AJAX/API requests. +pub fn chrome_145_ajax_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"), + ("Accept", "application/json, text/plain, */*"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Content-Type", "application/json"), + ("Sec-Fetch-Dest", "empty"), + ("Sec-Fetch-Mode", "cors"), + ("Sec-Fetch-Site", "same-origin"), + ("Sec-Ch-Ua", r#""Not:A-Brand";v="24", "Google Chrome";v="145", "Chromium";v="145""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 145 headers for form submissions. +pub fn chrome_145_form_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"), + ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Content-Type", "application/x-www-form-urlencoded"), + ("Sec-Fetch-Dest", "document"), + ("Sec-Fetch-Mode", "navigate"), + ("Sec-Fetch-Site", "same-origin"), + ("Sec-Ch-Ua", r#""Not:A-Brand";v="24", "Google Chrome";v="145", "Chromium";v="145""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Sec-Ch-Ua-Arch", r#""arm64""#), + ("Sec-Ch-Ua-Bitness", r#""64""#), + ("Sec-Ch-Ua-Full-Version-List", r#""Not:A-Brand";v="24.0.0.0", "Google Chrome";v="145.0.7632.117", "Chromium";v="145.0.7632.117""#), + ("Sec-Ch-Ua-Model", r#""""#), + ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#), + ("Sec-Ch-Ua-Wow64", "?0"), + ("Upgrade-Insecure-Requests", "1"), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 146 browser headers for page navigation. +pub fn chrome_146_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"), + ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Sec-Fetch-Dest", "document"), + ("Sec-Fetch-Mode", "navigate"), + ("Sec-Fetch-Site", "none"), + ("Sec-Fetch-User", "?1"), + ("Sec-Ch-Ua", r#""Chromium";v="146", "Not-A.Brand";v="99", "Google Chrome";v="146""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Sec-Ch-Ua-Arch", r#""arm64""#), + ("Sec-Ch-Ua-Bitness", r#""64""#), + ("Sec-Ch-Ua-Full-Version-List", r#""Chromium";v="146.0.7680.165", "Not-A.Brand";v="99.0.0.0", "Google Chrome";v="146.0.7680.165""#), + ("Sec-Ch-Ua-Model", r#""""#), + ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#), + ("Sec-Ch-Ua-Wow64", "?0"), + ("Upgrade-Insecure-Requests", "1"), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 146 headers for AJAX/API requests. +pub fn chrome_146_ajax_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"), + ("Accept", "application/json, text/plain, */*"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Content-Type", "application/json"), + ("Sec-Fetch-Dest", "empty"), + ("Sec-Fetch-Mode", "cors"), + ("Sec-Fetch-Site", "same-origin"), + ("Sec-Ch-Ua", r#""Chromium";v="146", "Not-A.Brand";v="99", "Google Chrome";v="146""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Connection", "keep-alive"), + ] +} + +/// Chrome 146 headers for form submissions. +pub fn chrome_146_form_headers() -> Vec<(&'static str, &'static str)> { + vec![ + ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"), + ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"), + ("Accept-Language", "en-US,en;q=0.9"), + ("Accept-Encoding", "gzip, deflate, br, zstd"), + ("Content-Type", "application/x-www-form-urlencoded"), + ("Sec-Fetch-Dest", "document"), + ("Sec-Fetch-Mode", "navigate"), + ("Sec-Fetch-Site", "same-origin"), + ("Sec-Ch-Ua", r#""Chromium";v="146", "Not-A.Brand";v="99", "Google Chrome";v="146""#), + ("Sec-Ch-Ua-Mobile", "?0"), + ("Sec-Ch-Ua-Platform", r#""macOS""#), + ("Sec-Ch-Ua-Arch", r#""arm64""#), + ("Sec-Ch-Ua-Bitness", r#""64""#), + ("Sec-Ch-Ua-Full-Version-List", r#""Chromium";v="146.0.7680.165", "Not-A.Brand";v="99.0.0.0", "Google Chrome";v="146.0.7680.165""#), + ("Sec-Ch-Ua-Model", r#""""#), + ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#), + ("Sec-Ch-Ua-Wow64", "?0"), + ("Upgrade-Insecure-Requests", "1"), + ("Connection", "keep-alive"), + ] +} + /// Add Cookie header from jar. -pub fn with_cookies( - base: Vec<(&'static str, &'static str)>, - url: &str, - jar: &CookieJar, -) -> Vec<(String, String)> { - let mut headers: Vec<(String, String)> = base - .into_iter() - .map(|(k, v)| (k.to_string(), v.to_string())) - .collect(); +pub fn with_cookies(base: impl Into, url: &str, jar: &CookieJar) -> Headers { + let mut headers: Headers = base.into(); + headers.remove("cookie"); if let Some(cookie_header) = jar.build_cookie_header(url) { - headers.push(("Cookie".to_string(), cookie_header)); + headers.append("Cookie", cookie_header); } headers } /// Add Origin header. -pub fn with_origin(mut headers: Vec<(String, String)>, origin: &str) -> Vec<(String, String)> { - headers.retain(|(k, _)| k.to_lowercase() != "origin"); - headers.push(("Origin".to_string(), origin.to_string())); +pub fn with_origin(mut headers: Headers, origin: &str) -> Headers { + headers.remove("origin"); + headers.append("Origin", origin.to_string()); headers } /// Add Referer header. -pub fn with_referer(mut headers: Vec<(String, String)>, referer: &str) -> Vec<(String, String)> { - headers.retain(|(k, _)| k.to_lowercase() != "referer"); - headers.push(("Referer".to_string(), referer.to_string())); +pub fn with_referer(mut headers: Headers, referer: &str) -> Headers { + headers.remove("referer"); + headers.append("Referer", referer.to_string()); headers } /// Convert owned headers to references. -pub fn headers_as_refs(headers: &[(String, String)]) -> Vec<(&str, &str)> { - headers - .iter() - .map(|(k, v)| (k.as_str(), v.as_str())) - .collect() +pub fn headers_as_refs(headers: &Headers) -> Vec<(&str, &str)> { + headers.as_refs() } /// Convert static headers to owned. @@ -120,6 +385,154 @@ pub fn headers_to_owned(headers: Vec<(&'static str, &'static str)>) -> Vec<(Stri .collect() } +/// Ordered headers for requests and responses. +/// +/// This preserves insertion order for fingerprinting while providing +/// convenient lookup and mutation helpers. +#[derive(Debug, Clone, Default)] +pub struct Headers { + headers: Vec<(String, String)>, +} + +impl Headers { + pub fn new() -> Self { + Self::default() + } + + pub fn from_vec(headers: Vec<(String, String)>) -> Self { + Self { headers } + } + + pub fn from_static(headers: Vec<(&'static str, &'static str)>) -> Self { + Self { + headers: headers + .into_iter() + .map(|(k, v)| (k.to_string(), v.to_string())) + .collect(), + } + } + + pub fn len(&self) -> usize { + self.headers.len() + } + + pub fn is_empty(&self) -> bool { + self.headers.is_empty() + } + + pub fn insert(&mut self, name: impl Into, value: impl Into) { + let name = name.into(); + let name_lower = name.to_ascii_lowercase(); + self.headers + .retain(|(k, _)| k.to_ascii_lowercase() != name_lower); + self.headers.push((name, value.into())); + } + + pub fn append(&mut self, name: impl Into, value: impl Into) { + self.headers.push((name.into(), value.into())); + } + + pub fn remove(&mut self, name: &str) -> Option> { + let name_lower = name.to_ascii_lowercase(); + let mut removed = Vec::new(); + self.headers.retain(|(k, v)| { + if k.to_ascii_lowercase() == name_lower { + removed.push(v.clone()); + false + } else { + true + } + }); + if removed.is_empty() { + None + } else { + Some(removed) + } + } + + pub fn get(&self, name: &str) -> Option<&str> { + let name_lower = name.to_ascii_lowercase(); + self.headers.iter().find_map(|(k, v)| { + if k.to_ascii_lowercase() == name_lower { + Some(v.as_str()) + } else { + None + } + }) + } + + pub fn get_all(&self, name: &str) -> Vec<&str> { + let name_lower = name.to_ascii_lowercase(); + self.headers + .iter() + .filter_map(|(k, v)| { + if k.to_ascii_lowercase() == name_lower { + Some(v.as_str()) + } else { + None + } + }) + .collect() + } + + pub fn contains(&self, name: &str) -> bool { + self.get(name).is_some() + } + + pub fn iter(&self) -> impl Iterator { + self.headers.iter().map(|(k, v)| (k.as_str(), v.as_str())) + } + + pub fn iter_ordered(&self) -> impl Iterator { + self.iter() + } + + pub fn extend(&mut self, other: Headers) { + self.headers.extend(other.headers); + } + + pub fn as_slice(&self) -> &[(String, String)] { + &self.headers + } + + pub fn as_refs(&self) -> Vec<(&str, &str)> { + self.headers + .iter() + .map(|(k, v)| (k.as_str(), v.as_str())) + .collect() + } + + pub fn to_vec(&self) -> Vec<(String, String)> { + self.headers.clone() + } +} + +impl From> for Headers { + fn from(value: Vec<(String, String)>) -> Self { + Headers::from_vec(value) + } +} + +impl From> for Headers { + fn from(value: Vec<(&'static str, &'static str)>) -> Self { + Headers::from_static(value) + } +} + +impl From for Headers { + fn from(map: HeaderMap) -> Self { + let mut headers = Vec::new(); + for (name, value) in map.iter() { + let value = value + .to_str() + .map(|s| s.to_string()) + .unwrap_or_else(|_| String::from_utf8_lossy(value.as_bytes()).into_owned()); + headers.push((name.as_str().to_string(), value)); + } + Headers { headers } + } +} + /// Ordered headers with JA4H fingerprint calculation. /// /// JA4H (JA4 for HTTP) fingerprints HTTP clients based on: @@ -140,8 +553,9 @@ impl OrderedHeaders { } /// Create Chrome navigation headers with exact order. + /// Uses Chrome 146 (latest) by default. pub fn chrome_navigation() -> Self { - Self::new(headers_to_owned(chrome_142_headers())) + Self::new(headers_to_owned(chrome_146_headers())) } /// Create Firefox navigation headers with exact order. diff --git a/src/lib.rs b/src/lib.rs index f98cc738..5352f2b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,10 +11,14 @@ pub mod cache; pub mod cookie; pub mod error; pub mod headers; +pub mod request; pub mod response; pub mod timeouts; pub mod version; +// Proxy support +pub mod proxy; + // Fingerprinting pub mod fingerprint; @@ -28,7 +32,9 @@ pub mod pool; pub use cookie::{hash_cookie_value, CookieJar}; pub use error::{Error, Result}; pub use fingerprint::{FingerprintProfile, PriorityTree}; +pub use headers::Headers; pub use headers::OrderedHeaders; +pub use request::{Body, IntoUrl, RedirectPolicy, Request}; pub use response::Response; pub use timeouts::{recv_with_idle_timeout, Timeouts}; pub use version::HttpVersion; @@ -45,3 +51,6 @@ pub use transport::tcp::TcpFingerprint; // Pool re-exports pub use pool::alt_svc::{AltSvcCache, AltSvcEntry}; pub use pool::multiplexer::{ConnectionPool, PoolEntry, PoolKey}; + +// Proxy re-exports +pub use proxy::{ProxyAuth, ProxyConfig}; diff --git a/src/pool/multiplexer.rs b/src/pool/multiplexer.rs index 8f2eb1c7..2fc5fa3d 100644 --- a/src/pool/multiplexer.rs +++ b/src/pool/multiplexer.rs @@ -21,6 +21,7 @@ pub struct PoolKey { pub host: String, pub port: u16, pub is_https: bool, + pub proxy_key: Option, } impl PoolKey { @@ -30,6 +31,17 @@ impl PoolKey { host, port, is_https, + proxy_key: None, + } + } + + /// Create a new pool key for a proxied connection + pub fn with_proxy(host: String, port: u16, is_https: bool, proxy_key: String) -> Self { + Self { + host, + port, + is_https, + proxy_key: Some(proxy_key), } } } diff --git a/src/proxy/http_connect.rs b/src/proxy/http_connect.rs new file mode 100644 index 00000000..2f1eb7ba --- /dev/null +++ b/src/proxy/http_connect.rs @@ -0,0 +1,120 @@ +use base64::Engine; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpStream; + +use crate::error::{Error, Result}; +use crate::proxy::ProxyAuth; + +/// Maximum response header size (8 KB) to prevent abuse. +const MAX_HEADER_SIZE: usize = 8192; + +/// Establishes an HTTP CONNECT tunnel through a proxy. +/// +/// On success, the returned `TcpStream` is connected end-to-end to +/// `target_host:target_port` — all further I/O goes straight to the target. +pub(crate) async fn http_connect( + proxy_host: &str, + proxy_port: u16, + target_host: &str, + target_port: u16, + auth: Option<&ProxyAuth>, +) -> Result { + let mut stream = TcpStream::connect((proxy_host, proxy_port)) + .await + .map_err(|e| { + Error::connection(format!( + "failed to connect to proxy {proxy_host}:{proxy_port}: {e}" + )) + })?; + + // Build CONNECT request. + let mut request = format!( + "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\n" + ); + if let Some(auth) = auth { + let credentials = base64::engine::general_purpose::STANDARD + .encode(format!("{}:{}", auth.username, auth.password)); + request.push_str(&format!("Proxy-Authorization: Basic {credentials}\r\n")); + } + request.push_str("\r\n"); + + stream + .write_all(request.as_bytes()) + .await + .map_err(|e| Error::connection(format!("failed to send CONNECT request: {e}")))?; + + // Read response headers until \r\n\r\n. + let mut buf = Vec::with_capacity(1024); + let mut tmp = [0u8; 1024]; + + loop { + let n = stream + .read(&mut tmp) + .await + .map_err(|e| Error::connection(format!("failed to read proxy response: {e}")))?; + + if n == 0 { + return Err(Error::connection( + "proxy closed connection before completing CONNECT handshake", + )); + } + + buf.extend_from_slice(&tmp[..n]); + + if buf.len() > MAX_HEADER_SIZE { + return Err(Error::connection( + "proxy response headers exceeded 8 KB limit", + )); + } + + // Check for end-of-headers marker. + if buf.windows(4).any(|w| w == b"\r\n\r\n") { + break; + } + } + + // Parse status line: HTTP/1.x STATUS_CODE REASON\r\n + let header_str = String::from_utf8_lossy(&buf); + let status_line = header_str + .lines() + .next() + .ok_or_else(|| Error::connection("empty response from proxy"))?; + + let status_code = parse_status_code(status_line)?; + + if status_code != 200 { + return Err(Error::connection(format!( + "proxy CONNECT failed: {status_line}" + ))); + } + + Ok(stream) +} + +/// Extracts the numeric status code from an HTTP status line. +/// +/// Accepts both `HTTP/1.0` and `HTTP/1.1` prefixes. +fn parse_status_code(status_line: &str) -> Result { + // Expected: "HTTP/1.x " + let mut parts = status_line.split_whitespace(); + + let version = parts + .next() + .ok_or_else(|| Error::connection("malformed proxy status line: missing version"))?; + + if !version.starts_with("HTTP/") { + return Err(Error::connection(format!( + "malformed proxy status line: unexpected version '{version}'" + ))); + } + + let code_str = parts + .next() + .ok_or_else(|| Error::connection("malformed proxy status line: missing status code"))?; + + code_str.parse::().map_err(|_| { + Error::connection(format!( + "malformed proxy status line: invalid status code '{code_str}'" + )) + }) +} diff --git a/src/proxy/mod.rs b/src/proxy/mod.rs new file mode 100644 index 00000000..e6542365 --- /dev/null +++ b/src/proxy/mod.rs @@ -0,0 +1,99 @@ +//! Proxy support for SOCKS5 and HTTP CONNECT tunneling. + +pub mod http_connect; +pub mod socks5; +pub mod udp_transport; + +/// Authentication credentials for proxy connections. +#[derive(Debug, Clone)] +pub struct ProxyAuth { + pub username: String, + pub password: String, +} + +/// Proxy configuration for tunneling connections. +#[derive(Debug, Clone)] +pub enum ProxyConfig { + /// SOCKS5 proxy (RFC 1928). + Socks5 { + host: String, + port: u16, + auth: Option, + }, + /// HTTP CONNECT proxy. + HttpConnect { + host: String, + port: u16, + auth: Option, + }, +} + +impl ProxyConfig { + /// Create a SOCKS5 proxy config without authentication. + pub fn socks5(host: impl Into, port: u16) -> Self { + Self::Socks5 { + host: host.into(), + port, + auth: None, + } + } + + /// Create a SOCKS5 proxy config with username/password authentication. + pub fn socks5_with_auth( + host: impl Into, + port: u16, + username: impl Into, + password: impl Into, + ) -> Self { + Self::Socks5 { + host: host.into(), + port, + auth: Some(ProxyAuth { + username: username.into(), + password: password.into(), + }), + } + } + + /// Create an HTTP CONNECT proxy config without authentication. + pub fn http_connect(host: impl Into, port: u16) -> Self { + Self::HttpConnect { + host: host.into(), + port, + auth: None, + } + } + + /// Create an HTTP CONNECT proxy config with username/password authentication. + pub fn http_connect_with_auth( + host: impl Into, + port: u16, + username: impl Into, + password: impl Into, + ) -> Self { + Self::HttpConnect { + host: host.into(), + port, + auth: Some(ProxyAuth { + username: username.into(), + password: password.into(), + }), + } + } + + /// Returns the proxy (host, port) regardless of variant. + pub fn addr(&self) -> (&str, u16) { + match self { + Self::Socks5 { host, port, .. } => (host, *port), + Self::HttpConnect { host, port, .. } => (host, *port), + } + } + + /// Returns a unique string key for connection pool keying. + pub fn proxy_key(&self) -> String { + match self { + Self::Socks5 { host, port, .. } => format!("socks5://{}:{}", host, port), + Self::HttpConnect { host, port, .. } => format!("http-connect://{}:{}", host, port), + } + } +} diff --git a/src/proxy/socks5.rs b/src/proxy/socks5.rs new file mode 100644 index 00000000..af4e13c4 --- /dev/null +++ b/src/proxy/socks5.rs @@ -0,0 +1,432 @@ +//! SOCKS5 proxy implementation (RFC 1928 + RFC 1929). + +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; + +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpStream; + +use crate::error::Error; +use crate::proxy::ProxyAuth; + +// SOCKS5 constants +const SOCKS5_VERSION: u8 = 0x05; +const AUTH_NONE: u8 = 0x00; +const AUTH_USER_PASS: u8 = 0x02; +const AUTH_NO_ACCEPTABLE: u8 = 0xFF; +const CMD_CONNECT: u8 = 0x01; +const CMD_UDP_ASSOCIATE: u8 = 0x03; +const ATYP_IPV4: u8 = 0x01; +const ATYP_DOMAIN: u8 = 0x03; +const ATYP_IPV6: u8 = 0x04; +const USERPASS_VERSION: u8 = 0x01; + +/// Establish a TCP tunnel through a SOCKS5 proxy to the target host. +pub(crate) async fn socks5_connect( + proxy_host: &str, + proxy_port: u16, + target_host: &str, + target_port: u16, + auth: Option<&ProxyAuth>, +) -> Result { + if target_host.len() > 255 { + return Err(Error::Connection( + "SOCKS5: domain name exceeds 255 bytes".into(), + )); + } + + let mut stream = TcpStream::connect((proxy_host, proxy_port)) + .await + .map_err(|e| Error::Connection(format!("SOCKS5: failed to connect to proxy: {}", e)))?; + + negotiate_auth(&mut stream, auth).await?; + + // CONNECT request: domain name (atyp=0x03, always remote DNS) + let domain = target_host.as_bytes(); + let mut buf = Vec::with_capacity(7 + domain.len()); + buf.push(SOCKS5_VERSION); + buf.push(CMD_CONNECT); + buf.push(0x00); // reserved + buf.push(ATYP_DOMAIN); + buf.push(domain.len() as u8); + buf.extend_from_slice(domain); + buf.push((target_port >> 8) as u8); + buf.push(target_port as u8); + + stream + .write_all(&buf) + .await + .map_err(|e| Error::Connection(format!("SOCKS5: failed to send CONNECT: {}", e)))?; + + let rep = read_reply(&mut stream).await?; + if rep != 0x00 { + return Err(Error::Connection(format!( + "SOCKS5 CONNECT failed: {}", + reply_message(rep) + ))); + } + + Ok(stream) +} + +/// State for an active SOCKS5 UDP ASSOCIATE session. +pub(crate) struct Socks5UdpAssociation { + /// The TCP control connection — must stay alive for the association to remain valid. + pub control_tcp: TcpStream, + /// The relay address to send UDP datagrams to. + pub relay_addr: SocketAddr, +} + +/// Request a SOCKS5 UDP ASSOCIATE through the proxy. +pub(crate) async fn socks5_udp_associate( + proxy_host: &str, + proxy_port: u16, + local_udp_addr: SocketAddr, + auth: Option<&ProxyAuth>, +) -> Result { + let mut stream = TcpStream::connect((proxy_host, proxy_port)) + .await + .map_err(|e| Error::Connection(format!("SOCKS5: failed to connect to proxy: {}", e)))?; + + negotiate_auth(&mut stream, auth).await?; + + // UDP ASSOCIATE request with local address (or 0.0.0.0:0 if unspecified) + let addr = match local_udp_addr { + SocketAddr::V4(v4) => v4, + SocketAddr::V6(_) => SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0), + }; + + let ip = addr.ip().octets(); + let port = addr.port(); + let request = [ + SOCKS5_VERSION, + CMD_UDP_ASSOCIATE, + 0x00, // reserved + ATYP_IPV4, + ip[0], + ip[1], + ip[2], + ip[3], + (port >> 8) as u8, + port as u8, + ]; + + stream + .write_all(&request) + .await + .map_err(|e| Error::Connection(format!("SOCKS5: failed to send UDP ASSOCIATE: {}", e)))?; + + let rep = read_reply_with_addr(&mut stream).await?; + if rep.reply != 0x00 { + return Err(Error::Connection(format!( + "SOCKS5 UDP ASSOCIATE failed: {}", + reply_message(rep.reply) + ))); + } + + // If server returns 0.0.0.0, use the proxy host IP instead + let relay_addr = match rep.bound_addr { + SocketAddr::V4(v4) if v4.ip().is_unspecified() => { + let proxy_ip: Ipv4Addr = proxy_host.parse().unwrap_or(Ipv4Addr::new(127, 0, 0, 1)); + SocketAddr::V4(SocketAddrV4::new(proxy_ip, v4.port())) + } + SocketAddr::V6(v6) if v6.ip().is_unspecified() => { + let proxy_ip: Ipv4Addr = proxy_host.parse().unwrap_or(Ipv4Addr::new(127, 0, 0, 1)); + SocketAddr::V4(SocketAddrV4::new(proxy_ip, v6.port())) + } + other => other, + }; + + Ok(Socks5UdpAssociation { + control_tcp: stream, + relay_addr, + }) +} + +/// Encode a SOCKS5 UDP relay header prepended to the payload. +/// +/// Format: `[0x00, 0x00, 0x00, atyp, addr, port] ++ data` +pub(crate) fn encode_socks5_udp_header(target: SocketAddr, data: &[u8]) -> Vec { + let mut buf = Vec::new(); + buf.push(0x00); // RSV + buf.push(0x00); // RSV + buf.push(0x00); // FRAG (no fragmentation) + + match target { + SocketAddr::V4(v4) => { + buf.push(ATYP_IPV4); + buf.extend_from_slice(&v4.ip().octets()); + } + SocketAddr::V6(v6) => { + buf.push(ATYP_IPV6); + buf.extend_from_slice(&v6.ip().octets()); + } + } + + let port = target.port(); + buf.push((port >> 8) as u8); + buf.push(port as u8); + buf.extend_from_slice(data); + buf +} + +/// Decode a SOCKS5 UDP relay header, returning the source address and the byte offset +/// where the payload data begins. +pub(crate) fn decode_socks5_udp_header(buf: &[u8]) -> Result<(SocketAddr, usize), Error> { + // Minimum: 2 RSV + 1 FRAG + 1 ATYP + 4 addr (IPv4) + 2 port = 10 + if buf.len() < 10 { + return Err(Error::Connection( + "SOCKS5 UDP: packet too short for header".into(), + )); + } + + // buf[0..2] = RSV, buf[2] = FRAG + let atyp = buf[3]; + match atyp { + ATYP_IPV4 => { + if buf.len() < 10 { + return Err(Error::Connection( + "SOCKS5 UDP: packet too short for IPv4 header".into(), + )); + } + let ip = Ipv4Addr::new(buf[4], buf[5], buf[6], buf[7]); + let port = u16::from_be_bytes([buf[8], buf[9]]); + Ok((SocketAddr::V4(SocketAddrV4::new(ip, port)), 10)) + } + ATYP_DOMAIN => { + if buf.len() < 5 { + return Err(Error::Connection( + "SOCKS5 UDP: packet too short for domain header".into(), + )); + } + let dlen = buf[4] as usize; + let header_len = 4 + 1 + dlen + 2; // atyp offset + len byte + domain + port + if buf.len() < header_len { + return Err(Error::Connection( + "SOCKS5 UDP: packet too short for domain name".into(), + )); + } + // For domain atyp in UDP response, we can't resolve here. + // Return 0.0.0.0 with the port — caller must handle domain resolution. + let port_offset = 4 + 1 + dlen; + let port = u16::from_be_bytes([buf[port_offset], buf[port_offset + 1]]); + Ok(( + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port)), + header_len, + )) + } + ATYP_IPV6 => { + let header_len = 4 + 16 + 2; // 4 header bytes + 16 addr + 2 port + if buf.len() < header_len { + return Err(Error::Connection( + "SOCKS5 UDP: packet too short for IPv6 header".into(), + )); + } + let mut octets = [0u8; 16]; + octets.copy_from_slice(&buf[4..20]); + let ip = Ipv6Addr::from(octets); + let port = u16::from_be_bytes([buf[20], buf[21]]); + Ok(( + SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)), + header_len, + )) + } + _ => Err(Error::Connection(format!( + "SOCKS5 UDP: unsupported address type 0x{:02x}", + atyp + ))), + } +} + +// --- Internal helpers --- + +/// Negotiate SOCKS5 authentication with the proxy. +async fn negotiate_auth(stream: &mut TcpStream, auth: Option<&ProxyAuth>) -> Result<(), Error> { + // Validate credentials length before sending anything + if let Some(a) = auth { + if a.username.len() > 255 { + return Err(Error::Connection( + "SOCKS5: username exceeds 255 bytes".into(), + )); + } + if a.password.len() > 255 { + return Err(Error::Connection( + "SOCKS5: password exceeds 255 bytes".into(), + )); + } + } + + // Greeting: offer methods + let greeting = if auth.is_some() { + vec![SOCKS5_VERSION, 2, AUTH_NONE, AUTH_USER_PASS] + } else { + vec![SOCKS5_VERSION, 1, AUTH_NONE] + }; + + stream + .write_all(&greeting) + .await + .map_err(|e| Error::Connection(format!("SOCKS5: failed to send greeting: {}", e)))?; + + let mut resp = [0u8; 2]; + stream.read_exact(&mut resp).await.map_err(|e| { + Error::Connection(format!("SOCKS5: failed to read greeting response: {}", e)) + })?; + + if resp[0] != SOCKS5_VERSION { + return Err(Error::Connection(format!( + "SOCKS5: unexpected version 0x{:02x}", + resp[0] + ))); + } + + match resp[1] { + AUTH_NONE => Ok(()), + AUTH_USER_PASS => { + let a = auth.ok_or_else(|| { + Error::Connection("SOCKS5: server requires auth but no credentials provided".into()) + })?; + authenticate_user_pass(stream, a).await + } + AUTH_NO_ACCEPTABLE => Err(Error::Connection( + "SOCKS5: no acceptable authentication method".into(), + )), + method => Err(Error::Connection(format!( + "SOCKS5: unsupported auth method 0x{:02x}", + method + ))), + } +} + +/// Perform RFC 1929 username/password authentication. +async fn authenticate_user_pass(stream: &mut TcpStream, auth: &ProxyAuth) -> Result<(), Error> { + let uname = auth.username.as_bytes(); + let passwd = auth.password.as_bytes(); + + let mut buf = Vec::with_capacity(3 + uname.len() + passwd.len()); + buf.push(USERPASS_VERSION); + buf.push(uname.len() as u8); + buf.extend_from_slice(uname); + buf.push(passwd.len() as u8); + buf.extend_from_slice(passwd); + + stream + .write_all(&buf) + .await + .map_err(|e| Error::Connection(format!("SOCKS5: failed to send auth: {}", e)))?; + + let mut resp = [0u8; 2]; + stream + .read_exact(&mut resp) + .await + .map_err(|e| Error::Connection(format!("SOCKS5: failed to read auth response: {}", e)))?; + + if resp[1] != 0x00 { + return Err(Error::Connection( + "SOCKS5: authentication failed (bad username/password)".into(), + )); + } + + Ok(()) +} + +/// Parsed SOCKS5 reply. +struct ReplyInfo { + reply: u8, + bound_addr: SocketAddr, +} + +/// Read SOCKS5 reply header, consume the bound address, and return the reply code. +/// Discards the bound address (used for CONNECT where we don't need it). +async fn read_reply(stream: &mut TcpStream) -> Result { + let info = read_reply_with_addr(stream).await?; + Ok(info.reply) +} + +/// Read full SOCKS5 reply including the bound address. +async fn read_reply_with_addr(stream: &mut TcpStream) -> Result { + let mut header = [0u8; 4]; + stream + .read_exact(&mut header) + .await + .map_err(|e| Error::Connection(format!("SOCKS5: failed to read reply: {}", e)))?; + + if header[0] != SOCKS5_VERSION { + return Err(Error::Connection(format!( + "SOCKS5: unexpected reply version 0x{:02x}", + header[0] + ))); + } + + let reply = header[1]; + let atyp = header[3]; + + let bound_addr = match atyp { + ATYP_IPV4 => { + let mut addr = [0u8; 4]; + stream.read_exact(&mut addr).await.map_err(|e| { + Error::Connection(format!("SOCKS5: failed to read bound IPv4 addr: {}", e)) + })?; + let mut port_buf = [0u8; 2]; + stream.read_exact(&mut port_buf).await.map_err(|e| { + Error::Connection(format!("SOCKS5: failed to read bound port: {}", e)) + })?; + let ip = Ipv4Addr::from(addr); + let port = u16::from_be_bytes(port_buf); + SocketAddr::V4(SocketAddrV4::new(ip, port)) + } + ATYP_DOMAIN => { + let mut len_buf = [0u8; 1]; + stream.read_exact(&mut len_buf).await.map_err(|e| { + Error::Connection(format!("SOCKS5: failed to read domain length: {}", e)) + })?; + let dlen = len_buf[0] as usize; + let mut domain = vec![0u8; dlen]; + stream.read_exact(&mut domain).await.map_err(|e| { + Error::Connection(format!("SOCKS5: failed to read bound domain: {}", e)) + })?; + let mut port_buf = [0u8; 2]; + stream.read_exact(&mut port_buf).await.map_err(|e| { + Error::Connection(format!("SOCKS5: failed to read bound port: {}", e)) + })?; + let port = u16::from_be_bytes(port_buf); + // Domain in reply — use unspecified addr with port + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port)) + } + ATYP_IPV6 => { + let mut addr = [0u8; 16]; + stream.read_exact(&mut addr).await.map_err(|e| { + Error::Connection(format!("SOCKS5: failed to read bound IPv6 addr: {}", e)) + })?; + let mut port_buf = [0u8; 2]; + stream.read_exact(&mut port_buf).await.map_err(|e| { + Error::Connection(format!("SOCKS5: failed to read bound port: {}", e)) + })?; + let ip = Ipv6Addr::from(addr); + let port = u16::from_be_bytes(port_buf); + SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)) + } + _ => { + return Err(Error::Connection(format!( + "SOCKS5: unsupported address type in reply 0x{:02x}", + atyp + ))); + } + }; + + Ok(ReplyInfo { reply, bound_addr }) +} + +/// Map a SOCKS5 reply code to a human-readable message. +fn reply_message(rep: u8) -> &'static str { + match rep { + 0x01 => "general SOCKS server failure", + 0x02 => "connection not allowed by ruleset", + 0x03 => "network unreachable", + 0x04 => "host unreachable", + 0x05 => "connection refused", + 0x06 => "TTL expired", + 0x07 => "command not supported", + 0x08 => "address type not supported", + _ => "unknown error", + } +} diff --git a/src/proxy/udp_transport.rs b/src/proxy/udp_transport.rs new file mode 100644 index 00000000..6f02b9d4 --- /dev/null +++ b/src/proxy/udp_transport.rs @@ -0,0 +1,125 @@ +use std::future::Future; +use std::io; +use std::net::SocketAddr; +use std::pin::Pin; +use std::sync::Arc; + +use tokio::net::{TcpStream, UdpSocket}; + +/// Object-safe trait for QUIC UDP transport, supporting both direct and +/// SOCKS5-proxied UDP paths. +#[allow(clippy::type_complexity)] +pub(crate) trait QuicUdpTransport: Send + Sync { + fn send_to_target<'a>( + &'a self, + buf: &'a [u8], + target: SocketAddr, + ) -> Pin> + Send + 'a>>; + + fn recv_from_target<'a>( + &'a self, + buf: &'a mut [u8], + ) -> Pin> + Send + 'a>>; + + fn local_addr(&self) -> io::Result; +} + +/// Transparent pass-through over a raw `UdpSocket`. +pub(crate) struct DirectUdpTransport { + socket: Arc, +} + +impl DirectUdpTransport { + pub(crate) fn new(socket: Arc) -> Self { + Self { socket } + } + + #[allow(dead_code)] + pub(crate) fn socket(&self) -> &Arc { + &self.socket + } +} + +impl QuicUdpTransport for DirectUdpTransport { + fn send_to_target<'a>( + &'a self, + buf: &'a [u8], + target: SocketAddr, + ) -> Pin> + Send + 'a>> { + Box::pin(async move { self.socket.send_to(buf, target).await }) + } + + fn recv_from_target<'a>( + &'a self, + buf: &'a mut [u8], + ) -> Pin> + Send + 'a>> { + Box::pin(async move { self.socket.recv_from(buf).await }) + } + + fn local_addr(&self) -> io::Result { + self.socket.local_addr() + } +} + +/// UDP transport through a SOCKS5 UDP ASSOCIATE relay. +/// +/// The `_control` TCP stream must remain alive for the duration of the +/// association — dropping it signals the SOCKS5 server to tear down the +/// UDP relay. +pub(crate) struct Socks5UdpTransport { + socket: Arc, + relay_addr: SocketAddr, + _control: TcpStream, +} + +impl Socks5UdpTransport { + pub(crate) fn new(socket: Arc, relay_addr: SocketAddr, control: TcpStream) -> Self { + Self { + socket, + relay_addr, + _control: control, + } + } + + #[allow(dead_code)] + pub(crate) fn socket(&self) -> &Arc { + &self.socket + } +} + +impl QuicUdpTransport for Socks5UdpTransport { + fn send_to_target<'a>( + &'a self, + buf: &'a [u8], + target: SocketAddr, + ) -> Pin> + Send + 'a>> { + Box::pin(async move { + let wrapped = crate::proxy::socks5::encode_socks5_udp_header(target, buf); + self.socket.send_to(&wrapped, self.relay_addr).await + }) + } + + fn recv_from_target<'a>( + &'a self, + buf: &'a mut [u8], + ) -> Pin> + Send + 'a>> { + Box::pin(async move { + let mut internal_buf = [0u8; 65535]; + let (n, _relay) = self.socket.recv_from(&mut internal_buf).await?; + let data = &internal_buf[..n]; + + let (source_addr, header_len) = crate::proxy::socks5::decode_socks5_udp_header(data) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; + + let payload = &data[header_len..]; + let copy_len = payload.len().min(buf.len()); + buf[..copy_len].copy_from_slice(&payload[..copy_len]); + + Ok((copy_len, source_addr)) + }) + } + + fn local_addr(&self) -> io::Result { + self.socket.local_addr() + } +} diff --git a/src/request.rs b/src/request.rs new file mode 100644 index 00000000..9e06f641 --- /dev/null +++ b/src/request.rs @@ -0,0 +1,169 @@ +//! Request and body types with reqwest-like ergonomics. + +use crate::error::{Error, Result}; +use crate::headers::Headers; +use crate::version::HttpVersion; +use bytes::Bytes; +use http::Method; +use std::time::Duration; +use url::Url; + +/// Convert common URL inputs into a `Url`. +pub trait IntoUrl { + fn into_url(self) -> Result; +} + +impl IntoUrl for Url { + fn into_url(self) -> Result { + Ok(self) + } +} + +impl IntoUrl for &Url { + fn into_url(self) -> Result { + Ok(self.clone()) + } +} + +impl IntoUrl for &str { + fn into_url(self) -> Result { + Url::parse(self).map_err(Error::from) + } +} + +impl IntoUrl for String { + fn into_url(self) -> Result { + Url::parse(&self).map_err(Error::from) + } +} + +impl IntoUrl for http::Uri { + fn into_url(self) -> Result { + Url::parse(&self.to_string()).map_err(Error::from) + } +} + +impl IntoUrl for &http::Uri { + fn into_url(self) -> Result { + Url::parse(&self.to_string()).map_err(Error::from) + } +} + +/// Request body variants. +#[derive(Clone, Debug, Default)] +pub enum Body { + #[default] + Empty, + Bytes(Bytes), + Text(String), + Json(Vec), + Form(String), + Raw(Vec), +} + +impl Body { + pub fn empty() -> Self { + Body::Empty + } + + pub fn is_empty(&self) -> bool { + matches!(self, Body::Empty) + } + + pub fn into_bytes(self) -> Result { + Ok(match self { + Body::Empty => Bytes::new(), + Body::Bytes(bytes) => bytes, + Body::Text(text) => Bytes::from(text.into_bytes()), + Body::Json(bytes) => Bytes::from(bytes), + Body::Form(text) => Bytes::from(text.into_bytes()), + Body::Raw(bytes) => Bytes::from(bytes), + }) + } +} + +impl From for Body { + fn from(value: Bytes) -> Self { + Body::Bytes(value) + } +} + +impl From> for Body { + fn from(value: Vec) -> Self { + Body::Raw(value) + } +} + +impl From<&[u8]> for Body { + fn from(value: &[u8]) -> Self { + Body::Raw(value.to_vec()) + } +} + +impl From for Body { + fn from(value: String) -> Self { + Body::Text(value) + } +} + +impl From<&str> for Body { + fn from(value: &str) -> Self { + Body::Text(value.to_string()) + } +} + +/// High-level request object for execution. +#[derive(Clone, Debug)] +pub struct Request { + pub(crate) method: Method, + pub(crate) url: Url, + pub(crate) headers: Headers, + pub(crate) body: Body, + pub(crate) version: Option, + pub(crate) timeout: Option, +} + +impl Request { + pub fn new(method: Method, url: Url) -> Self { + Self { + method, + url, + headers: Headers::new(), + body: Body::Empty, + version: None, + timeout: None, + } + } + + pub fn method(&self) -> &Method { + &self.method + } + + pub fn url(&self) -> &Url { + &self.url + } + + pub fn headers(&self) -> &Headers { + &self.headers + } + + pub fn body(&self) -> &Body { + &self.body + } + + pub fn version(&self) -> Option { + self.version + } + + pub fn timeout(&self) -> Option { + self.timeout + } +} + +/// Redirect policy for the client. +#[derive(Clone, Debug, Default)] +pub enum RedirectPolicy { + #[default] + None, + Limited(u32), +} diff --git a/src/response.rs b/src/response.rs index 2bd8ff2d..262dca00 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,21 +1,24 @@ //! HTTP response handling with explicit decompression. use crate::error::{Error, Result}; +use crate::headers::Headers; use bytes::Bytes; +use http::StatusCode; use std::io::Read; +use url::Url; /// HTTP response with explicit decompression. #[derive(Debug, Clone)] pub struct Response { - pub status: u16, - pub headers: Vec, + pub(crate) status: u16, + headers: Headers, body: Bytes, http_version: String, - pub effective_url: Option, + effective_url: Option, } impl Response { - pub fn new(status: u16, headers: Vec, body: Bytes, http_version: String) -> Self { + pub fn new(status: u16, headers: Headers, body: Bytes, http_version: String) -> Self { Self { status, headers, @@ -27,20 +30,47 @@ impl Response { /// Set the effective URL (the URL that was actually requested). /// This is used by the redirect engine to track the current URL. - pub fn with_url(mut self, url: impl Into) -> Self { - self.effective_url = Some(url.into()); + pub fn with_url(mut self, url: Url) -> Self { + self.effective_url = Some(url); self } pub fn http_version(&self) -> &str { &self.http_version } + + pub fn status(&self) -> StatusCode { + StatusCode::from_u16(self.status).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR) + } + + pub fn status_code(&self) -> u16 { + self.status + } + + pub fn headers(&self) -> &Headers { + &self.headers + } + + pub fn url(&self) -> Option<&Url> { + self.effective_url.as_ref() + } + pub fn body(&self) -> &Bytes { &self.body } + + pub fn bytes_raw(&self) -> Bytes { + self.body.clone() + } + pub fn into_body(self) -> Bytes { self.body } + + pub fn bytes(&self) -> Result { + self.decoded_body() + } + pub fn is_success(&self) -> bool { (200..300).contains(&self.status) } @@ -52,30 +82,11 @@ impl Response { } pub fn get_header(&self, name: &str) -> Option<&str> { - let name_lower = name.to_lowercase(); - for header in &self.headers { - if let Some((key, value)) = header.split_once(':') { - if key.trim().to_lowercase() == name_lower { - return Some(value.trim()); - } - } - } - None + self.headers.get(name) } pub fn get_headers(&self, name: &str) -> Vec<&str> { - let name_lower = name.to_lowercase(); - self.headers - .iter() - .filter_map(|h| { - let (key, value) = h.split_once(':')?; - if key.trim().to_lowercase() == name_lower { - Some(value.trim()) - } else { - None - } - }) - .collect() + self.headers.get_all(name) } pub fn content_type(&self) -> Option<&str> { @@ -144,6 +155,32 @@ impl Response { let text = self.text()?; serde_json::from_str(&text).map_err(Error::from) } + + pub fn error_for_status(self) -> Result { + if self.status().is_client_error() || self.status().is_server_error() { + let message = self + .status() + .canonical_reason() + .unwrap_or("HTTP error") + .to_string(); + Err(Error::http_status(self.status, message)) + } else { + Ok(self) + } + } + + pub fn error_for_status_ref(&self) -> Result<&Self> { + if self.status().is_client_error() || self.status().is_server_error() { + let message = self + .status() + .canonical_reason() + .unwrap_or("HTTP error") + .to_string(); + Err(Error::http_status(self.status, message)) + } else { + Ok(self) + } + } } fn decode_gzip(data: &[u8]) -> Result { diff --git a/src/transport/connector.rs b/src/transport/connector.rs index 77336a9c..b3cbe016 100644 --- a/src/transport/connector.rs +++ b/src/transport/connector.rs @@ -114,6 +114,8 @@ pub struct BoringConnector { use_platform_roots: bool, /// Skip TLS certificate verification (DANGEROUS - for testing only) danger_accept_invalid_certs: bool, + /// Optional proxy configuration for tunneling connections + proxy: Option, } impl BoringConnector { @@ -129,6 +131,7 @@ impl BoringConnector { root_certs: Vec::new(), use_platform_roots: false, danger_accept_invalid_certs: false, + proxy: None, } } @@ -140,6 +143,7 @@ impl BoringConnector { root_certs: Vec::new(), use_platform_roots: false, danger_accept_invalid_certs: false, + proxy: None, } } @@ -151,9 +155,16 @@ impl BoringConnector { root_certs: Vec::new(), use_platform_roots: false, danger_accept_invalid_certs: false, + proxy: None, } } + /// Set proxy configuration for tunneling connections. + pub fn with_proxy(mut self, proxy: crate::proxy::ProxyConfig) -> Self { + self.proxy = Some(proxy); + self + } + /// Set TCP fingerprint configuration. pub fn with_tcp_fingerprint(mut self, tcp_fp: TcpFingerprint) -> Self { self.tcp_fingerprint = Some(tcp_fp); @@ -465,10 +476,34 @@ impl BoringConnector { 80 }); + let tcp_stream = if let Some(ref proxy) = self.proxy { + self.connect_via_proxy(proxy, host, port).await? + } else { + self.connect_direct(host, port).await? + }; + + if uri.scheme_str() == Some("https") { + let ssl_connector = self.configure_ssl(host)?; + + let ssl_config = ssl_connector + .configure() + .map_err(|e| Error::Tls(format!("Failed to configure SSL: {}", e)))?; + + let ssl_stream = tokio_boring::connect(ssl_config, host, tcp_stream) + .await + .map_err(|e| Error::Tls(format!("TLS handshake failed: {}", e)))?; + + Ok(MaybeHttpsStream::Https(ssl_stream)) + } else { + Ok(MaybeHttpsStream::Http(tcp_stream)) + } + } + + /// Establish a direct TCP connection, applying TCP fingerprint if configured. + async fn connect_direct(&self, host: &str, port: u16) -> Result { let addr = format!("{}:{}", host, port); - // Configure TCP socket options if fingerprint is provided - let tcp_stream = if let Some(ref tcp_fp) = self.tcp_fingerprint { + let tcp = if let Some(ref tcp_fp) = self.tcp_fingerprint { // Create socket2 socket, configure it, then connect and convert to tokio TcpStream use socket2::{Domain, Socket, Type}; use std::net::SocketAddr; @@ -528,20 +563,25 @@ impl BoringConnector { .map_err(|e| Error::Connection(format!("Failed to connect to {}: {}", addr, e)))? }; - if uri.scheme_str() == Some("https") { - let ssl_connector = self.configure_ssl(host)?; - - let ssl_config = ssl_connector - .configure() - .map_err(|e| Error::Tls(format!("Failed to configure SSL: {}", e)))?; - - let ssl_stream = tokio_boring::connect(ssl_config, host, tcp_stream) - .await - .map_err(|e| Error::Tls(format!("TLS handshake failed: {}", e)))?; + Ok(tcp) + } - Ok(MaybeHttpsStream::Https(ssl_stream)) - } else { - Ok(MaybeHttpsStream::Http(tcp_stream)) + /// Establish a TCP connection through a proxy tunnel. + async fn connect_via_proxy( + &self, + proxy: &crate::proxy::ProxyConfig, + target_host: &str, + target_port: u16, + ) -> Result { + match proxy { + crate::proxy::ProxyConfig::Socks5 { host, port, auth } => { + crate::proxy::socks5::socks5_connect(host, *port, target_host, target_port, auth.as_ref()) + .await + } + crate::proxy::ProxyConfig::HttpConnect { host, port, auth } => { + crate::proxy::http_connect::http_connect(host, *port, target_host, target_port, auth.as_ref()) + .await + } } } } diff --git a/src/transport/h1.rs b/src/transport/h1.rs index 000531ba..91a9589d 100644 --- a/src/transport/h1.rs +++ b/src/transport/h1.rs @@ -8,6 +8,7 @@ use http::{Method, Uri}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use crate::error::{Error, Result}; +use crate::headers::Headers; use crate::response::Response; use crate::transport::connector::MaybeHttpsStream; @@ -270,12 +271,18 @@ impl H1Connection { let version = format!("HTTP/1.{}", response.version.unwrap_or(1)); // Collect headers - let response_headers: Vec = response + let response_headers: Vec<(String, String)> = response .headers .iter() .filter(|h| !h.name.is_empty()) - .map(|h| format!("{}: {}", h.name, String::from_utf8_lossy(h.value))) + .map(|h| { + ( + h.name.to_string(), + String::from_utf8_lossy(h.value).to_string(), + ) + }) .collect(); + let response_headers = Headers::from(response_headers); // Check Connection header for close directive if let Some(conn) = find_header_value(&response_headers, "connection") { @@ -511,15 +518,8 @@ fn find_header_end(buffer: &[u8]) -> Option { } /// Find a header value by name (case-insensitive). -fn find_header_value<'a>(headers: &'a [String], name: &str) -> Option<&'a str> { - for header in headers { - if let Some((hname, hvalue)) = header.split_once(": ") { - if hname.eq_ignore_ascii_case(name) { - return Some(hvalue); - } - } - } - None +fn find_header_value<'a>(headers: &'a Headers, name: &str) -> Option<&'a str> { + headers.get(name) } /// Parse a chunk size from the buffer, returning (size, end_of_line_position). @@ -640,10 +640,10 @@ mod tests { #[test] fn test_find_header_value() { - let headers = vec![ - "Content-Type: text/html".to_string(), - "Content-Length: 100".to_string(), - ]; + let headers = Headers::from(vec![ + ("Content-Type".to_string(), "text/html".to_string()), + ("Content-Length".to_string(), "100".to_string()), + ]); assert_eq!( find_header_value(&headers, "content-type"), Some("text/html") diff --git a/src/transport/h1_h2.rs b/src/transport/h1_h2.rs index 25356742..c15001ba 100644 --- a/src/transport/h1_h2.rs +++ b/src/transport/h1_h2.rs @@ -7,18 +7,24 @@ //! //! Supports automatic HTTP/3 upgrade via Alt-Svc header caching. +use base64::Engine; use bytes::Bytes; use http::{Method, Uri}; +use serde::Serialize; use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; use tokio::sync::RwLock; use tokio::time::timeout as tokio_timeout; +use url::Url; +use crate::cookie::CookieJar; use crate::error::{Error, Result}; use crate::fingerprint::{http2::Http2Settings, FingerprintProfile}; +use crate::headers::Headers; use crate::pool::alt_svc::AltSvcCache; use crate::pool::multiplexer::{ConnectionPool, PoolKey}; +use crate::request::{Body, IntoUrl, RedirectPolicy, Request}; use crate::response::Response; use crate::timeouts::Timeouts; use crate::transport::connector::{BoringConnector, MaybeHttpsStream}; @@ -59,16 +65,26 @@ pub struct Client { danger_accept_invalid_certs: bool, /// Skip TLS verification for localhost connections only localhost_allows_invalid_certs: bool, + /// Default headers applied to every request + default_headers: Headers, + /// Redirect policy + redirect_policy: RedirectPolicy, + /// Optional cookie store + cookie_store: Option>>, + /// Optional proxy configuration + proxy: Option, } /// Builder for HTTP requests. pub struct RequestBuilder<'a> { client: &'a Client, - uri: String, + url: Option, method: Method, - headers: Vec<(String, String)>, - body: Option>, + headers: Headers, + body: Body, version: Option, + timeout: Option, + error: Option, } /// Builder for creating HTTP clients. @@ -87,72 +103,60 @@ pub struct ClientBuilder { danger_accept_invalid_certs: bool, /// Automatically skip TLS verification for localhost connections localhost_allows_invalid_certs: bool, + /// Default headers applied to every request + default_headers: Headers, + /// Redirect policy + redirect_policy: RedirectPolicy, + /// Optional cookie store + cookie_store: Option>>, + /// Optional proxy configuration + proxy: Option, } impl Client { + /// Create a new client with default settings. + pub fn new() -> Result { + ClientBuilder::new().build() + } + /// Create a new client builder. pub fn builder() -> ClientBuilder { ClientBuilder::new() } /// Create a GET request builder. - pub fn get(&self, url: impl Into) -> RequestBuilder<'_> { - RequestBuilder { - client: self, - uri: url.into(), - method: Method::GET, - headers: Vec::new(), - body: None, - version: None, - } + pub fn get(&self, url: impl IntoUrl) -> RequestBuilder<'_> { + RequestBuilder::new(self, Method::GET, url) } /// Create a POST request builder. - pub fn post(&self, url: impl Into) -> RequestBuilder<'_> { - RequestBuilder { - client: self, - uri: url.into(), - method: Method::POST, - headers: Vec::new(), - body: None, - version: None, - } + pub fn post(&self, url: impl IntoUrl) -> RequestBuilder<'_> { + RequestBuilder::new(self, Method::POST, url) } /// Create a PUT request builder. - pub fn put(&self, url: impl Into) -> RequestBuilder<'_> { - RequestBuilder { - client: self, - uri: url.into(), - method: Method::PUT, - headers: Vec::new(), - body: None, - version: None, - } + pub fn put(&self, url: impl IntoUrl) -> RequestBuilder<'_> { + RequestBuilder::new(self, Method::PUT, url) } /// Create a DELETE request builder. - pub fn delete(&self, url: impl Into) -> RequestBuilder<'_> { - RequestBuilder { - client: self, - uri: url.into(), - method: Method::DELETE, - headers: Vec::new(), - body: None, - version: None, - } + pub fn delete(&self, url: impl IntoUrl) -> RequestBuilder<'_> { + RequestBuilder::new(self, Method::DELETE, url) + } + + /// Create a HEAD request builder. + pub fn head(&self, url: impl IntoUrl) -> RequestBuilder<'_> { + RequestBuilder::new(self, Method::HEAD, url) + } + + /// Create a PATCH request builder. + pub fn patch(&self, url: impl IntoUrl) -> RequestBuilder<'_> { + RequestBuilder::new(self, Method::PATCH, url) } /// Create a custom method request builder. - pub fn request(&self, method: Method, url: impl Into) -> RequestBuilder<'_> { - RequestBuilder { - client: self, - uri: url.into(), - method, - headers: Vec::new(), - body: None, - version: None, - } + pub fn request(&self, method: Method, url: impl IntoUrl) -> RequestBuilder<'_> { + RequestBuilder::new(self, method, url) } /// Get the Alt-Svc cache for manual inspection or manipulation. @@ -186,21 +190,153 @@ impl Client { } impl<'a> RequestBuilder<'a> { + fn new(client: &'a Client, method: Method, url: impl IntoUrl) -> Self { + let mut error = None; + let url = match url.into_url() { + Ok(url) => Some(url), + Err(err) => { + error = Some(err); + None + } + }; + + Self { + client, + url, + method, + headers: client.default_headers.clone(), + body: Body::Empty, + version: None, + timeout: None, + error, + } + } + + fn set_error(&mut self, error: Error) { + if self.error.is_none() { + self.error = Some(error); + } + } + + fn ensure_content_type(&mut self, value: &str) { + if !self.headers.contains("content-type") { + self.headers.insert("Content-Type", value.to_string()); + } + } + /// Add a header to the request. pub fn header(mut self, key: impl Into, value: impl Into) -> Self { - self.headers.push((key.into(), value.into())); + self.headers.insert(key, value); + self + } + + /// Append a header without replacing existing values. + pub fn header_append(mut self, key: impl Into, value: impl Into) -> Self { + self.headers.append(key, value); self } /// Set all headers (replaces existing headers). - pub fn headers(mut self, headers: Vec<(String, String)>) -> Self { - self.headers = headers; + pub fn headers(mut self, headers: impl Into) -> Self { + self.headers = headers.into(); self } /// Set the request body. - pub fn body(mut self, body: impl Into>) -> Self { - self.body = Some(body.into()); + pub fn body(mut self, body: impl Into) -> Self { + self.body = body.into(); + self + } + + /// Add URL query parameters. + pub fn query(mut self, query: &T) -> Self { + if self.error.is_some() { + return self; + } + + let url = match self.url.as_mut() { + Some(url) => url, + None => return self, + }; + + match serde_urlencoded::to_string(query) { + Ok(encoded) => { + if !encoded.is_empty() { + let merged = match url.query() { + Some(existing) if !existing.is_empty() => { + format!("{}&{}", existing, encoded) + } + _ => encoded, + }; + url.set_query(Some(&merged)); + } + } + Err(err) => self.set_error(err.into()), + } + + self + } + + /// Set a JSON body. + pub fn json(mut self, json: &T) -> Self { + if self.error.is_some() { + return self; + } + + match serde_json::to_vec(json) { + Ok(bytes) => { + self.body = Body::Json(bytes); + self.ensure_content_type("application/json"); + } + Err(err) => self.set_error(err.into()), + } + + self + } + + /// Set a form-encoded body. + pub fn form(mut self, form: &T) -> Self { + if self.error.is_some() { + return self; + } + + match serde_urlencoded::to_string(form) { + Ok(encoded) => { + self.body = Body::Form(encoded); + self.ensure_content_type("application/x-www-form-urlencoded"); + } + Err(err) => self.set_error(err.into()), + } + + self + } + + /// Set a bearer token for Authorization header. + pub fn bearer_auth(mut self, token: impl AsRef) -> Self { + self.headers + .insert("Authorization", format!("Bearer {}", token.as_ref())); + self + } + + /// Set basic auth for Authorization header. + pub fn basic_auth>( + mut self, + username: impl AsRef, + password: Option

, + ) -> Self { + let creds = match password { + Some(p) => format!("{}:{}", username.as_ref(), p.as_ref()), + None => format!("{}:", username.as_ref()), + }; + let encoded = base64::engine::general_purpose::STANDARD.encode(creds.as_bytes()); + self.headers + .insert("Authorization", format!("Basic {}", encoded)); + self + } + + /// Set per-request total timeout. + pub fn timeout(mut self, timeout: Duration) -> Self { + self.timeout = Some(timeout); self } @@ -210,6 +346,31 @@ impl<'a> RequestBuilder<'a> { self } + /// Build a request without sending it. + pub fn build(self) -> Result { + if let Some(error) = self.error { + return Err(error); + } + + let url = self.url.ok_or_else(|| Error::missing("url"))?; + + Ok(Request { + method: self.method, + url, + headers: self.headers, + body: self.body, + version: self.version, + timeout: self.timeout, + }) + } + + /// Send the request and return the response. + pub async fn send(self) -> Result { + let client = self.client.clone(); + let request = self.build()?; + client.execute(request).await + } + /// Send the request and return the response with streaming body. /// Returns (Response, Receiver for body chunks). /// The response body is empty - chunks arrive via the receiver. @@ -219,7 +380,25 @@ impl<'a> RequestBuilder<'a> { Response, tokio::sync::mpsc::Receiver>, )> { - let version = self.version.unwrap_or(self.client.default_version); + let client = self.client.clone(); + let request = self.build()?; + let mut timeouts = client.timeouts.clone(); + if let Some(total) = request.timeout { + timeouts.total = Some(total); + } + let mut headers = request.headers.clone(); + + if let Some(jar) = &client.cookie_store { + if !headers.contains("cookie") { + if let Some(cookie_header) = + jar.read().await.build_cookie_header(request.url.as_str()) + { + headers.insert("Cookie", cookie_header); + } + } + } + + let version = request.version.unwrap_or(client.default_version); // Only HTTP/2 supports streaming currently if !matches!(version, HttpVersion::Http2 | HttpVersion::Auto) { @@ -229,18 +408,17 @@ impl<'a> RequestBuilder<'a> { } // Parse URI - let uri: Uri = self - .uri + let uri: Uri = request + .url + .as_str() .parse() .map_err(|e| Error::HttpProtocol(format!("Invalid URI: {}", e)))?; - let _pool_key = Self::make_pool_key(&uri); - // For HTTP/2 streaming, we need direct connection access (no pooling for streaming) // Apply connect timeout to TCP + TLS handshake - let connector = self.client.connector_for_uri(&uri); + let connector = client.connector_for_uri(&uri); let connect_fut = connector.connect(&uri); - let stream = if let Some(connect_timeout) = self.client.timeouts.connect { + let stream = if let Some(connect_timeout) = timeouts.connect { tokio_timeout(connect_timeout, connect_fut) .await .map_err(|_| Error::ConnectTimeout(connect_timeout))?? @@ -258,12 +436,9 @@ impl<'a> RequestBuilder<'a> { } // Create H2 connection (part of connect phase) - let h2_connect_fut = H2Connection::connect( - stream, - self.client.http2_settings.clone(), - self.client.pseudo_order, - ); - let mut h2_conn = if let Some(connect_timeout) = self.client.timeouts.connect { + let h2_connect_fut = + H2Connection::connect(stream, client.http2_settings.clone(), client.pseudo_order); + let mut h2_conn = if let Some(connect_timeout) = timeouts.connect { tokio_timeout(connect_timeout, h2_connect_fut) .await .map_err(|_| Error::ConnectTimeout(connect_timeout))?? @@ -272,9 +447,17 @@ impl<'a> RequestBuilder<'a> { }; // Build HTTP request - let path = uri.path_and_query().map(|pq| pq.as_str()).unwrap_or("/"); - let host = uri.host().unwrap_or("localhost"); - let authority = if let Some(port) = uri.port_u16() { + let mut path = request.url.path().to_string(); + if path.is_empty() { + path = "/".to_string(); + } + if let Some(query) = request.url.query() { + path.push('?'); + path.push_str(query); + } + + let host = request.url.host_str().unwrap_or("localhost"); + let authority = if let Some(port) = request.url.port_or_known_default() { if port == 443 { host.to_string() } else { @@ -285,27 +468,24 @@ impl<'a> RequestBuilder<'a> { }; // Build URI with scheme and authority for HTTP/2 - // Note: http::Request::builder() doesn't accept pseudo-headers via .header() - // The :method, :scheme, :authority, :path pseudo-headers are set implicitly - // via .method() and .uri() - the URI must include scheme+authority for HTTP/2 let full_uri = format!("https://{}{}", authority, path); let mut request_builder = http::Request::builder() - .method(self.method.clone()) + .method(request.method.clone()) .uri(&full_uri); // Add custom headers (pseudo-headers are derived from method/uri) - for (key, value) in &self.headers { - request_builder = request_builder.header(key.as_str(), value.as_str()); + for (key, value) in headers.iter() { + request_builder = request_builder.header(key, value); } - let body = self.body.map(Bytes::from).unwrap_or_default(); - let request = request_builder + let body = request.body.clone().into_bytes()?; + let http_request = request_builder .body(body) .map_err(|e| Error::HttpProtocol(format!("Failed to build request: {}", e)))?; // Send streaming request with TTFB timeout - let send_fut = h2_conn.send_request_streaming(request); - let (response, rx) = if let Some(ttfb_timeout) = self.client.timeouts.ttfb { + let send_fut = h2_conn.send_request_streaming(http_request); + let (response, rx) = if let Some(ttfb_timeout) = timeouts.ttfb { tokio_timeout(ttfb_timeout, send_fut) .await .map_err(|_| Error::TtfbTimeout(ttfb_timeout))?? @@ -329,34 +509,95 @@ impl<'a> RequestBuilder<'a> { // Convert http::Response to our Response type let status = response.status().as_u16(); - let headers: Vec = response + let headers = response .headers() .iter() - .map(|(k, v)| format!("{}: {}", k.as_str(), v.to_str().unwrap_or(""))) - .collect(); + .map(|(k, v)| (k.as_str().to_string(), v.to_str().unwrap_or("").to_string())) + .collect::>(); let our_response = crate::response::Response::new( status, - headers, + Headers::from(headers), Bytes::new(), // Body comes through rx "HTTP/2".to_string(), ); - Ok((our_response.with_url(self.uri.clone()), rx)) + let request_url = request.url.clone(); + let our_response = our_response.with_url(request_url.clone()); + + if let Some(jar) = &client.cookie_store { + jar.write() + .await + .store_from_headers(our_response.headers(), request_url.as_str()); + } + + Ok((our_response, rx)) } +} - /// Send the request and return the response. - pub async fn send(self) -> Result { - let version = self.version.unwrap_or(self.client.default_version); +impl Client { + /// Execute a built request with client policy (redirects, cookies, etc.). + pub async fn execute(&self, mut request: Request) -> Result { + let policy = self.redirect_policy.clone(); + let mut redirects = 0u32; + + loop { + let mut headers = request.headers.clone(); + let cookie_injected = self.apply_cookie_header(&request, &mut headers).await; + request.headers = headers; + + let mut timeouts = self.timeouts.clone(); + if let Some(total) = request.timeout { + timeouts.total = Some(total); + } + + let response = self.execute_once(&request, &timeouts).await?; + + self.store_cookies(&response, &request.url).await; + + if matches!(policy, RedirectPolicy::None) || !response.is_redirect() { + return Ok(response); + } + + let location = match response.redirect_url() { + Some(value) => value, + None => return Ok(response), + }; + + if let RedirectPolicy::Limited(limit) = policy { + if redirects >= limit { + return Err(Error::RedirectLimit { count: limit }); + } + } + + let next_url = request.url.join(location).map_err(Error::from)?; + let mut next_request = self.redirect_request(&request, &response, next_url); + + if cookie_injected { + next_request.headers.remove("cookie"); + } + + request = next_request; + redirects += 1; + } + } + + async fn execute_once(&self, request: &Request, timeouts: &Timeouts) -> Result { + let version = request.version.unwrap_or(self.default_version); // HTTP/3 only - go directly to H3 if matches!(version, HttpVersion::Http3Only) { - return self.send_h3().await; + return self + .send_h3_for_url(request, request.url.clone(), timeouts) + .await; } // HTTP/3 preferred - try H3 first, fall back to H1/H2 if matches!(version, HttpVersion::Http3) { - match self.send_h3_inner().await { + match self + .send_h3_for_url(request, request.url.clone(), timeouts) + .await + { Ok(response) => return Ok(response), Err(e) => { tracing::debug!("HTTP/3 failed, falling back to HTTP/1.1 or HTTP/2: {}", e); @@ -366,41 +607,28 @@ impl<'a> RequestBuilder<'a> { } // Auto mode - check Alt-Svc cache for HTTP/3 upgrade opportunity - if matches!(version, HttpVersion::Auto) && self.client.h3_upgrade_enabled { - let origin = self.get_origin(); - if let Some(alt_svc) = self.client.alt_svc_cache.get_h3_alternative(&origin).await { + if matches!(version, HttpVersion::Auto) && self.h3_upgrade_enabled { + let origin = Self::origin_for_url(&request.url); + if let Some(alt_svc) = self.alt_svc_cache.get_h3_alternative(&origin).await { tracing::debug!( "Alt-Svc indicates HTTP/3 support for {}, attempting upgrade", origin ); - // Try HTTP/3 to the alternative endpoint - let h3_url = if let Some(ref host) = alt_svc.host { - // Different host - format!("https://{}:{}{}", host, alt_svc.port, self.get_path()) - } else { - // Same host, different port (or same port) - self.uri.clone() - }; + let mut h3_url = request.url.clone(); + let _ = h3_url.set_scheme("https"); + if let Some(ref host) = alt_svc.host { + h3_url + .set_host(Some(host)) + .map_err(|_| Error::HttpProtocol("Invalid Alt-Svc host".into()))?; + } + let _ = h3_url.set_port(Some(alt_svc.port)); match self - .client - .h3_client - .send_request( - &h3_url, - self.method.as_str(), - self.headers - .iter() - .map(|(k, v)| (k.as_str(), v.as_str())) - .collect(), - self.body.clone(), - ) + .send_h3_for_url(request, h3_url.clone(), timeouts) .await { - Ok(response) => { - let resp: Response = response; - return Ok(resp.with_url(h3_url)); - } + Ok(response) => return Ok(response.with_url(h3_url)), Err(e) => { tracing::debug!("HTTP/3 upgrade failed, using HTTP/1.1 or HTTP/2: {}", e); // Fall through to H1/H2 @@ -410,28 +638,30 @@ impl<'a> RequestBuilder<'a> { } // HTTP/1.1 or HTTP/2 via TCP+TLS - self.send_h1_h2(version).await + self.send_h1_h2(request, version, timeouts).await } - /// Send via HTTP/3 only (no fallback). - async fn send_h3(self) -> Result { - self.send_h3_inner().await - } + async fn send_h3_for_url( + &self, + request: &Request, + url: Url, + timeouts: &Timeouts, + ) -> Result { + let body = if request.body.is_empty() { + None + } else { + Some(request.body.clone().into_bytes()?.to_vec()) + }; - /// Internal HTTP/3 send. - async fn send_h3_inner(&self) -> Result { - let fut = self.client.h3_client.send_request( - &self.uri, - self.method.as_str(), - self.headers - .iter() - .map(|(k, v)| (k.as_str(), v.as_str())) - .collect(), - self.body.clone(), + let fut = self.h3_client.send_request( + url.as_str(), + request.method.as_str(), + request.headers.to_vec(), + body, ); // Apply total timeout for HTTP/3 (includes connect + request + response) - let response = if let Some(total_timeout) = self.client.timeouts.total { + let response = if let Some(total_timeout) = timeouts.total { tokio_timeout(total_timeout, fut) .await .map_err(|_| Error::TotalTimeout(total_timeout))?? @@ -439,21 +669,22 @@ impl<'a> RequestBuilder<'a> { fut.await? }; - // Set effective_url so redirect engines can track the current URL - Ok(response.with_url(self.uri.clone())) + Ok(response.with_url(url)) } - /// Send via HTTP/1.1 or HTTP/2. - /// - /// HTTP/2 connections are pooled and multiplexed - subsequent requests to the - /// same host:port reuse the existing connection instead of creating a new one. - async fn send_h1_h2(self, version: HttpVersion) -> Result { + async fn send_h1_h2( + &self, + request: &Request, + version: HttpVersion, + timeouts: &Timeouts, + ) -> Result { // Save the original URL for effective_url tracking - let request_url = self.uri.clone(); + let request_url = request.url.clone(); // Parse URI - let uri: Uri = self - .uri + let uri: Uri = request + .url + .as_str() .parse() .map_err(|e| Error::HttpProtocol(format!("Invalid URI: {}", e)))?; @@ -464,21 +695,28 @@ impl<'a> RequestBuilder<'a> { HttpVersion::Http3 | HttpVersion::Http3Only => { return Err(Error::HttpProtocol("HTTP/3 should use send_h3".into())); } - HttpVersion::Auto => matches!(self.client.default_version, HttpVersion::Http2), + HttpVersion::Auto => matches!(self.default_version, HttpVersion::Http2), }; // Extract values needed after potential moves - let h3_upgrade_enabled = self.client.h3_upgrade_enabled; - let alt_svc_cache = self.client.alt_svc_cache.clone(); - let origin = self.get_origin(); + let h3_upgrade_enabled = self.h3_upgrade_enabled; + let alt_svc_cache = self.alt_svc_cache.clone(); + let origin = Self::origin_for_url(&request.url); + + let headers_vec = request.headers.to_vec(); + let body_bytes = if request.body.is_empty() { + None + } else { + Some(request.body.clone().into_bytes()?) + }; // For HTTP/2, try to use pooled connection first if prefer_http2 { - let pool_key = Self::make_pool_key(&uri); + let pool_key = self.make_pool_key(&uri); // Check for existing pooled connection let pooled = { - let pool = self.client.h2_pool.read().await; + let pool = self.h2_pool.read().await; pool.get(&pool_key).cloned() }; @@ -486,10 +724,10 @@ impl<'a> RequestBuilder<'a> { // Try to use pooled connection let result = conn .send_request( - self.method.clone(), + request.method.clone(), &uri, - self.headers.clone(), - self.body.clone().map(Bytes::from), + headers_vec.clone(), + body_bytes.clone(), ) .await; @@ -506,7 +744,7 @@ impl<'a> RequestBuilder<'a> { Err(e) => { // Connection failed - remove from pool and create new one tracing::debug!("Pooled HTTP/2 connection failed, creating new: {}", e); - let mut pool = self.client.h2_pool.write().await; + let mut pool = self.h2_pool.write().await; pool.remove(&pool_key); } } @@ -514,9 +752,9 @@ impl<'a> RequestBuilder<'a> { // No pooled connection or it failed - create new one // Apply connect timeout - let connector = self.client.connector_for_uri(&uri); + let connector = self.connector_for_uri(&uri); let connect_fut = connector.connect(&uri); - let stream = if let Some(connect_timeout) = self.client.timeouts.connect { + let stream = if let Some(connect_timeout) = timeouts.connect { tokio_timeout(connect_timeout, connect_fut) .await .map_err(|_| Error::ConnectTimeout(connect_timeout))?? @@ -525,8 +763,7 @@ impl<'a> RequestBuilder<'a> { }; // Verify ALPN negotiated h2 - let use_http2 = if self.client.http2_prior_knowledge && !stream.alpn_protocol().is_h2() - { + let use_http2 = if self.http2_prior_knowledge && !stream.alpn_protocol().is_h2() { // For Prior Knowledge, we use H2 if strictly requested, even if no ALPN (e.g. cleartext) true } else if let MaybeHttpsStream::Https(ref ssl_stream) = stream { @@ -537,29 +774,26 @@ impl<'a> RequestBuilder<'a> { if use_http2 { // Create HTTP/2 connection and pool it - let h2_conn = H2Connection::connect( - stream, - self.client.http2_settings.clone(), - self.client.pseudo_order, - ) - .await?; + let h2_conn = + H2Connection::connect(stream, self.http2_settings.clone(), self.pseudo_order) + .await?; let pooled_conn = H2PooledConnection::new(h2_conn); // Store in pool { - let mut pool = self.client.h2_pool.write().await; + let mut pool = self.h2_pool.write().await; pool.insert(pool_key, pooled_conn.clone()); } // Send request with TTFB timeout let fut = pooled_conn.send_request( - self.method, + request.method.clone(), &uri, - self.headers, - self.body.map(Bytes::from), + headers_vec.clone(), + body_bytes.clone(), ); - let response = if let Some(ttfb_timeout) = self.client.timeouts.ttfb { + let response = if let Some(ttfb_timeout) = timeouts.ttfb { tokio_timeout(ttfb_timeout, fut) .await .map_err(|_| Error::TtfbTimeout(ttfb_timeout))? @@ -580,10 +814,10 @@ impl<'a> RequestBuilder<'a> { } // HTTP/1.1 path (with connection pooling) - let pool_key = Self::make_pool_key(&uri); + let pool_key = self.make_pool_key(&uri); // Try to get a pooled connection first - let mut stream_opt = self.client.h1_pool.get_h1(&pool_key).await; + let mut stream_opt = self.h1_pool.get_h1(&pool_key).await; let mut used_pooled = stream_opt.is_some(); // If no pooled connection, create a new one @@ -593,9 +827,9 @@ impl<'a> RequestBuilder<'a> { } else { tracing::debug!("H1: Creating new connection for {:?}", pool_key); // Apply connect timeout - let connector = self.client.connector_for_uri(&uri); + let connector = self.connector_for_uri(&uri); let connect_fut = connector.connect(&uri); - if let Some(connect_timeout) = self.client.timeouts.connect { + if let Some(connect_timeout) = timeouts.connect { tokio_timeout(connect_timeout, connect_fut) .await .map_err(|_| Error::ConnectTimeout(connect_timeout))?? @@ -616,29 +850,26 @@ impl<'a> RequestBuilder<'a> { // Server negotiated HTTP/2 - we must speak HTTP/2 or they'll close connection tracing::debug!("Server selected h2 via ALPN, upgrading to HTTP/2"); - let h2_conn = H2Connection::connect( - stream, - self.client.http2_settings.clone(), - self.client.pseudo_order, - ) - .await?; + let h2_conn = + H2Connection::connect(stream, self.http2_settings.clone(), self.pseudo_order) + .await?; let pooled_conn = H2PooledConnection::new(h2_conn); // Store in pool for reuse { - let mut pool = self.client.h2_pool.write().await; + let mut pool = self.h2_pool.write().await; pool.insert(pool_key, pooled_conn.clone()); } // Send request with TTFB timeout let fut = pooled_conn.send_request( - self.method, + request.method.clone(), &uri, - self.headers, - self.body.map(Bytes::from), + headers_vec.clone(), + body_bytes.clone(), ); - if let Some(ttfb_timeout) = self.client.timeouts.ttfb { + if let Some(ttfb_timeout) = timeouts.ttfb { tokio_timeout(ttfb_timeout, fut) .await .map_err(|_| Error::TtfbTimeout(ttfb_timeout))? @@ -653,14 +884,14 @@ impl<'a> RequestBuilder<'a> { let stream_for_request = stream; let fut = Self::do_send_http1( stream_for_request, - self.method.clone(), + request.method.clone(), &uri, - self.headers.clone(), - self.body.clone().map(Bytes::from), + headers_vec.clone(), + body_bytes.clone(), ); // Apply TTFB timeout for HTTP/1.1 request - let request_result = if let Some(ttfb_timeout) = self.client.timeouts.ttfb { + let request_result = if let Some(ttfb_timeout) = timeouts.ttfb { tokio_timeout(ttfb_timeout, fut) .await .map_err(|_| Error::TtfbTimeout(ttfb_timeout))? @@ -671,10 +902,7 @@ impl<'a> RequestBuilder<'a> { match request_result { Ok((resp, returned_stream)) => { // Success - return stream to pool for reuse - self.client - .h1_pool - .put_h1(pool_key.clone(), returned_stream) - .await; + self.h1_pool.put_h1(pool_key.clone(), returned_stream).await; break Ok(resp); } Err(e) => { @@ -686,9 +914,9 @@ impl<'a> RequestBuilder<'a> { e ); // Try again with a fresh connection (with connect timeout) - let connector = self.client.connector_for_uri(&uri); + let connector = self.connector_for_uri(&uri); let connect_fut = connector.connect(&uri); - stream = if let Some(connect_timeout) = self.client.timeouts.connect { + stream = if let Some(connect_timeout) = timeouts.connect { tokio_timeout(connect_timeout, connect_fut) .await .map_err(|_| Error::ConnectTimeout(connect_timeout))?? @@ -723,12 +951,67 @@ impl<'a> RequestBuilder<'a> { Ok(response.with_url(request_url)) } + fn redirect_request(&self, request: &Request, response: &Response, next_url: Url) -> Request { + let status = response.status().as_u16(); + let mut method = request.method.clone(); + let mut body = request.body.clone(); + let mut headers = request.headers.clone(); + + let should_switch = status == 303 + || ((status == 301 || status == 302) && !matches!(method, Method::GET | Method::HEAD)); + + if should_switch { + method = Method::GET; + body = Body::Empty; + headers.remove("content-length"); + headers.remove("content-type"); + } + + if Self::is_cross_origin(&request.url, &next_url) { + headers.remove("authorization"); + } + + Request { + method, + url: next_url, + headers, + body, + version: request.version, + timeout: request.timeout, + } + } + + async fn apply_cookie_header(&self, request: &Request, headers: &mut Headers) -> bool { + if let Some(jar) = &self.cookie_store { + if !headers.contains("cookie") { + if let Some(cookie_header) = + jar.read().await.build_cookie_header(request.url.as_str()) + { + headers.insert("Cookie", cookie_header); + return true; + } + } + } + false + } + + async fn store_cookies(&self, response: &Response, url: &Url) { + if let Some(jar) = &self.cookie_store { + jar.write() + .await + .store_from_headers(response.headers(), url.as_str()); + } + } + /// Create a pool key from a URI. - fn make_pool_key(uri: &Uri) -> PoolKey { + fn make_pool_key(&self, uri: &Uri) -> PoolKey { let host = uri.host().unwrap_or("localhost").to_string(); let is_https = uri.scheme_str() == Some("https"); let port = uri.port_u16().unwrap_or(if is_https { 443 } else { 80 }); - PoolKey::new(host, port, is_https) + match &self.proxy { + Some(proxy) => PoolKey::with_proxy(host, port, is_https, proxy.proxy_key()), + None => PoolKey::new(host, port, is_https), + } } async fn do_send_http1( @@ -744,34 +1027,25 @@ impl<'a> RequestBuilder<'a> { Ok((response, stream)) } - /// Extract origin (scheme://host:port) from URI. - fn get_origin(&self) -> String { - if let Ok(uri) = self.uri.parse::() { - let scheme = uri.scheme_str().unwrap_or("https"); - let host = uri.host().unwrap_or("localhost"); - let port = uri - .port_u16() - .unwrap_or(if scheme == "https" { 443 } else { 80 }); + /// Extract origin (scheme://host:port) from URL. + fn origin_for_url(url: &Url) -> String { + let scheme = url.scheme(); + let host = url.host_str().unwrap_or("localhost"); + let port = url + .port_or_known_default() + .unwrap_or(if scheme == "https" { 443 } else { 80 }); - if (scheme == "https" && port == 443) || (scheme == "http" && port == 80) { - format!("{}://{}", scheme, host) - } else { - format!("{}://{}:{}", scheme, host, port) - } + if (scheme == "https" && port == 443) || (scheme == "http" && port == 80) { + format!("{}://{}", scheme, host) } else { - self.uri.clone() + format!("{}://{}:{}", scheme, host, port) } } - /// Extract path from URI. - fn get_path(&self) -> String { - if let Ok(uri) = self.uri.parse::() { - uri.path_and_query() - .map(|pq| pq.as_str().to_string()) - .unwrap_or_else(|| "/".to_string()) - } else { - "/".to_string() - } + fn is_cross_origin(a: &Url, b: &Url) -> bool { + a.scheme() != b.scheme() + || a.host_str() != b.host_str() + || a.port_or_known_default() != b.port_or_known_default() } } @@ -797,6 +1071,10 @@ impl ClientBuilder { use_platform_roots: false, danger_accept_invalid_certs: false, localhost_allows_invalid_certs: true, // Enable by default for easier local dev + default_headers: Headers::new(), + redirect_policy: RedirectPolicy::None, + cookie_store: None, + proxy: None, } } @@ -892,6 +1170,56 @@ impl ClientBuilder { self } + /// Set default headers applied to every request. + pub fn default_headers(mut self, headers: impl Into) -> Self { + self.default_headers = headers.into(); + self + } + + /// Add or replace a single default header. + pub fn default_header(mut self, name: impl Into, value: impl Into) -> Self { + self.default_headers.insert(name, value); + self + } + + /// Convenience for setting the User-Agent default header. + pub fn user_agent(mut self, value: impl Into) -> Self { + self.default_headers.insert("User-Agent", value.into()); + self + } + + /// Set redirect policy. + pub fn redirect_policy(mut self, policy: RedirectPolicy) -> Self { + self.redirect_policy = policy; + self + } + + /// Enable or disable the cookie store. + pub fn cookie_store(mut self, enabled: bool) -> Self { + if enabled { + self.cookie_store = Some(Arc::new(RwLock::new(CookieJar::new()))); + } else { + self.cookie_store = None; + } + self + } + + /// Provide a custom cookie jar to use for requests. + pub fn cookie_jar(mut self, jar: Arc>) -> Self { + self.cookie_store = Some(jar); + self + } + + /// Set proxy configuration for all connections. + /// + /// Supports SOCKS5 and HTTP CONNECT proxies with optional authentication. + /// SOCKS5 proxies support HTTP/1.1, HTTP/2 (via TCP CONNECT) and HTTP/3 (via UDP ASSOCIATE). + /// HTTP CONNECT proxies only support HTTP/1.1 and HTTP/2. + pub fn proxy(mut self, proxy: crate::proxy::ProxyConfig) -> Self { + self.proxy = Some(proxy); + self + } + /// Set HTTP/2 preference (for Auto version selection). pub fn prefer_http2(mut self, prefer: bool) -> Self { self.prefer_http2 = prefer; @@ -976,14 +1304,25 @@ impl ClientBuilder { connector = connector.danger_accept_invalid_certs(true); } + // Apply proxy configuration if set + if let Some(ref proxy) = self.proxy { + connector = connector.with_proxy(proxy.clone()); + } + // Create insecure connector for localhost (always skips TLS verification) - let insecure_connector = BoringConnector::with_fingerprint(tls_fingerprint.clone()) + let mut insecure_connector = BoringConnector::with_fingerprint(tls_fingerprint.clone()) .with_root_certificates(self.root_certs) .with_platform_roots(self.use_platform_roots) .danger_accept_invalid_certs(true); + if let Some(ref proxy) = self.proxy { + insecure_connector = insecure_connector.with_proxy(proxy.clone()); + } // Create H3 client with same TLS fingerprint - let h3_client = H3Client::with_fingerprint(tls_fingerprint); + let mut h3_client = H3Client::with_fingerprint(tls_fingerprint); + if let Some(ref proxy) = self.proxy { + h3_client = h3_client.with_proxy(proxy.clone()); + } // Use provided HTTP/2 settings or default from fingerprint let http2_settings = self.http2_settings.unwrap_or_default(); @@ -1010,6 +1349,10 @@ impl ClientBuilder { http2_prior_knowledge: self.http2_prior_knowledge, danger_accept_invalid_certs: self.danger_accept_invalid_certs, localhost_allows_invalid_certs: self.localhost_allows_invalid_certs, + default_headers: self.default_headers, + redirect_policy: self.redirect_policy, + cookie_store: self.cookie_store, + proxy: self.proxy, }) } } diff --git a/src/transport/h2/connection.rs b/src/transport/h2/connection.rs index 926a6670..ebb26dcc 100644 --- a/src/transport/h2/connection.rs +++ b/src/transport/h2/connection.rs @@ -1367,11 +1367,7 @@ where if let Some(stream) = self.streams.remove(&stream_id) { let response = SpecterResponse::new( status, - stream - .response_headers - .iter() - .map(|(n, v)| format!("{}: {}", n, v)) - .collect(), + crate::headers::Headers::from(stream.response_headers), stream.response_data.freeze(), "HTTP/2".to_string(), ); diff --git a/src/transport/h2/handle.rs b/src/transport/h2/handle.rs index 33744883..09b4ae53 100644 --- a/src/transport/h2/handle.rs +++ b/src/transport/h2/handle.rs @@ -8,6 +8,7 @@ use http::{Method, Uri}; use tokio::sync::mpsc; use crate::error::{Error, Result}; +use crate::headers::Headers; use crate::response::Response; use crate::transport::h2::driver::DriverCommand; @@ -59,11 +60,7 @@ impl H2Handle { // Convert StreamResponse to Response Ok(Response::new( stream_response.status, - stream_response - .headers - .iter() - .map(|(n, v)| format!("{}: {}", n, v)) - .collect(), + Headers::from(stream_response.headers), stream_response.body, "HTTP/2".to_string(), )) diff --git a/src/transport/h3/connection.rs b/src/transport/h3/connection.rs index 2315ffa8..72cef12b 100644 --- a/src/transport/h3/connection.rs +++ b/src/transport/h3/connection.rs @@ -4,6 +4,8 @@ use std::net::SocketAddr; use std::sync::Arc; use std::time::Instant; use tokio::net::UdpSocket; +use crate::proxy::ProxyConfig; +use crate::proxy::udp_transport::{QuicUdpTransport, DirectUdpTransport, Socks5UdpTransport}; use tokio::sync::mpsc; use crate::error::{Error, Result}; @@ -18,7 +20,7 @@ pub struct H3Connection; impl H3Connection { /// Connect to an HTTP/3 server and return a handle. /// This spawns a background driver task. - pub async fn connect(url: &str, mut config: quiche::Config) -> Result { + pub async fn connect(url: &str, mut config: quiche::Config, proxy: Option<&ProxyConfig>) -> Result { let (host, port, _path) = parse_url(url)?; // Resolve peer @@ -28,10 +30,29 @@ impl H3Connection { .next() .ok_or_else(|| Error::Connection("DNS/IP not found".into()))?; - // Bind local socket - let local_addr: SocketAddr = "0.0.0.0:0".parse().unwrap(); - let socket = UdpSocket::bind(local_addr).await.map_err(Error::Io)?; - let socket = Arc::new(socket); + // Create UDP transport (direct or via SOCKS5 relay) + let (transport, local_addr): (Box, SocketAddr) = match proxy { + Some(ProxyConfig::Socks5 { host: ph, port: pp, auth }) => { + let local_socket = UdpSocket::bind("0.0.0.0:0").await.map_err(Error::Io)?; + let local_udp_addr = local_socket.local_addr().map_err(Error::Io)?; + let local_socket = Arc::new(local_socket); + + let association = crate::proxy::socks5::socks5_udp_associate( + ph, *pp, local_udp_addr, auth.as_ref() + ).await?; + + let addr = local_socket.local_addr().map_err(Error::Io)?; + let transport = Socks5UdpTransport::new(local_socket, association.relay_addr, association.control_tcp); + (Box::new(transport) as Box, addr) + } + _ => { + // Direct UDP (original behavior); also covers HttpConnect (no UDP path for H3) + let socket = UdpSocket::bind("0.0.0.0:0").await.map_err(Error::Io)?; + let addr = socket.local_addr().map_err(Error::Io)?; + let socket = Arc::new(socket); + (Box::new(DirectUdpTransport::new(socket)) as Box, addr) + } + }; // Generate CID let mut scid = [0u8; 20]; @@ -42,7 +63,7 @@ impl H3Connection { let mut conn = quiche::connect( Some(&host), &scid, - socket.local_addr().unwrap(), + local_addr, peer_addr, &mut config, ) @@ -66,8 +87,8 @@ impl H3Connection { loop { match conn.send(&mut out) { Ok((len, _)) => { - socket - .send_to(&out[..len], peer_addr) + transport + .send_to_target(&out[..len], peer_addr) .await .map_err(Error::Io)?; } @@ -88,15 +109,13 @@ impl H3Connection { .timeout() .unwrap_or(std::time::Duration::from_millis(100)); // Use small timeout for recv to allow sending keep-alives/re-transmits - match tokio::time::timeout(recv_timeout, socket.recv_from(&mut buf)).await { + match tokio::time::timeout(recv_timeout, transport.recv_from_target(&mut buf)).await { Ok(Ok((len, from))) => { - if from == peer_addr { - let info = quiche::RecvInfo { - from, - to: socket.local_addr().unwrap(), - }; - let _ = conn.recv(&mut buf[..len], info); - } + let info = quiche::RecvInfo { + from, + to: transport.local_addr().unwrap(), + }; + let _ = conn.recv(&mut buf[..len], info); } Ok(Err(e)) => return Err(Error::Io(e)), Err(_) => { @@ -113,7 +132,7 @@ impl H3Connection { // Spawn Driver let (tx, rx) = mpsc::channel(32); - let driver = H3Driver::new(rx, conn, h3_conn, socket.clone(), peer_addr); + let driver = H3Driver::new(rx, conn, h3_conn, transport, peer_addr); tokio::spawn(async move { if let Err(e) = driver.drive().await { diff --git a/src/transport/h3/driver.rs b/src/transport/h3/driver.rs index 54cb9ad0..5c016c97 100644 --- a/src/transport/h3/driver.rs +++ b/src/transport/h3/driver.rs @@ -1,13 +1,12 @@ //! HTTP/3 connection driver - background task that reads packets and routes them to streams. //! -//! The driver owns the QUIC connection and UdpSocket. +//! The driver owns the QUIC connection and routes packets through a QuicUdpTransport. use bytes::{Bytes, BytesMut}; use std::collections::HashMap; use std::net::SocketAddr; -use std::sync::Arc; use std::time::Duration; -use tokio::net::UdpSocket; +use crate::proxy::udp_transport::QuicUdpTransport; use tokio::sync::mpsc; use tokio::sync::oneshot; use tokio::time::sleep; @@ -64,7 +63,7 @@ pub struct H3Driver { command_rx: mpsc::Receiver, conn: quiche::Connection, h3_conn: quiche::h3::Connection, - socket: Arc, + transport: Box, peer_addr: SocketAddr, streams: HashMap, } @@ -74,14 +73,14 @@ impl H3Driver { command_rx: mpsc::Receiver, conn: quiche::Connection, h3_conn: quiche::h3::Connection, - socket: Arc, + transport: Box, peer_addr: SocketAddr, ) -> Self { Self { command_rx, conn, h3_conn, - socket, + transport, peer_addr, streams: HashMap::new(), } @@ -112,7 +111,7 @@ impl H3Driver { loop { match self.conn.send(&mut out) { Ok((len, _)) => { - if let Err(e) = self.socket.send_to(&out[..len], self.peer_addr).await { + if let Err(e) = self.transport.send_to_target(&out[..len], self.peer_addr).await { tracing::error!("H3 socket send error: {}", e); return Err(Error::Io(e)); } @@ -140,7 +139,7 @@ impl H3Driver { Err(_) => {} } while let Ok((len, _)) = self.conn.send(&mut out) { - let _ = self.socket.send_to(&out[..len], self.peer_addr).await; + let _ = self.transport.send_to_target(&out[..len], self.peer_addr).await; } return Ok(()); } @@ -148,24 +147,20 @@ impl H3Driver { } // Incoming Packet - res = self.socket.recv_from(&mut buf) => { + res = self.transport.recv_from_target(&mut buf) => { match res { - Ok((len, from)) => { - if from == self.peer_addr { - let info = quiche::RecvInfo { - from, - to: self.socket.local_addr().unwrap(), - // to: self.socket.local_addr().unwrap(), // Need to handle unchecked? - // The original code unwrapped, presumably safe if bound. - }; - match self.conn.recv(&mut buf[..len], info) { - Ok(_) => { - self.process_h3_events()?; - } - Err(quiche::Error::Done) => {}, - Err(e) => { - tracing::warn!("QUIC recv error: {}", e); - } + Ok((len, _from)) => { + let info = quiche::RecvInfo { + from: self.peer_addr, + to: self.transport.local_addr().unwrap(), + }; + match self.conn.recv(&mut buf[..len], info) { + Ok(_) => { + self.process_h3_events()?; + } + Err(quiche::Error::Done) => {}, + Err(e) => { + tracing::warn!("QUIC recv error: {}", e); } } } diff --git a/src/transport/h3/handle.rs b/src/transport/h3/handle.rs index 1072f4c6..76a317cd 100644 --- a/src/transport/h3/handle.rs +++ b/src/transport/h3/handle.rs @@ -8,6 +8,7 @@ use tokio::sync::mpsc; use tokio::sync::oneshot; use crate::error::{Error, Result}; +use crate::headers::Headers; use crate::response::Response; use crate::transport::h3::driver::DriverCommand; @@ -59,11 +60,7 @@ impl H3Handle { // Convert StreamResponse to Response Ok(Response::new( stream_response.status, - stream_response - .headers - .iter() - .map(|(n, v)| format!("{}: {}", n, v)) - .collect(), + Headers::from(stream_response.headers), stream_response.body, "HTTP/3".to_string(), )) diff --git a/src/transport/h3/mod.rs b/src/transport/h3/mod.rs index fb0272f9..f3a4411b 100644 --- a/src/transport/h3/mod.rs +++ b/src/transport/h3/mod.rs @@ -22,7 +22,7 @@ use crate::response::Response; pub struct H3Client { tls_fingerprint: Option, verify_peer: bool, - // In future: connection pool + proxy: Option, } impl Default for H3Client { @@ -36,6 +36,7 @@ impl H3Client { Self { tls_fingerprint: None, verify_peer: true, + proxy: None, } } @@ -43,6 +44,7 @@ impl H3Client { Self { tls_fingerprint: Some(fp), verify_peer: true, + proxy: None, } } @@ -52,6 +54,11 @@ impl H3Client { self } + pub fn with_proxy(mut self, proxy: crate::proxy::ProxyConfig) -> Self { + self.proxy = Some(proxy); + self + } + /// Send a request. /// Warning: Currently establishes a NEW connection every time (simple wrapper). /// To use multiplexing, use `connect()` to get a handle, then reuse handle. @@ -60,7 +67,7 @@ impl H3Client { &self, url: &str, method: &str, - headers: Vec<(&str, &str)>, + headers: Vec<(String, String)>, body: Option>, ) -> Result { let (_host, _port, _path) = parse_url_host(url)?; @@ -69,13 +76,7 @@ impl H3Client { // Implementing full pooling inside H3Client is Phase 2. let config = self.create_quic_config()?; - let handle = H3Connection::connect(url, config).await?; - - // Convert headers - let headers_string: Vec<(String, String)> = headers - .iter() - .map(|(k, v)| (k.to_string(), v.to_string())) - .collect(); + let handle = H3Connection::connect(url, config, self.proxy.as_ref()).await?; // Convert body let body_bytes = body.map(bytes::Bytes::from); @@ -88,7 +89,7 @@ impl H3Client { .map_err(|_| Error::HttpProtocol("Invalid Method".into()))?; handle - .send_request(method_http, &uri, headers_string, body_bytes) + .send_request(method_http, &uri, headers, body_bytes) .await } diff --git a/tests/benchmarks.rs b/tests/benchmarks.rs deleted file mode 100644 index eba1b952..00000000 --- a/tests/benchmarks.rs +++ /dev/null @@ -1,53 +0,0 @@ -use specter::Client; -use std::time::Instant; - -/// Benchmark HTTP/1.1 connection pooling performance -#[tokio::test] -#[ignore] // Run with: cargo test --test benchmarks -- --ignored -async fn benchmark_h1_pooling() { - // This test requires H1 pooling to be integrated into Client - // Currently, Client doesn't use ConnectionPool for H1 - - let _client = Client::builder().prefer_http2(false).build().unwrap(); - - // TODO: Use mock server once H1 pooling is integrated - tracing::info!("H1 pooling benchmark - requires integration"); -} - -/// Benchmark HTTP/2 multiplexing performance -#[tokio::test] -#[ignore] -async fn benchmark_h2_multiplexing() { - let client = Client::builder().prefer_http2(true).build().unwrap(); - - let url = "https://nghttp2.org/httpbin/delay/1"; - - // Pre-warm connection - let _ = client - .get("https://nghttp2.org/robots.txt") - .send() - .await - .expect("Pre-warm failed"); - - // Measure 10 concurrent requests - let start = Instant::now(); - let mut tasks = Vec::new(); - - for _ in 0..10 { - let client_clone = client.clone(); - tasks.push(tokio::spawn( - async move { client_clone.get(url).send().await }, - )); - } - - for task in tasks { - let _ = task.await.unwrap().expect("Request failed"); - } - - let elapsed = start.elapsed(); - tracing::info!("10 concurrent H2 requests completed in {:?}", elapsed); - - // With true multiplexing: ~1s (all parallel) - // With serialization: ~10s (all sequential) - // Current: ~23s (severe serialization) -} diff --git a/tests/chrome_versions.rs b/tests/chrome_versions.rs new file mode 100644 index 00000000..a6bb44ad --- /dev/null +++ b/tests/chrome_versions.rs @@ -0,0 +1,326 @@ +//! Chrome multi-version fingerprint validation tests. +//! +//! Validates Chrome 142-146 fingerprint profiles produce correct +//! User-Agent strings, Sec-Ch-Ua headers, and shared TLS/HTTP2 config. + +use specter::fingerprint::profiles::FingerprintProfile; +use specter::fingerprint::tls::{CertCompression, TlsFingerprint}; +use specter::headers::{ + chrome_142_ajax_headers, chrome_142_form_headers, chrome_142_headers, chrome_143_ajax_headers, + chrome_143_form_headers, chrome_143_headers, chrome_144_ajax_headers, chrome_144_form_headers, + chrome_144_headers, chrome_145_ajax_headers, chrome_145_form_headers, chrome_145_headers, + chrome_146_ajax_headers, chrome_146_form_headers, chrome_146_headers, +}; + +#[test] +fn test_default_profile_is_chrome142() { + // Default must remain Chrome142 for SemVer backwards compatibility + assert_eq!(FingerprintProfile::default(), FingerprintProfile::Chrome142); +} + +#[test] +fn test_chrome_user_agents_contain_correct_version() { + let cases = [ + (FingerprintProfile::Chrome142, "Chrome/142.0.0.0"), + (FingerprintProfile::Chrome143, "Chrome/143.0.0.0"), + (FingerprintProfile::Chrome144, "Chrome/144.0.0.0"), + (FingerprintProfile::Chrome145, "Chrome/145.0.0.0"), + (FingerprintProfile::Chrome146, "Chrome/146.0.0.0"), + ]; + + for (profile, expected_version) in &cases { + let ua = profile.user_agent(); + assert!( + ua.contains(expected_version), + "Profile {:?} UA should contain '{}', got: {}", + profile, + expected_version, + ua + ); + // All should be macOS + assert!( + ua.contains("Macintosh; Intel Mac OS X 10_15_7"), + "UA should contain macOS platform" + ); + // All should have Safari token + assert!( + ua.contains("Safari/537.36"), + "UA should contain Safari token" + ); + } +} + +#[test] +fn test_chrome_tls_fingerprints_identical_across_versions() { + let profiles = [ + FingerprintProfile::Chrome142, + FingerprintProfile::Chrome143, + FingerprintProfile::Chrome144, + FingerprintProfile::Chrome145, + FingerprintProfile::Chrome146, + ]; + + let base = profiles[0].tls_fingerprint(); + + for profile in &profiles[1..] { + let fp = profile.tls_fingerprint(); + assert_eq!( + fp.cipher_list, base.cipher_list, + "Cipher suites should be identical for {:?}", + profile + ); + assert_eq!( + fp.sigalgs, base.sigalgs, + "Signature algorithms should be identical for {:?}", + profile + ); + assert_eq!( + fp.curves, base.curves, + "Curves should be identical for {:?}", + profile + ); + assert_eq!( + fp.extensions, base.extensions, + "Extensions should be identical for {:?}", + profile + ); + assert_eq!( + fp.grease, base.grease, + "GREASE should be identical for {:?}", + profile + ); + assert_eq!( + fp.cert_compression, base.cert_compression, + "Cert compression should be identical for {:?}", + profile + ); + assert_eq!( + fp.enable_kyber, base.enable_kyber, + "Kyber should be identical for {:?}", + profile + ); + } + + // Verify shared Chrome TLS properties + assert!(base.grease, "Chrome should use GREASE"); + assert_eq!( + base.cert_compression, + CertCompression::Brotli, + "Chrome should use Brotli cert compression" + ); + assert!(base.enable_kyber, "Chrome should enable Kyber"); +} + +#[test] +fn test_chrome_http2_settings_identical_across_versions() { + let profiles = [ + FingerprintProfile::Chrome142, + FingerprintProfile::Chrome143, + FingerprintProfile::Chrome144, + FingerprintProfile::Chrome145, + FingerprintProfile::Chrome146, + ]; + + let base = profiles[0].http2_settings(); + + for profile in &profiles[1..] { + let settings = profile.http2_settings(); + assert_eq!(settings.initial_window_size, base.initial_window_size); + assert_eq!(settings.initial_window_update, base.initial_window_update); + assert_eq!(settings.header_table_size, base.header_table_size); + assert_eq!(settings.max_frame_size, base.max_frame_size); + } +} + +#[test] +fn test_chrome_sec_ch_ua_brand_strings() { + // Verify each version has the correct GREASE brand string from Chromium algorithm + let nav_142 = chrome_142_headers(); + let nav_143 = chrome_143_headers(); + let nav_144 = chrome_144_headers(); + let nav_145 = chrome_145_headers(); + let nav_146 = chrome_146_headers(); + + fn get_sec_ch_ua<'a>(headers: &'a [(&str, &str)]) -> &'a str { + headers.iter().find(|(k, _)| *k == "Sec-Ch-Ua").unwrap().1 + } + + let ua_142 = get_sec_ch_ua(&nav_142); + let ua_143 = get_sec_ch_ua(&nav_143); + let ua_144 = get_sec_ch_ua(&nav_144); + let ua_145 = get_sec_ch_ua(&nav_145); + let ua_146 = get_sec_ch_ua(&nav_146); + + // Chrome 142: "Not_A Brand" v="24", order: Chromium, GC, GREASE + assert!( + ua_142.contains(r#""Not_A Brand";v="24""#), + "Chrome 142 brand: {}", + ua_142 + ); + assert!( + ua_142.starts_with(r#""Chromium""#), + "Chrome 142 order: {}", + ua_142 + ); + + // Chrome 143: "Not A(Brand" v="99", order: GC, Chromium, GREASE + assert!( + ua_143.contains(r#""Not A(Brand";v="99""#), + "Chrome 143 brand: {}", + ua_143 + ); + assert!( + ua_143.starts_with(r#""Google Chrome""#), + "Chrome 143 order: {}", + ua_143 + ); + + // Chrome 144: "Not(A:Brand" v="8", order: GREASE, Chromium, GC + assert!( + ua_144.contains(r#""Not(A:Brand";v="8""#), + "Chrome 144 brand: {}", + ua_144 + ); + assert!( + ua_144.starts_with(r#""Not(A:Brand""#), + "Chrome 144 order: {}", + ua_144 + ); + + // Chrome 145: "Not:A-Brand" v="24", order: GREASE, GC, Chromium + assert!( + ua_145.contains(r#""Not:A-Brand";v="24""#), + "Chrome 145 brand: {}", + ua_145 + ); + assert!( + ua_145.starts_with(r#""Not:A-Brand""#), + "Chrome 145 order: {}", + ua_145 + ); + + // Chrome 146: "Not-A.Brand" v="99", order: Chromium, GREASE, GC + assert!( + ua_146.contains(r#""Not-A.Brand";v="99""#), + "Chrome 146 brand: {}", + ua_146 + ); + assert!( + ua_146.starts_with(r#""Chromium""#), + "Chrome 146 order: {}", + ua_146 + ); + + // All should be distinct + let all = [ua_142, ua_143, ua_144, ua_145, ua_146]; + for i in 0..all.len() { + for j in (i + 1)..all.len() { + assert_ne!(all[i], all[j], "Sec-Ch-Ua should differ between versions"); + } + } +} + +#[test] +fn test_chrome_all_versions_have_three_header_types() { + // Verify each version exports navigation, AJAX, and form headers + let versions: Vec<(Vec<_>, Vec<_>, Vec<_>)> = vec![ + ( + chrome_142_headers(), + chrome_142_ajax_headers(), + chrome_142_form_headers(), + ), + ( + chrome_143_headers(), + chrome_143_ajax_headers(), + chrome_143_form_headers(), + ), + ( + chrome_144_headers(), + chrome_144_ajax_headers(), + chrome_144_form_headers(), + ), + ( + chrome_145_headers(), + chrome_145_ajax_headers(), + chrome_145_form_headers(), + ), + ( + chrome_146_headers(), + chrome_146_ajax_headers(), + chrome_146_form_headers(), + ), + ]; + + for (i, (nav, ajax, form)) in versions.iter().enumerate() { + let version = 142 + i; + + // Navigation headers should have Sec-Fetch-User + let nav_names: Vec<&str> = nav.iter().map(|(k, _)| *k).collect(); + assert!( + nav_names.contains(&"Sec-Fetch-User"), + "Chrome {} nav missing Sec-Fetch-User", + version + ); + assert!( + nav_names.contains(&"Upgrade-Insecure-Requests"), + "Chrome {} nav missing UIR", + version + ); + + // AJAX headers should have Content-Type: application/json + let ajax_ct = ajax.iter().find(|(k, _)| *k == "Content-Type"); + assert_eq!( + ajax_ct.unwrap().1, + "application/json", + "Chrome {} AJAX Content-Type", + version + ); + + // Form headers should have Content-Type: application/x-www-form-urlencoded + let form_ct = form.iter().find(|(k, _)| *k == "Content-Type"); + assert_eq!( + form_ct.unwrap().1, + "application/x-www-form-urlencoded", + "Chrome {} form Content-Type", + version + ); + + // All should have the same User-Agent containing the version number + let expected_ua_fragment = format!("Chrome/{}.0.0.0", version); + for (header_type, headers) in [("nav", nav), ("ajax", ajax), ("form", form)] { + let ua = headers.iter().find(|(k, _)| *k == "User-Agent").unwrap().1; + assert!( + ua.contains(&expected_ua_fragment), + "Chrome {} {} UA should contain '{}': {}", + version, + header_type, + expected_ua_fragment, + ua + ); + } + } +} + +#[test] +fn test_chrome_tls_constructors_match_shared() { + // All version-specific constructors should produce the same result as chrome() + let shared = TlsFingerprint::chrome(); + let constructors = [ + TlsFingerprint::chrome_142(), + TlsFingerprint::chrome_143(), + TlsFingerprint::chrome_144(), + TlsFingerprint::chrome_145(), + TlsFingerprint::chrome_146(), + ]; + + for (i, fp) in constructors.iter().enumerate() { + assert_eq!( + fp.cipher_list, + shared.cipher_list, + "chrome_{} ciphers", + 142 + i + ); + assert_eq!(fp.sigalgs, shared.sigalgs, "chrome_{} sigalgs", 142 + i); + assert_eq!(fp.curves, shared.curves, "chrome_{} curves", 142 + i); + } +} diff --git a/tests/compression.rs b/tests/compression.rs new file mode 100644 index 00000000..bdc6e86d --- /dev/null +++ b/tests/compression.rs @@ -0,0 +1,252 @@ +//! Content-Encoding / Compression Tests +//! +//! Tests that the specter client correctly handles compressed responses: +//! - gzip Content-Encoding +//! - deflate Content-Encoding +//! - brotli Content-Encoding +//! - zstd Content-Encoding +//! - Identity (no compression) baseline + +use specter::Client; +use std::io::Write; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpListener; + +mod helpers; + +const TEST_BODY: &str = + "Hello, compressed world! This is a test payload for verifying decompression."; + +/// Start a mock HTTP/1.1 server that returns a response with the given +/// Content-Encoding header and pre-compressed body bytes. +async fn start_encoding_server( + content_encoding: &'static str, + compressed_body: Vec, +) -> (String, tokio::task::JoinHandle<()>) { + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + let url = format!("http://127.0.0.1:{}/test", port); + + let handle = tokio::spawn(async move { + // Accept one connection. + let (mut stream, _) = listener.accept().await.unwrap(); + + // Read the request (drain it). + let mut buf = [0u8; 4096]; + let _ = stream.read(&mut buf).await; + + // Build the response. + let response = format!( + "HTTP/1.1 200 OK\r\n\ + Content-Encoding: {}\r\n\ + Content-Length: {}\r\n\ + Content-Type: text/plain\r\n\ + Connection: close\r\n\ + \r\n", + content_encoding, + compressed_body.len() + ); + + let _ = stream.write_all(response.as_bytes()).await; + let _ = stream.write_all(&compressed_body).await; + let _ = stream.flush().await; + }); + + (url, handle) +} + +/// Compress bytes with gzip. +fn gzip_compress(data: &[u8]) -> Vec { + let mut encoder = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default()); + encoder.write_all(data).unwrap(); + encoder.finish().unwrap() +} + +/// Compress bytes with deflate (zlib wrapper, which is what HTTP "deflate" means per RFC 7230). +fn deflate_compress(data: &[u8]) -> Vec { + let mut encoder = flate2::write::ZlibEncoder::new(Vec::new(), flate2::Compression::default()); + encoder.write_all(data).unwrap(); + encoder.finish().unwrap() +} + +/// Compress bytes with brotli. +fn brotli_compress(data: &[u8]) -> Vec { + let mut output = Vec::new(); + { + let mut writer = brotli::CompressorWriter::new(&mut output, 4096, 6, 22); + writer.write_all(data).unwrap(); + // Flush on drop. + } + output +} + +/// Compress bytes with zstd. +fn zstd_compress(data: &[u8]) -> Vec { + zstd::encode_all(data, 3).unwrap() +} + +/// Test transparent gzip decompression. +#[tokio::test] +async fn test_gzip_decompression() { + let compressed = gzip_compress(TEST_BODY.as_bytes()); + let (url, _handle) = start_encoding_server("gzip", compressed).await; + + tokio::time::sleep(std::time::Duration::from_millis(50)).await; + + let client = Client::builder().prefer_http2(false).build().unwrap(); + + let resp = client + .get(url.as_str()) + .send() + .await + .expect("Request failed"); + + assert_eq!(resp.status().as_u16(), 200); + assert_eq!( + resp.content_encoding(), + Some("gzip"), + "Content-Encoding header should be gzip" + ); + + // The decoded body should match the original text. + let text = resp.text().expect("Failed to decode response body"); + assert_eq!(text, TEST_BODY, "Decompressed body does not match original"); +} + +/// Test transparent deflate decompression. +#[tokio::test] +async fn test_deflate_decompression() { + let compressed = deflate_compress(TEST_BODY.as_bytes()); + let (url, _handle) = start_encoding_server("deflate", compressed).await; + + tokio::time::sleep(std::time::Duration::from_millis(50)).await; + + let client = Client::builder().prefer_http2(false).build().unwrap(); + + let resp = client + .get(url.as_str()) + .send() + .await + .expect("Request failed"); + + assert_eq!(resp.status().as_u16(), 200); + assert_eq!(resp.content_encoding(), Some("deflate")); + + let text = resp.text().expect("Failed to decode response body"); + assert_eq!( + text, TEST_BODY, + "Decompressed deflate body does not match original" + ); +} + +/// Test transparent brotli decompression. +#[tokio::test] +async fn test_brotli_decompression() { + let compressed = brotli_compress(TEST_BODY.as_bytes()); + let (url, _handle) = start_encoding_server("br", compressed).await; + + tokio::time::sleep(std::time::Duration::from_millis(50)).await; + + let client = Client::builder().prefer_http2(false).build().unwrap(); + + let resp = client + .get(url.as_str()) + .send() + .await + .expect("Request failed"); + + assert_eq!(resp.status().as_u16(), 200); + assert_eq!(resp.content_encoding(), Some("br")); + + let text = resp.text().expect("Failed to decode response body"); + assert_eq!( + text, TEST_BODY, + "Decompressed brotli body does not match original" + ); +} + +/// Test transparent zstd decompression. +#[tokio::test] +async fn test_zstd_decompression() { + let compressed = zstd_compress(TEST_BODY.as_bytes()); + let (url, _handle) = start_encoding_server("zstd", compressed).await; + + tokio::time::sleep(std::time::Duration::from_millis(50)).await; + + let client = Client::builder().prefer_http2(false).build().unwrap(); + + let resp = client + .get(url.as_str()) + .send() + .await + .expect("Request failed"); + + assert_eq!(resp.status().as_u16(), 200); + assert_eq!(resp.content_encoding(), Some("zstd")); + + let text = resp.text().expect("Failed to decode response body"); + assert_eq!( + text, TEST_BODY, + "Decompressed zstd body does not match original" + ); +} + +/// Test that identity (no compression) works correctly and returns the raw body. +#[tokio::test] +async fn test_identity_no_compression() { + let plain_body = TEST_BODY.as_bytes().to_vec(); + let (url, _handle) = start_encoding_server("identity", plain_body).await; + + tokio::time::sleep(std::time::Duration::from_millis(50)).await; + + let client = Client::builder().prefer_http2(false).build().unwrap(); + + let resp = client + .get(url.as_str()) + .send() + .await + .expect("Request failed"); + + assert_eq!(resp.status().as_u16(), 200); + assert_eq!(resp.content_encoding(), Some("identity")); + + let text = resp.text().expect("Failed to decode response body"); + assert_eq!(text, TEST_BODY, "Identity body does not match original"); +} + +/// Test that raw bytes can be accessed without decompression via bytes_raw(). +#[tokio::test] +async fn test_raw_bytes_vs_decoded() { + let compressed = gzip_compress(TEST_BODY.as_bytes()); + let compressed_len = compressed.len(); + let (url, _handle) = start_encoding_server("gzip", compressed).await; + + tokio::time::sleep(std::time::Duration::from_millis(50)).await; + + let client = Client::builder().prefer_http2(false).build().unwrap(); + + let resp = client + .get(url.as_str()) + .send() + .await + .expect("Request failed"); + + // Raw bytes should be the compressed form. + let raw = resp.bytes_raw(); + assert_eq!( + raw.len(), + compressed_len, + "Raw bytes length should match compressed size" + ); + + // Decoded bytes should be the original text. + let decoded = resp.bytes().expect("Decode failed"); + assert_eq!(decoded.as_ref(), TEST_BODY.as_bytes()); + + // They should differ (compressed != uncompressed). + assert_ne!( + raw.as_ref(), + decoded.as_ref(), + "Raw and decoded bytes should differ for compressed responses" + ); +} diff --git a/tests/concurrency.rs b/tests/concurrency.rs deleted file mode 100644 index 71b24c42..00000000 --- a/tests/concurrency.rs +++ /dev/null @@ -1,83 +0,0 @@ -use specter::Client; -use std::time::Instant; - -#[tokio::test] -async fn test_h2_multiplexing_performance() { - // Initialize tracing - let _ = tracing_subscriber::fmt() - .with_env_filter("specter=debug") - .try_init(); - - let client = Client::builder().prefer_http2(true).build().unwrap(); - - // Use reliable target - let url = "https://www.google.com/"; - - // Pre-warm connection to ensure we test multiplexing, not connection establishment - tracing::info!("Pre-warming connection..."); - let pre_warm_start = Instant::now(); - let _ = client - .get("https://www.google.com/robots.txt") - .header("User-Agent", "specter-test/0.1") - .send() - .await - .expect("Pre-warm failed"); - tracing::info!("Pre-warm complete in {:?}", pre_warm_start.elapsed()); - - let start = Instant::now(); - let mut tasks = Vec::new(); - - // Launch all requests concurrently - for i in 0..2 { - let request_start = Instant::now(); - let client_clone = client.clone(); - let url_clone = url.to_string(); - tasks.push(tokio::spawn(async move { - let req_start = Instant::now(); - let result = client_clone - .get(&url_clone) - .header("User-Agent", "specter-test/0.1") - .send() - .await; - let req_duration = req_start.elapsed(); - tracing::debug!( - "Request {} completed in {:?} (launched {:?} after start)", - i + 1, - req_duration, - request_start.duration_since(start) - ); - result - })); - } - - // Wait for all requests to complete - let mut completion_times = Vec::new(); - for (i, task) in tasks.into_iter().enumerate() { - let task_start = Instant::now(); - let res = task.await.unwrap(); - let task_wait = task_start.elapsed(); - let resp = res.unwrap_or_else(|_| panic!("Request {} failed", i + 1)); - if resp.status != 200 { - tracing::warn!( - "Request {} failed with status {}. Body: {:?}", - i + 1, - resp.status, - resp.text() - ); - } - assert_eq!(resp.status, 200); - completion_times.push((i + 1, task_wait)); - } - - let elapsed = start.elapsed(); - - tracing::info!("Total elapsed time: {:?}", elapsed); - tracing::info!("Individual request completion times:"); - for (req_num, duration) in completion_times { - tracing::info!(" Request {}: {:?}", req_num, duration); - } - - // Just ensure they all passed - // We rely on logs to verify multiplexing - assert!(elapsed.as_secs() < 30); -} diff --git a/tests/error_handling.rs b/tests/error_handling.rs new file mode 100644 index 00000000..ea077a28 --- /dev/null +++ b/tests/error_handling.rs @@ -0,0 +1,256 @@ +//! Error handling tests for the specter HTTP client. +//! +//! Tests client behavior under various failure conditions: +//! - Connection refused +//! - DNS resolution failure +//! - Read timeout (server accepts but never responds) +//! - Connection reset during body read +//! - TLS handshake failure + +use specter::Client; +use std::time::Duration; +use tokio::io::AsyncWriteExt; +use tokio::net::TcpListener; + +mod helpers; + +/// Connecting to a port with no listener should produce a connection error. +#[tokio::test] +async fn test_connection_refused() { + // Bind a listener to get a port, then drop it immediately so nothing is listening. + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + drop(listener); + + let client = Client::builder().prefer_http2(false).build().unwrap(); + + let url = format!("http://127.0.0.1:{}/test", port); + let result = client.get(url.as_str()).send().await; + + assert!(result.is_err(), "Expected connection refused error"); + let err = result.unwrap_err(); + let err_msg = format!("{}", err); + // The error should indicate a connection or IO failure. + assert!( + err_msg.contains("Connection") || err_msg.contains("IO") || err_msg.contains("refused"), + "Expected connection-related error, got: {}", + err_msg + ); +} + +/// Connecting to an invalid/unresolvable hostname should produce a DNS or connection error. +#[tokio::test] +async fn test_dns_failure() { + let client = Client::builder() + .prefer_http2(false) + .connect_timeout(Duration::from_secs(2)) + .build() + .unwrap(); + + let url = "http://this-host-does-not-exist-xyzzy-12345.invalid/test"; + let result = client.get(url).send().await; + + assert!(result.is_err(), "Expected DNS resolution error"); + let err = result.unwrap_err(); + let err_msg = format!("{}", err); + // DNS failures typically surface as IO or Connection errors. + assert!( + err_msg.contains("IO") + || err_msg.contains("Connection") + || err_msg.contains("dns") + || err_msg.contains("resolve") + || err_msg.contains("No address") + || err_msg.contains("not known") + || err_msg.contains("nodename nor servname"), + "Expected DNS-related error, got: {}", + err_msg + ); +} + +/// A server that accepts but never sends any data should trigger a TTFB timeout. +/// Uses a short real timeout (200ms) since the server never responds. +#[tokio::test] +async fn test_read_timeout_ttfb() { + // Start a server that accepts connections but never responds. + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + + tokio::spawn(async move { + loop { + let (stream, _) = listener.accept().await.unwrap(); + // Hold the connection open but never write anything. + tokio::spawn(async move { + let _held = stream; + tokio::time::sleep(Duration::from_secs(3600)).await; + }); + } + }); + + let client = Client::builder() + .prefer_http2(false) + .ttfb_timeout(Duration::from_millis(200)) + .total_timeout(Duration::from_millis(500)) + .build() + .unwrap(); + + let url = format!("http://127.0.0.1:{}/test", port); + let result = client.get(url.as_str()).send().await; + + assert!(result.is_err(), "Expected timeout error"); + let err_msg = format!("{}", result.unwrap_err()); + assert!( + err_msg.contains("timeout") || err_msg.contains("Timeout") || err_msg.contains("timed out"), + "Expected timeout-related error, got: {}", + err_msg + ); +} + +/// A server that sends a partial HTTP response (headers only, no body) and then +/// closes the connection should produce an error when the client reads the body. +#[tokio::test] +async fn test_connection_reset_partial_response() { + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + + tokio::spawn(async move { + let (mut stream, _) = listener.accept().await.unwrap(); + + // Read the request (just drain it). + let mut buf = [0u8; 4096]; + let _ = tokio::io::AsyncReadExt::read(&mut stream, &mut buf).await; + + // Send partial HTTP response: headers claim 1000 bytes but we send only a few + // then abruptly close. + let partial = + b"HTTP/1.1 200 OK\r\nContent-Length: 1000\r\nConnection: close\r\n\r\nPartial"; + let _ = stream.write_all(partial).await; + let _ = stream.flush().await; + + // Close the connection (simulates reset/truncation). + drop(stream); + }); + + // Small delay so server is ready. + tokio::time::sleep(Duration::from_millis(50)).await; + + let client = Client::builder().prefer_http2(false).build().unwrap(); + + let url = format!("http://127.0.0.1:{}/test", port); + let result = client.get(url.as_str()).send().await; + + // The client might succeed in getting a response but with truncated body, + // or it might fail during read. Either way, the body should not be 1000 bytes. + match result { + Ok(resp) => { + // If we got a response, the body should be shorter than Content-Length claimed. + let body = resp.body(); + assert!( + body.len() < 1000, + "Expected truncated body (got {} bytes)", + body.len() + ); + } + Err(e) => { + // Connection reset error is also acceptable. + let err_msg = format!("{}", e); + assert!( + err_msg.contains("IO") + || err_msg.contains("Connection") + || err_msg.contains("reset") + || err_msg.contains("closed") + || err_msg.contains("incomplete") + || err_msg.contains("unexpected eof") + || err_msg.contains("protocol"), + "Expected connection/IO error, got: {}", + err_msg + ); + } + } +} + +/// Connecting with HTTPS to a plain TCP (non-TLS) server should fail with a TLS error. +#[tokio::test] +async fn test_tls_handshake_failure() { + // Start a plain TCP server (no TLS). + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + + tokio::spawn(async move { + loop { + match listener.accept().await { + Ok((mut stream, _)) => { + // Send garbage that is not a valid TLS ServerHello. + let _ = stream.write_all(b"This is not TLS").await; + drop(stream); + } + Err(_) => break, + } + } + }); + + tokio::time::sleep(Duration::from_millis(50)).await; + + // Use a client that does NOT skip TLS verification for localhost. + let client = Client::builder() + .localhost_allows_invalid_certs(false) + .connect_timeout(Duration::from_secs(5)) + .build() + .unwrap(); + + let url = format!("https://127.0.0.1:{}/test", port); + let result = client.get(url.as_str()).send().await; + + assert!(result.is_err(), "Expected TLS handshake error"); + let err_msg = format!("{}", result.unwrap_err()); + // TLS failures can appear as TLS, IO, or Connection errors. + assert!( + err_msg.contains("TLS") + || err_msg.contains("tls") + || err_msg.contains("SSL") + || err_msg.contains("ssl") + || err_msg.contains("handshake") + || err_msg.contains("IO") + || err_msg.contains("Connection"), + "Expected TLS-related error, got: {}", + err_msg + ); +} + +/// When both connect and TTFB timeouts are set, the TTFB timeout fires for +/// a server that accepts connections but never sends headers. +/// This validates that granular timeouts compose correctly. +#[tokio::test] +async fn test_combined_timeouts() { + // Server that accepts but never responds. + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + + tokio::spawn(async move { + loop { + let (stream, _) = listener.accept().await.unwrap(); + tokio::spawn(async move { + let _held = stream; + tokio::time::sleep(Duration::from_secs(3600)).await; + }); + } + }); + + // Set connect timeout generous (should succeed), TTFB tight (should fire). + let client = Client::builder() + .prefer_http2(false) + .connect_timeout(Duration::from_secs(5)) + .ttfb_timeout(Duration::from_millis(200)) + .build() + .unwrap(); + + let url = format!("http://127.0.0.1:{}/test", port); + let result = client.get(url.as_str()).send().await; + + assert!(result.is_err(), "Expected TTFB timeout error"); + let err_msg = format!("{}", result.unwrap_err()); + assert!( + err_msg.contains("timeout") || err_msg.contains("Timeout") || err_msg.contains("TTFB"), + "Expected timeout-related error, got: {}", + err_msg + ); +} diff --git a/tests/fingerprint_integration.rs b/tests/fingerprint_integration.rs index 52f04d2c..78d2f844 100644 --- a/tests/fingerprint_integration.rs +++ b/tests/fingerprint_integration.rs @@ -84,7 +84,7 @@ async fn test_http2_fingerprint_matches_chrome() { .await .expect("HTTP/2 request should succeed"); - assert_eq!(response.status, 200, "Should get 200 OK"); + assert_eq!(response.status().as_u16(), 200, "Should get 200 OK"); // Parse response JSON let body = String::from_utf8_lossy(response.body()); @@ -248,7 +248,8 @@ async fn test_browserleaks_passes() { .expect("browserleaks.com should accept our fingerprint"); assert_eq!( - response.status, 200, + response.status().as_u16(), + 200, "browserleaks.com should return 200 OK" ); @@ -284,17 +285,18 @@ async fn test_http3_fingerprint_works() { "GET", vec![ ( - "user-agent", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user-agent".to_string(), + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" + .to_string(), ), - ("accept", "*/*"), + ("accept".to_string(), "*/*".to_string()), ], None, ) .await .expect("HTTP/3 request should succeed"); - assert_eq!(response.status, 200); + assert_eq!(response.status().as_u16(), 200); assert_eq!(response.http_version(), "HTTP/3"); // Verify trace shows http/3 @@ -408,7 +410,7 @@ async fn test_firefox_http2_fingerprint_matches() { .await .expect("HTTP/2 request should succeed"); - assert_eq!(response.status, 200, "Should get 200 OK"); + assert_eq!(response.status().as_u16(), 200, "Should get 200 OK"); // Parse response JSON let body = String::from_utf8_lossy(response.body()); @@ -544,7 +546,8 @@ async fn test_firefox_browserleaks_passes() { .expect("browserleaks.com should accept Firefox fingerprint"); assert_eq!( - response.status, 200, + response.status().as_u16(), + 200, "browserleaks.com should return 200 OK" ); @@ -595,7 +598,7 @@ async fn test_priority_frames_in_akamai() { .await .expect("HTTP/2 request should succeed"); - assert_eq!(response.status, 200); + assert_eq!(response.status().as_u16(), 200); // Parse response JSON let body = String::from_utf8_lossy(response.body()); diff --git a/tests/h1_pooling.rs b/tests/h1_pooling.rs index 313d368d..c8b1523d 100644 --- a/tests/h1_pooling.rs +++ b/tests/h1_pooling.rs @@ -17,13 +17,21 @@ async fn test_h1_connection_reuse() { let client = Client::builder().prefer_http2(false).build().unwrap(); // Request 1 - let resp1 = client.get(&url).send().await.expect("Request 1 failed"); - assert_eq!(resp1.status, 200); + let resp1 = client + .get(url.as_str()) + .send() + .await + .expect("Request 1 failed"); + assert_eq!(resp1.status().as_u16(), 200); assert_eq!(resp1.text().unwrap(), "Hello"); // Request 2 - should reuse the same connection - let resp2 = client.get(&url).send().await.expect("Request 2 failed"); - assert_eq!(resp2.status, 200); + let resp2 = client + .get(url.as_str()) + .send() + .await + .expect("Request 2 failed"); + assert_eq!(resp2.status().as_u16(), 200); assert_eq!(resp2.text().unwrap(), "Hello"); } @@ -39,8 +47,12 @@ async fn test_h1_connection_expiration() { let client = Client::builder().prefer_http2(false).build().unwrap(); // Request 1 - let resp1 = client.get(&url).send().await.expect("Request 1 failed"); - assert_eq!(resp1.status, 200); + let resp1 = client + .get(url.as_str()) + .send() + .await + .expect("Request 1 failed"); + assert_eq!(resp1.status().as_u16(), 200); // Wait longer than connection pool idle timeout (30s default) // For testing, we'll just verify the connection pool works @@ -48,8 +60,12 @@ async fn test_h1_connection_expiration() { tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; // Request 2 - should still work (connection may or may not be reused depending on timing) - let resp2 = client.get(&url).send().await.expect("Request 2 failed"); - assert_eq!(resp2.status, 200); + let resp2 = client + .get(url.as_str()) + .send() + .await + .expect("Request 2 failed"); + assert_eq!(resp2.status().as_u16(), 200); } #[tokio::test] @@ -66,11 +82,11 @@ async fn test_h1_multiple_sequential_requests() { // Make 5 sequential requests for i in 0..5 { let resp = client - .get(&url) + .get(url.as_str()) .send() .await .unwrap_or_else(|_| panic!("Request {} failed", i + 1)); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.text().unwrap(), "Hello"); } } diff --git a/tests/h1_rfc_compliance.rs b/tests/h1_rfc_compliance.rs index a7bca72d..0fb45a0c 100644 --- a/tests/h1_rfc_compliance.rs +++ b/tests/h1_rfc_compliance.rs @@ -28,9 +28,9 @@ async fn test_http11_basic_request() { tokio::time::sleep(Duration::from_millis(100)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.body().as_ref(), b"Hello"); } @@ -46,8 +46,8 @@ async fn test_http11_connection_reuse() { // Multiple requests should reuse the connection for _ in 0..3 { - let resp = client.get(&url).send().await.unwrap(); - assert_eq!(resp.status, 200); + let resp = client.get(url.as_str()).send().await.unwrap(); + assert_eq!(resp.status().as_u16(), 200); } } @@ -77,9 +77,9 @@ async fn test_204_no_content_has_no_body() { tokio::time::sleep(Duration::from_millis(100)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 204); + assert_eq!(resp.status().as_u16(), 204); // Body should be empty even though Content-Length says 100 assert!(resp.body().is_empty()); @@ -105,9 +105,9 @@ async fn test_304_not_modified_has_no_body() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 304); + assert_eq!(resp.status().as_u16(), 304); assert!(resp.body().is_empty()); let _ = server_task.await; @@ -131,9 +131,9 @@ async fn test_chunked_transfer_encoding() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.body().as_ref(), b"hello"); let _ = server_task.await; @@ -159,9 +159,9 @@ async fn test_chunked_case_insensitive() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.body().as_ref(), b"hello"); let _ = server_task.await; @@ -187,9 +187,9 @@ async fn test_transfer_encoding_overrides_content_length() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); // Should use chunked encoding, not Content-Length assert_eq!(resp.body().as_ref(), b"hello"); @@ -215,9 +215,9 @@ async fn test_chunked_with_trailers() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.body().as_ref(), b"hello"); let _ = server_task.await; @@ -241,9 +241,9 @@ async fn test_chunked_multiple_chunks() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.body().as_ref(), b"hello world"); let _ = server_task.await; @@ -268,9 +268,9 @@ async fn test_content_length_exact() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.body().as_ref(), b"hello world"); let _ = server_task.await; @@ -294,9 +294,9 @@ async fn test_content_length_zero() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert!(resp.body().is_empty()); let _ = server_task.await; @@ -322,10 +322,10 @@ async fn test_1xx_responses_skipped() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); // Should skip 100 Continue and return 200 - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.body().as_ref(), b"hello"); let _ = server_task.await; @@ -352,9 +352,9 @@ async fn test_close_delimited_body() { tokio::time::sleep(Duration::from_millis(50)).await; let client = Client::builder().prefer_http2(false).build().unwrap(); - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.body().as_ref(), b"This body is close-delimited"); let _ = server_task.await; diff --git a/tests/h2_flow_control.rs b/tests/h2_flow_control.rs index c292505c..5819b0ed 100644 --- a/tests/h2_flow_control.rs +++ b/tests/h2_flow_control.rs @@ -143,7 +143,12 @@ async fn test_large_upload_flow_control() { .http2_prior_knowledge(true) .build() .unwrap(); - let res = client.post(&url).body(body_clone).send().await.unwrap(); + let res = client + .post(url.as_str()) + .body(body_clone) + .send() + .await + .unwrap(); assert!(res.is_success()); } diff --git a/tests/h2_malformed.rs b/tests/h2_malformed.rs index 79534de6..0c1ce67c 100644 --- a/tests/h2_malformed.rs +++ b/tests/h2_malformed.rs @@ -84,7 +84,7 @@ async fn test_oversized_frame() { tokio::time::sleep(Duration::from_millis(100)).await; let client = Client::builder().prefer_http2(true).build().unwrap(); - let result = timeout(Duration::from_secs(2), client.get(&url).send()).await; + let result = timeout(Duration::from_secs(2), client.get(url.as_str()).send()).await; // Request will likely fail or timeout due to protocol error // We're just verifying the client doesn't panic @@ -145,7 +145,7 @@ async fn test_zero_length_headers_frame() { tokio::time::sleep(Duration::from_millis(100)).await; let client = Client::builder().prefer_http2(true).build().unwrap(); - let result = timeout(Duration::from_secs(2), client.get(&url).send()).await; + let result = timeout(Duration::from_secs(2), client.get(url.as_str()).send()).await; // Request should fail if let Ok(Ok(_)) = result { diff --git a/tests/h2_multiplexing.rs b/tests/h2_multiplexing.rs new file mode 100644 index 00000000..0995aa0a --- /dev/null +++ b/tests/h2_multiplexing.rs @@ -0,0 +1,300 @@ +//! HTTP/2 Multiplexing Validation Tests +//! +//! Tests that the specter client properly multiplexes concurrent requests +//! over a single HTTP/2 connection using the mock H2 server infrastructure. + +use specter::Client; +use std::collections::HashSet; +use std::sync::Arc; +use std::time::Duration; +use tokio::sync::Mutex; +use tokio::time::timeout; + +mod helpers; +use helpers::mock_h2_server::{MockH2Connection, MockH2Server}; +use helpers::tls::generate_cert_bundle; + +/// Perform the H2 handshake (preface + SETTINGS exchange) and return the first +/// HEADERS frame's stream ID. Also records all observed stream IDs. +async fn h2_handshake_and_serve( + conn: &MockH2Connection, + observed_stream_ids: Arc>>, +) { + // Read client preface. + if let Err(e) = conn.read_preface().await { + tracing::error!("Preface error: {}", e); + return; + } + + // Process frames: handle SETTINGS, respond to HEADERS frames. + // We will serve multiple requests on this single connection. + let mut settings_sent = false; + + loop { + let frame = match timeout(Duration::from_secs(3), conn.read_frame()).await { + Ok(Ok(frame)) => frame, + Ok(Err(_)) => break, // Connection closed. + Err(_) => break, // Timeout -- no more frames. + }; + + let (_len, frame_type, flags, stream_id, _payload) = frame; + + match frame_type { + 0x04 => { + // SETTINGS + if flags & 0x01 == 0 && !settings_sent { + // Client SETTINGS -- reply with our SETTINGS + ACK. + conn.send_settings(&[ + (0x01, 4096), // HEADER_TABLE_SIZE + (0x03, 100), // MAX_CONCURRENT_STREAMS + (0x04, 65535), // INITIAL_WINDOW_SIZE + ]) + .await + .unwrap(); + conn.send_settings_ack().await.unwrap(); + settings_sent = true; + } + // else: ACK from client, ignore. + } + 0x01 => { + // HEADERS -- a new request on this stream. + let mut ids = observed_stream_ids.lock().await; + ids.push(stream_id); + + // Send a minimal response: :status 200 + small body. + let response_headers = vec![0x88]; // :status 200 (HPACK indexed) + conn.send_headers(stream_id, &response_headers, false, true) + .await + .unwrap(); + + // Include the stream ID in the response body so the client can verify. + let body = format!("stream-{}", stream_id); + conn.send_data(stream_id, body.as_bytes(), true) + .await + .unwrap(); + } + 0x08 => { + // WINDOW_UPDATE -- ignore. + } + _ => { + // Ignore other frame types. + } + } + } +} + +/// Verify that multiple concurrent requests to the same H2 server are multiplexed +/// onto a single connection with unique, odd-numbered stream IDs. +#[tokio::test] +async fn test_h2_parallel_requests_multiplex() { + let _ = tracing_subscriber::fmt() + .with_env_filter("debug") + .try_init(); + + // TLS setup with h2 ALPN. + let (mut builder, ca_cert) = generate_cert_bundle(); + builder.set_alpn_select_callback(|_, client_protos| { + boring::ssl::select_next_proto(b"\x02h2", client_protos) + .ok_or(boring::ssl::AlpnError::NOACK) + }); + let acceptor = builder.build(); + + let server = MockH2Server::new().await.unwrap(); + let url = server.url_tls(); + let observed_ids: Arc>> = Arc::new(Mutex::new(Vec::new())); + let ids_clone = observed_ids.clone(); + + server.start_tls(acceptor, move |conn: MockH2Connection| { + let ids = ids_clone.clone(); + async move { + h2_handshake_and_serve(&conn, ids).await; + } + }); + + // Build client that prefers H2 and trusts our self-signed cert. + let client = Client::builder() + .add_root_certificate(ca_cert) + .prefer_http2(true) + .build() + .unwrap(); + + // Send 3 sequential requests (H2 connection pooling means they share the connection). + let mut responses = Vec::new(); + for i in 0..3 { + let req_url = format!("{}/request-{}", url, i); + let result = timeout(Duration::from_secs(5), client.get(req_url.as_str()).send()).await; + assert!(result.is_ok(), "Request {} timed out", i); + let resp = result.unwrap(); + assert!(resp.is_ok(), "Request {} failed: {:?}", i, resp.err()); + responses.push(resp.unwrap()); + } + + // Verify all responses succeeded. + for (i, resp) in responses.iter().enumerate() { + assert_eq!( + resp.status().as_u16(), + 200, + "Request {} returned non-200 status", + i + ); + assert_eq!( + resp.http_version(), + "HTTP/2", + "Request {} did not use HTTP/2", + i + ); + } + + // Verify stream IDs are unique and odd (client-initiated streams must be odd per RFC 9113). + let ids = observed_ids.lock().await; + assert!( + !ids.is_empty(), + "No stream IDs were observed by the mock server" + ); + let unique_ids: HashSet = ids.iter().copied().collect(); + assert_eq!( + unique_ids.len(), + ids.len(), + "Stream IDs should be unique. Observed: {:?}", + *ids + ); + for &id in ids.iter() { + assert!( + id % 2 == 1, + "Client-initiated stream ID must be odd, got: {}", + id + ); + } +} + +/// Verify that stream IDs are properly assigned in ascending order. +#[tokio::test] +async fn test_h2_stream_ids_ascending() { + let _ = tracing_subscriber::fmt() + .with_env_filter("debug") + .try_init(); + + let (mut builder, ca_cert) = generate_cert_bundle(); + builder.set_alpn_select_callback(|_, client_protos| { + boring::ssl::select_next_proto(b"\x02h2", client_protos) + .ok_or(boring::ssl::AlpnError::NOACK) + }); + let acceptor = builder.build(); + + let server = MockH2Server::new().await.unwrap(); + let url = server.url_tls(); + let observed_ids: Arc>> = Arc::new(Mutex::new(Vec::new())); + let ids_clone = observed_ids.clone(); + + server.start_tls(acceptor, move |conn: MockH2Connection| { + let ids = ids_clone.clone(); + async move { + h2_handshake_and_serve(&conn, ids).await; + } + }); + + let client = Client::builder() + .add_root_certificate(ca_cert) + .prefer_http2(true) + .build() + .unwrap(); + + // Send 5 sequential requests on the same pooled H2 connection. + for i in 0..5 { + let req_url = format!("{}/req-{}", url, i); + let result = timeout(Duration::from_secs(5), client.get(req_url.as_str()).send()).await; + assert!(result.is_ok(), "Request {} timed out", i); + let resp = result.unwrap(); + assert!(resp.is_ok(), "Request {} failed: {:?}", i, resp.err()); + } + + let ids = observed_ids.lock().await; + assert!( + ids.len() >= 2, + "Expected at least 2 stream IDs, got {}", + ids.len() + ); + + // Stream IDs should be strictly ascending. + for window in ids.windows(2) { + assert!( + window[1] > window[0], + "Stream IDs should be ascending: {} should be > {}", + window[1], + window[0] + ); + } + + // First client-initiated stream should be 1. + assert_eq!(ids[0], 1, "First client stream ID should be 1"); +} + +/// Verify that each response body correctly corresponds to its stream. +/// This confirms the multiplexer does not mix up response data across streams. +#[tokio::test] +async fn test_h2_response_body_per_stream() { + let _ = tracing_subscriber::fmt() + .with_env_filter("debug") + .try_init(); + + let (mut builder, ca_cert) = generate_cert_bundle(); + builder.set_alpn_select_callback(|_, client_protos| { + boring::ssl::select_next_proto(b"\x02h2", client_protos) + .ok_or(boring::ssl::AlpnError::NOACK) + }); + let acceptor = builder.build(); + + let server = MockH2Server::new().await.unwrap(); + let url = server.url_tls(); + let observed_ids: Arc>> = Arc::new(Mutex::new(Vec::new())); + let ids_clone = observed_ids.clone(); + + server.start_tls(acceptor, move |conn: MockH2Connection| { + let ids = ids_clone.clone(); + async move { + h2_handshake_and_serve(&conn, ids).await; + } + }); + + let client = Client::builder() + .add_root_certificate(ca_cert) + .prefer_http2(true) + .build() + .unwrap(); + + // Send 3 requests and collect bodies. + let mut bodies = Vec::new(); + for i in 0..3 { + let req_url = format!("{}/item-{}", url, i); + let resp = timeout(Duration::from_secs(5), client.get(req_url.as_str()).send()) + .await + .expect("Request timed out") + .expect("Request failed"); + + bodies.push(resp.text().unwrap()); + } + + // Each body should contain "stream-N" where N is the stream ID. + // The important thing is that all bodies are distinct (no mixing). + let unique_bodies: HashSet<&String> = bodies.iter().collect(); + assert_eq!( + unique_bodies.len(), + bodies.len(), + "Response bodies should be distinct across streams. Got: {:?}", + bodies + ); + + // Each body should match the pattern "stream-". + for body in &bodies { + assert!( + body.starts_with("stream-"), + "Expected body starting with 'stream-', got: {}", + body + ); + let id_str = body.strip_prefix("stream-").unwrap(); + let id: u32 = id_str + .parse() + .unwrap_or_else(|_| panic!("Expected numeric stream ID, got: {}", id_str)); + assert!(id % 2 == 1, "Stream ID in body should be odd, got: {}", id); + } +} diff --git a/tests/h2_push_promise.rs b/tests/h2_push_promise.rs index dc776fe3..cfa1c758 100644 --- a/tests/h2_push_promise.rs +++ b/tests/h2_push_promise.rs @@ -137,7 +137,7 @@ async fn test_push_promise_when_disabled() { .http2_prior_knowledge(true) .build() .unwrap(); - let result = timeout(Duration::from_secs(2), client.get(&url).send()).await; + let result = timeout(Duration::from_secs(2), client.get(url.as_str()).send()).await; assert!(result.is_ok(), "Request timed out"); let response = result.unwrap(); diff --git a/tests/h2_state_machine.rs b/tests/h2_state_machine.rs index ddf355fb..da4d84ac 100644 --- a/tests/h2_state_machine.rs +++ b/tests/h2_state_machine.rs @@ -113,7 +113,7 @@ async fn test_data_on_closed_stream() { .build() .unwrap(); - let result = timeout(Duration::from_secs(2), client.get(&url).send()).await; + let result = timeout(Duration::from_secs(2), client.get(url.as_str()).send()).await; // Request should succeed (we got a valid response before the violation) assert!(result.is_ok(), "Request timed out"); @@ -166,7 +166,7 @@ async fn test_server_initiated_stream_even_id() { .http2_prior_knowledge(true) .build() .unwrap(); - let result = timeout(Duration::from_secs(2), client.get(&url).send()).await; + let result = timeout(Duration::from_secs(2), client.get(url.as_str()).send()).await; assert!(result.is_ok()); assert!(result.unwrap().is_ok()); diff --git a/tests/helpers/mock_h3_server.rs b/tests/helpers/mock_h3_server.rs index f1238def..b8ab328e 100644 --- a/tests/helpers/mock_h3_server.rs +++ b/tests/helpers/mock_h3_server.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use quiche::ConnectionId; use std::collections::HashMap; use std::net::SocketAddr; diff --git a/tests/integration.rs b/tests/integration.rs deleted file mode 100644 index c64e19fe..00000000 --- a/tests/integration.rs +++ /dev/null @@ -1,36 +0,0 @@ -use specter::Client; - -/// Test mixed protocol scenarios -#[tokio::test] -#[ignore] -async fn test_mixed_protocols() { - let _client = Client::builder() - .prefer_http2(false) // Prefer H1, but server may negotiate H2 - .build() - .unwrap(); - - // Test that protocol selection works correctly - // TODO: Implement with mock servers for both protocols - tracing::info!("Mixed protocol test - requires mock servers"); -} - -/// Test connection failure handling -#[tokio::test] -#[ignore] -async fn test_connection_failure() { - // Test that pool cleanup works when connection fails - // TODO: Implement with server that closes connections - tracing::info!("Connection failure test - requires failure simulation"); -} - -/// Test concurrent clients don't interfere -#[tokio::test] -#[ignore] -async fn test_concurrent_clients() { - let _client1 = Client::builder().prefer_http2(true).build().unwrap(); - let _client2 = Client::builder().prefer_http2(true).build().unwrap(); - - // Verify clients have separate connection pools - // TODO: Add instrumentation to verify pool isolation - tracing::info!("Concurrent clients test - requires pool instrumentation"); -} diff --git a/tests/rfc3986_uri.rs b/tests/rfc3986_uri.rs deleted file mode 100644 index e8f71d79..00000000 --- a/tests/rfc3986_uri.rs +++ /dev/null @@ -1,50 +0,0 @@ -//! RFC 3986 URI Compliance Tests -//! -//! https://www.rfc-editor.org/rfc/rfc3986 - -use http::Uri; - -// Helper to access private methods if needed? -// Client::get_origin is private. -// But we can test public behavior or `Uri` parsing directly if Specter exposes a wrapper. -// Specter uses `http::Uri`. -// Maybe we can test `ClientBuilder` or `RequestBuilder` URL handling? -// `RequestBuilder` parse uri. - -#[test] -fn test_uri_normalization_rfc3986_section_6() { - // RFC 3986 Section 6.2.2.1: Case Normalization - // Scheme and host should be case-insensitive. - let uri: Uri = "HTTP://EXAMPLE.COM/".parse().unwrap(); - // Verify case-insensitive match (specter handles normalization internally) - assert_eq!(uri.host().unwrap().to_lowercase(), "example.com"); - - // Note: http::Uri preserves case in host(), so direct comparison would fail. - // assert_eq!(uri.host(), Some("example.com")); // Fails -} - -#[test] -fn test_path_removal_dot_segments_rfc3986_section_5_2_4() { - // "a/b/c/./../../g" -> "a/g" - // `http` crate does NOT normalize paths by default. - // Does Specter normalize before sending? - // Client doesn't seem to normalize. - // If we rely on standard crates, we assume valid URI handling. - // Compliance check: does Specter prevent sending invalid URIs? -} - -// Since Specter uses `http::Uri`, extensive URI testing tests the `http` crate, not Specter. -// But we can test `specter::cookie::normalize_domain` logic (which implements part of normalization). - -use specter::cookie::Cookie; - -#[test] -fn test_cookie_domain_normalization() { - // Lowercase - let c = Cookie::new("name", "val", "EXAMPLE.COM"); - assert_eq!(c.domain, "example.com"); - - // Trailing dot removal - let c = Cookie::new("name", "val", "example.com."); - assert_eq!(c.domain, "example.com"); -} diff --git a/tests/rfc6265_cookies.rs b/tests/rfc6265_cookies.rs index 7aad0ec2..3e88b4ba 100644 --- a/tests/rfc6265_cookies.rs +++ b/tests/rfc6265_cookies.rs @@ -4,6 +4,18 @@ use chrono::{TimeZone, Utc}; use specter::cookie::{Cookie, CookieJar, SameSite}; +use specter::Headers; + +#[test] +fn test_cookie_domain_normalization() { + // Lowercase + let c = Cookie::new("name", "val", "EXAMPLE.COM"); + assert_eq!(c.domain, "example.com"); + + // Trailing dot removal + let c = Cookie::new("name", "val", "example.com."); + assert_eq!(c.domain, "example.com"); +} #[test] fn test_secure_flag_enforcement_rfc6265_section_5_4() { @@ -180,13 +192,11 @@ fn test_cookie_jar_rfc6265_section_5_4() { let mut jar = CookieJar::new(); let url = "http://example.com/foo"; - jar.store_from_headers( - &[ - "Set-Cookie: SID=123; Path=/foo".to_string(), - "Set-Cookie: SID=456; Path=/".to_string(), - ], - url, - ); + let headers = Headers::from(vec![ + ("Set-Cookie".to_string(), "SID=123; Path=/foo".to_string()), + ("Set-Cookie".to_string(), "SID=456; Path=/".to_string()), + ]); + jar.store_from_headers(&headers, url); // Should retrieve most specific path first (RFC 5.4.2) assert!( diff --git a/tests/rfc9110_semantics.rs b/tests/rfc9110_semantics.rs index 3d15521c..71418180 100644 --- a/tests/rfc9110_semantics.rs +++ b/tests/rfc9110_semantics.rs @@ -102,7 +102,7 @@ async fn test_redirect_response_301() { .await .expect("Request failed"); - assert_eq!(response.status, 301); + assert_eq!(response.status().as_u16(), 301); assert_eq!(response.get_header("location").unwrap(), "/target"); } @@ -132,7 +132,7 @@ async fn test_content_negotiation_accept_header() { .await .expect("Request failed"); - assert_eq!(response.status, 200); + assert_eq!(response.status().as_u16(), 200); assert_eq!( response.get_header("content-type").unwrap(), "application/json" @@ -165,5 +165,5 @@ async fn test_conditional_request_if_none_match() { .await .expect("Request failed"); - assert_eq!(response.status, 304); // Not Modified + assert_eq!(response.status().as_u16(), 304); // Not Modified } diff --git a/tests/rfc9111_caching.rs b/tests/rfc9111_caching.rs index d90383a0..c4b6350c 100644 --- a/tests/rfc9111_caching.rs +++ b/tests/rfc9111_caching.rs @@ -6,6 +6,7 @@ use bytes::Bytes; use http::Method; use specter::cache::{CacheStatus, HttpCache}; use specter::response::Response; +use specter::Headers; #[test] fn test_cache_no_store_rfc9111_section_5_2_2_3() { @@ -14,7 +15,7 @@ fn test_cache_no_store_rfc9111_section_5_2_2_3() { let response = Response::new( 200, - vec!["Cache-Control: no-store".to_string()], + Headers::from(vec![("Cache-Control".to_string(), "no-store".to_string())]), Bytes::from("secret"), "HTTP/1.1".to_string(), ); @@ -36,7 +37,10 @@ fn test_cache_hit_rfc9111() { let response = Response::new( 200, - vec!["Cache-Control: max-age=3600".to_string()], + Headers::from(vec![( + "Cache-Control".to_string(), + "max-age=3600".to_string(), + )]), Bytes::from("data"), "HTTP/1.1".to_string(), ); @@ -58,10 +62,10 @@ fn test_cache_revalidation_etag() { // Stored response with ETag let response = Response::new( 200, - vec![ - "Cache-Control: max-age=1".to_string(), // Expire quickly - "ETag: \"12345\"".to_string(), - ], + Headers::from(vec![ + ("Cache-Control".to_string(), "max-age=1".to_string()), // Expire quickly + ("ETag".to_string(), "\"12345\"".to_string()), + ]), Bytes::from("data"), "HTTP/1.1".to_string(), ); diff --git a/tests/rfc9112_http1.rs b/tests/rfc9112_http1.rs index 297ef198..e2acc0ec 100644 --- a/tests/rfc9112_http1.rs +++ b/tests/rfc9112_http1.rs @@ -71,7 +71,7 @@ async fn test_request_framing_content_length() { .unwrap(); // Response status is a public field u16 - assert_eq!(response.status, 200); + assert_eq!(response.status().as_u16(), 200); } #[tokio::test] @@ -102,7 +102,7 @@ async fn test_request_framing_chunked() { .await .unwrap(); - assert_eq!(response.status, 200); + assert_eq!(response.status().as_u16(), 200); // Verify body content assert_eq!(&response.body()[..], b"Hello"); } diff --git a/tests/rfc9114_http3.rs b/tests/rfc9114_http3.rs deleted file mode 100644 index 3f932f39..00000000 --- a/tests/rfc9114_http3.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! RFC 9114 HTTP/3 Compliance Tests -//! -//! https://www.rfc-editor.org/rfc/rfc9114 - -use specter::fingerprint::tls::TlsFingerprint; -use specter::transport::h3::H3Client; - -#[test] -fn test_h3_client_configuration_rfc9114() { - // RFC 9114 Section 3.1: ALPN - // Clients MUST include "h3" in ALPN. - // Our H3Client should configure quiche with this. - - let profile = TlsFingerprint::chrome_142(); - let _client = H3Client::with_fingerprint(profile); - - // Internal verification of config isn't easily exposed without inspection. - // But we can verify it initializes without error. - // And we can check functionality if we had a mock server. - - // For now, we verify the struct construction succeeds. - // The client is created successfully if we reach here without panicking. -} - -// Additional tests for Alt-Svc parsing (RFC 7838) which is crucial for H3 discovery. - -#[test] -fn test_altsvc_parsing_rfc7838() { - // h3=":443"; ma=2592000 - let _header = "h3=\":443\"; ma=2592000"; - // Assuming AltSvcEntry has a parse method or similar logic in AltSvcCache. - // Checking AltSvcCache outline: parse_and_store. - // Checking internal parse logic if exposed? - // It's likely internal. - // Compliance check: Integration test (mock response with Alt-Svc). - // In lieu of mock, we assume AltSvcCache tests cover this (if they exist). -} diff --git a/tests/tls_mock_server.rs b/tests/tls_mock_server.rs index cf3c7d65..22858899 100644 --- a/tests/tls_mock_server.rs +++ b/tests/tls_mock_server.rs @@ -34,9 +34,9 @@ async fn test_h1_tls() { .unwrap(); // Send request - let resp = client.get(&url).send().await.unwrap(); + let resp = client.get(url.as_str()).send().await.unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.http_version(), "HTTP/1.1"); let body = resp.text().unwrap(); assert!(body.contains("Hello")); @@ -110,12 +110,12 @@ async fn test_h2_tls() { .unwrap(); // Send request (ensure we use https) - let result = timeout(Duration::from_secs(2), client.get(&url).send()).await; + let result = timeout(Duration::from_secs(2), client.get(url.as_str()).send()).await; assert!(result.is_ok(), "Request timed out"); let resp = result.unwrap().unwrap(); - assert_eq!(resp.status, 200); + assert_eq!(resp.status().as_u16(), 200); assert_eq!(resp.http_version(), "HTTP/2"); assert_eq!(resp.text().unwrap(), "Hello"); }