Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions BBMTLib/Dockerfile.fips
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# syntax=docker/dockerfile:1
# Dockerfile.fips - BoldWallet FIPS-aware gomobile build (UBI 9 + Android SDK/NDK + Go 1.25)

FROM registry.access.redhat.com/ubi9/ubi:9.4 AS builder

LABEL maintainer="BoldWallet Team" \
description="FIPS-aware gomobile build env for TSS lib (Android/iOS bindings)" \
fips="policy-enabled" \
base="ubi9"

# Install dependencies
RUN dnf install -y --setopt=install_weak_deps=False --nodocs \
gcc gcc-c++ make git wget tar unzip which \
java-17-openjdk-devel \
bzip2 bzip2-devel zlib-devel libffi-devel xz-devel \
glibc-devel glibc-headers libstdc++-devel \
crypto-policies openssl openssl-devel \
&& dnf clean all \
&& rm -rf /var/cache/dnf/*

# Enable FIPS crypto policy
RUN update-crypto-policies --set FIPS && \
grep -q '^FIPS$' /etc/crypto-policies/config || { echo "FIPS policy failed"; exit 1; }

# Install Go 1.25 (amd64 for gomobile compatibility)
ARG GO_VERSION=1.25.0
RUN wget -O go.tar.gz "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" && \
tar -C /usr/local -xzf go.tar.gz && \
rm go.tar.gz

ENV PATH="/usr/local/go/bin:/go/bin:${PATH}" \
GOPATH="/go" \
GOCACHE="/go/.cache" \
GO111MODULE=on \
CGO_ENABLED=1 \
GODEBUG=fips140=on \
CGO_CFLAGS="-O2 -g -Wall -Wno-unused-variable -Wno-error=unused-variable -Wno-unused-but-set-variable -Wno-error=unused-but-set-variable"

# Android SDK/NDK
ENV ANDROID_HOME=/opt/android-sdk \
ANDROID_SDK_ROOT=/opt/android-sdk \
PATH="${PATH}:/opt/android-sdk/cmdline-tools/latest/bin:/opt/android-sdk/platform-tools"

RUN mkdir -p ${ANDROID_HOME}/cmdline-tools && \
wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdline.zip && \
unzip -q cmdline.zip -d ${ANDROID_HOME}/cmdline-tools && \
mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest && \
rm cmdline.zip && \
yes | sdkmanager --licenses >/dev/null 2>&1 && \
sdkmanager --update && \
sdkmanager \
"platform-tools" \
"platforms;android-34" \
"build-tools;34.0.0" \
"ndk;27.1.12297006" && \
ln -sfn ${ANDROID_HOME}/ndk/27.1.12297006 ${ANDROID_HOME}/ndk/latest

ENV ANDROID_NDK_HOME="${ANDROID_HOME}/ndk/27.1.12297006"

# Install gomobile + gobind (pinned)
RUN go install golang.org/x/mobile/cmd/gomobile@v0.0.0-20250408133729-978277e7eaf7 && \
go install golang.org/x/mobile/cmd/gobind@v0.0.0-20250408133729-978277e7eaf7

# Init gomobile
RUN gomobile init

WORKDIR /workspace
# This stage has no CMD – we use it only for docker cp / export
22 changes: 22 additions & 0 deletions BBMTLib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,28 @@ gomobile bind -v -target=android -androidapi 21 github.com/BoldBitcoinWallet/BBM
cp tss.aar ../android/app/libs/tss.aar
```

## FIPS 140-3 (SP 800-90A DRBG) (NIST) compliance

The library can be built with the Go Cryptographic Module so that key generation and signing use FIPS 140-3 approved algorithms. The top-level `build.sh` and the Docker build enable this by default.


**Randomness Behavior:**

- **Without FIPS:**
- Only one source of entropy is used
- `crypto/rand.Reader` uses **only the operating system’s RNG** via `crypto/internal/sysrand`.
- No DRBG is used; output is directly from the OS.

- **With FIPS enabled:**
- Two different sources of entropy are mixed together
- `crypto/rand.Reader` is backed by an **SP 800-90A DRBG** (`crypto/internal/fips140/drbg`), seeded from a dedicated FIPS entropy source.
- On every read, **128 bits of OS randomness** are mixed in as additional input, strengthening the output per FIPS requirements.

- **Build with FIPS (default):** `GOFIPS140=v1.0.0` is set in `build.sh`; the resulting binary runs in FIPS mode by default. No runtime env is required.
- **Build without FIPS:** run `GOFIPS140=off ./build.sh` (or set `GOFIPS140=off` before `gomobile bind`).
- **Docker:** pass `--build-arg GOFIPS140=off` to disable FIPS in the image.

Requires Go 1.24+. See [Go FIPS 140-3](https://go.dev/doc/security/fips140).

## License
This project is licensed under the **Apache-2.0 License**. See [LICENSE](LICENSE) for details.
Expand Down
180 changes: 145 additions & 35 deletions BBMTLib/build.sh
Original file line number Diff line number Diff line change
@@ -1,47 +1,157 @@
#!/bin/bash

# Check for --clear-cache flag
CLEAR_CACHE=false
for arg in "$@"; do
if [ "$arg" = "--clear-cache" ]; then
CLEAR_CACHE=true
break
fi
done
#!/usr/bin/env bash
set -euo pipefail

echo "building gomobile tss lib"
go mod tidy
# --- Configuration & Helpers ---

# Clear module cache if --clear-cache flag is provided
if [ "$CLEAR_CACHE" = true ]; then
echo "Clearing module cache to force fresh download..."
go clean -modcache
# Text formatting
BOLD="\033[1m"
RESET="\033[0m"
GREEN="\033[32m"
YELLOW="\033[33m"

info() { echo -e "${BOLD}${GREEN}==>${RESET} ${BOLD}$1${RESET}"; }
warn() { echo -e "${BOLD}${YELLOW}Warning:${RESET} $1"; }

info "Starting BoldWallet TSS gomobile build (FIPS-aware, Go 1.25+)"

# --- 1. Environment Checks ---

echo "Go environment:"
go version
go env | grep -E 'GOOS|GOARCH|CGO_ENABLED|GODEBUG|GOEXPERIMENT|GOPATH|PATH'

# FIPS Policy Check (Linux specific)
if [[ "$(uname)" == "Linux" ]] && [[ -f "/etc/crypto-policies/config" ]]; then
info "FIPS policy check (system level):"
if grep -q '^FIPS$' /etc/crypto-policies/config 2>/dev/null; then
echo "FIPS crypto policy active"
else
echo "No FIPS system policy active"
fi
fi

# Force download of all dependencies
echo "Downloading all dependencies..."
# Reliable FIPS check (Cross-platform temp file)
info "Checking native FIPS 140-3 mode..."

# Portable mktemp approach: create in current dir to avoid /tmp permission/path issues on different OSs
TMP_GO_FILE="./fips_check_$(date +%s).go"

cat > "$TMP_GO_FILE" <<'EOF'
package main
import (
"crypto/fips140"
"fmt"
"os"
)
func main() {
if fips140.Enabled() {
fmt.Fprint(os.Stdout, "enabled")
} else {
fmt.Fprint(os.Stdout, "disabled")
}
}
EOF

# Run check, defaulting to disabled if run fails (e.g. if crypto/fips140 doesn't exist in older Go)
FIPS_ENABLED=$(go run "$TMP_GO_FILE" 2>/dev/null || echo "disabled/unavailable")
rm -f "$TMP_GO_FILE"

echo "Native FIPS mode: ${FIPS_ENABLED}"

# --- 2. Toolchain Setup ---

info "Preparing modules..."
go mod tidy
go mod download
go mod verify

# Install gomobile if not already installed
# Ensure GOPATH/bin is in PATH
export PATH="$PATH:$(go env GOPATH)/bin"

# Install gomobile/gobind if missing
if ! command -v gomobile &> /dev/null; then
echo "gomobile not found, installing..."
warn "gomobile not found. Installing..."
go install golang.org/x/mobile/cmd/gomobile@latest
# Add Go bin directory to PATH if not already there
export PATH="$PATH:$(go env GOPATH)/bin"
fi

gomobile init
if ! command -v gobind &> /dev/null; then
warn "gobind not found. Installing..."
go install golang.org/x/mobile/cmd/gobind@latest
fi

# Initialize gomobile (Safe to run repeatedly, but we try standard init first)
info "Initializing gomobile..."
gomobile init || { warn "Init failed – retrying with verbose output"; gomobile init -v; }

# Verify gobind works
gobind -h >/dev/null 2>&1 || { echo "Error: gobind not functional"; exit 1; }

# Optional cache clear
if [[ "${1:-}" == "--clear-cache" ]]; then
warn "Clearing cache as requested..."
go clean -modcache
go mod download
fi

# --- 3. Build: Android ---

info "Building for Android..."

# Check requirements for Android
if [[ -z "${ANDROID_HOME:-}" ]]; then
warn "ANDROID_HOME is not set. Android build might fail if SDK is missing."
fi

# Set flag for Go modules
export GOFLAGS="-mod=mod"
gomobile bind -v -target=android -androidapi 21 github.com/BoldBitcoinWallet/BBMTLib/tss
cp tss.aar ../android/app/libs/tss.aar
cp tss-sources.jar ../android/app/libs/tss-sources.jar

gomobile bind -v -target=ios,iossimulator,macos github.com/BoldBitcoinWallet/BBMTLib/tss
# Remove old framework first (cp -r fails with symlinks when destination exists)
rm -rf ../ios/Tss.xcframework
cp -R ./Tss.xcframework ../ios/

# Run go mod tidy again at the end to ensure go.mod/go.sum are up to date
# This ensures any dependencies added during the build are included
echo "Updating go.mod/go.sum..."

# Run Bind
# Note: -androidapi 21 is the standard min version
gomobile bind -v -target=android -androidapi 21 -o tss.aar github.com/BoldBitcoinWallet/BBMTLib/tss

# Copy Artifacts
if [[ -d "../android/app/libs" ]]; then
info "Copying Android artifacts..."
cp -v tss.aar ../android/app/libs/tss.aar || warn "Copy tss.aar failed"
echo "✓ tss.aar copied to ../android/app/libs/tss.aar"
# gomobile bind generates sources jar alongside the aar?
# Usually it produces just the .aar. If you have a custom process generating -sources.jar, keep this.
if [[ -f "tss-sources.jar" ]]; then
cp -v tss-sources.jar ../android/app/libs/tss-sources.jar || warn "Copy sources.jar failed"
echo "✓ tss-sources.jar copied to ../android/app/libs/tss-sources.jar"
fi
fi

# --- 4. Build: iOS/macOS ---

if [[ "$(uname)" == "Darwin" ]]; then
info "macOS detected → Building for iOS/Simulator/macOS"

# Ensure Xcode command line tools or Xcode is valid
if ! xcode-select -p &>/dev/null; then
echo "Error: Xcode tools not found. Cannot build for iOS."
exit 1
fi

# Build xcframework
gomobile bind -v -target=ios,iossimulator,macos -o Tss.xcframework github.com/BoldBitcoinWallet/BBMTLib/tss

# Copy Artifacts
if [[ -d "../ios" ]]; then
info "Copying iOS artifacts..."
# Clean old framework to ensure clean copy
rm -rf ../ios/Tss.xcframework 2>/dev/null || true
cp -a ./Tss.xcframework ../ios/ || warn "Copy Tss.xcframework failed"
echo "✓ Tss.xcframework copied to ../ios/Tss.xcframework"
fi
else
info "Not running on macOS → Skipping iOS/macOS targets"
fi

# --- 5. Cleanup ---

info "Finalizing..."
# Run go mod tidy again at the end to ensure go.mod/go.sum are clean
go mod tidy

info "Build complete!"
19 changes: 19 additions & 0 deletions BBMTLib/fips-android.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Dockerfile.fips
docker buildx build --platform linux/amd64 -f Dockerfile.fips -t boldwallet-builder:fips .

# Generate lib
docker run --rm \
--platform linux/amd64 \
-v "$(pwd)":/workspace \
boldwallet-builder:fips ./build.sh

# List outputs
ls -lh tss.aar tss-sources.jar 2>/dev/null || echo "No artifacts found"

# Copy Android artifacts
if [[ -d "../android/app/libs" ]]; then
cp -v tss.aar ../android/app/libs/tss.aar || echo "Warning: copy tss.aar failed"
cp -v tss-sources.jar ../android/app/libs/tss-sources.jar || echo "Warning: copy sources.jar failed"
else
echo "Skipping Android copy"
fi
6 changes: 2 additions & 4 deletions BBMTLib/go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module github.com/BoldBitcoinWallet/BBMTLib

go 1.24.1

toolchain go1.24.2
go 1.25.0

require (
github.com/bnb-chain/tss-lib/v2 v2.0.2
Expand Down Expand Up @@ -61,7 +59,7 @@ require (
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.44.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/sys v0.41.0 // indirect
google.golang.org/protobuf v1.36.2 // indirect
)

Expand Down
4 changes: 2 additions & 2 deletions BBMTLib/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
Expand Down
8 changes: 8 additions & 0 deletions BBMTLib/scripts/keygen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
set -e # Exit on error
set -o pipefail # Catch errors in pipes

# FIPS 140-3 by default (override with GOFIPS140=off or GODEBUG= to disable)
export GOFIPS140="${GOFIPS140:-v1.0.0}"
export GODEBUG="${GODEBUG:+$GODEBUG,}fips140=on"

BIN_NAME="bbmt"
BUILD_DIR="./bin"

Expand Down Expand Up @@ -92,6 +96,10 @@ case "$ADDRESS_TYPE" in
;;
esac

# Run from BBMTLib root (script may be invoked from BBMTLib or BBMTLib/scripts)
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"

# Ensure build directory exists
mkdir -p "$BUILD_DIR"

Expand Down
4 changes: 4 additions & 0 deletions BBMTLib/scripts/nostr-keygen-3party.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

set -euo pipefail

# FIPS 140-3 by default (override with GOFIPS140=off or GODEBUG= to disable)
export GOFIPS140="${GOFIPS140:-v1.0.0}"
export GODEBUG="${GODEBUG:+$GODEBUG,}fips140=on"

ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"

Expand Down
4 changes: 4 additions & 0 deletions BBMTLib/scripts/nostr-keygen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

set -euo pipefail

# FIPS 140-3 by default (override with GOFIPS140=off or GODEBUG= to disable)
export GOFIPS140="${GOFIPS140:-v1.0.0}"
export GODEBUG="${GODEBUG:+$GODEBUG,}fips140=on"

ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"

Expand Down
Loading
Loading