freenet / freenet-core

Declare your digital independence
https://freenet.org/
Apache License 2.0
2.28k stars 79 forks source link

Implement Cross-Platform Sandboxing for Secure Data Storage in Freenet #1154

Open sanity opened 4 months ago

sanity commented 4 months ago

To ensure Freenet's delegate mechanism securely stores private data and avoids criticisms similar to those faced by Signal, we need to implement a robust sandboxing solution. This solution should be cross-platform, requiring minimal development effort, and provide consistent protection across Linux, macOS, Windows, iOS, and Android.

Background

Recently, Signal received criticism for storing chat databases in an unprotected area of the file system, making them accessible by any user process. To prevent similar vulnerabilities in Freenet, we need to adopt a sandboxing strategy that ensures private data is stored securely and inaccessible to unauthorized processes.

Requirements

  1. Cross-Platform Support: The solution should work uniformly across Linux, macOS, Windows, iOS, and Android.
  2. Minimal Development Effort: The implementation should leverage existing tools and libraries to minimize development overhead.
  3. Strong Isolation: Ensure that private data is sandboxed and inaccessible to unauthorized applications or processes.

Tasks

  1. Research Sandboxing Solutions:

    • Investigate cross-platform sandboxing tools and libraries.
    • Evaluate the feasibility and security of each solution.
  2. Select a Sandboxing Solution:

    • Choose a solution that meets the requirements for cross-platform support, minimal development effort, and strong isolation.
    • Document the rationale for the selected solution.
  3. Implement the Selected Solution:

    • Develop and integrate the sandboxing solution into the Freenet application.
    • Ensure the solution works consistently across all supported platforms.
  4. Test and Validate:

    • Conduct thorough testing to verify the sandboxing implementation.
    • Ensure private data is securely stored and inaccessible to unauthorized processes on all platforms.
  5. Document the Implementation:

    • Provide detailed documentation on the sandboxing setup and configuration.
    • Include instructions for maintaining and updating the sandboxing solution.

Additional Information

By researching and selecting an appropriate sandboxing solution, we aim to enhance the security of Freenet and provide robust protection for private data stored within the delegate mechanism. This approach will help us maintain secure and best-practice data storage across all supported platforms.

References

By following these steps, we aim to enhance the security of Freenet and provide robust protection for private data stored within the delegate mechanism.

sanity commented 4 months ago

Here is a "roll our own" solution that might solve the issue, it's inspired by how Freenet's delegates work.

Proposal: Cross-Platform Keyring Utility in Rust

Objective

Develop a cross-platform keyring utility in Rust that securely provides cryptographic keys to a process only if the process binary is digitally signed with a specified cryptographic key. This avoids the need to request user permission for key access. This tool will work out-of-the-box on Windows, macOS, Linux, Android, and iOS without requiring additional hardware.

Features

  1. Cross-Platform Compatibility: Support for Windows, macOS, Linux, Android, and iOS.
  2. Digital Signature Verification: Verify the binary signature of the requesting process before providing access to the keys.
  3. Secure Key Storage: Utilize platform-specific APIs to securely store and manage cryptographic keys.
  4. Simple API: Provide a simple Rust API for applications to request keys.

Components

  1. Keyring Library: Core Rust library for managing keys and verifying binary signatures.
  2. Platform-Specific Modules: Implementations for handling key storage and binary verification on each supported platform.
  3. Command-Line Interface (CLI): A CLI tool for managing keys and testing the keyring utility.

Design

1. Keyring Library

The core library will provide the following functionality:

Keyring API
pub struct Keyring {
    // Opaque type for the keyring
}

impl Keyring {
    /// Create a new keyring instance
    pub fn new() -> Result<Self, KeyringError>;

    /// Store a key in the keyring
    pub fn store_key(&self, key_id: &str, key: &[u8]) -> Result<(), KeyringError>;

    /// Retrieve a key from the keyring if the calling binary is verified
    pub fn retrieve_key(&self, key_id: &str) -> Result<Vec<u8>, KeyringError>;

    /// Verify the calling binary's signature
    fn verify_binary_signature(&self) -> Result<(), KeyringError>;
}

2. Platform-Specific Modules

Each platform-specific module will implement the verify_binary_signature and key management functions using the appropriate APIs.

Windows
macOS and iOS
Linux
Android

3. Command-Line Interface (CLI)

A CLI tool for developers to interact with the keyring, including storing and retrieving keys and verifying the setup.

CLI Commands
# Initialize the keyring
keyring init

# Store a key
keyring store --key-id my_key --key-file /path/to/key

# Retrieve a key
keyring retrieve --key-id my_key

Implementation Steps

  1. Setup the Rust Project: Initialize a new Rust project with a library and binary crate.
  2. Implement the Core Library:
    • Define the Keyring struct and its methods.
    • Implement platform-agnostic key management functions.
  3. Develop Platform-Specific Modules:
    • Implement Windows module using WinVerifyTrust and DPAPI.
    • Implement macOS/iOS module using codesign and Keychain.
    • Implement Linux module using openssl/gpg and libsecret.
    • Implement Android module using Keystore and attestation APIs.
  4. Create the CLI Tool:
    • Implement CLI commands for keyring management.
    • Integrate the CLI with the core library.
  5. Testing and Validation:
    • Write unit and integration tests for the core library.
    • Perform end-to-end testing on all supported platforms.

Example Code Snippet

Here is a simplified example of how the Keyring struct might look in Rust:

use std::error::Error;

pub struct Keyring;

impl Keyring {
    pub fn new() -> Result<Self, Box<dyn Error>> {
        // Platform-specific initialization
        Ok(Keyring)
    }

    pub fn store_key(&self, key_id: &str, key: &[u8]) -> Result<(), Box<dyn Error>> {
        // Platform-specific key storage implementation
        Ok(())
    }

    pub fn retrieve_key(&self, key_id: &str) -> Result<Vec<u8>, Box<dyn Error>> {
        self.verify_binary_signature()?;
        // Platform-specific key retrieval implementation
        Ok(vec![])
    }

    fn verify_binary_signature(&self) -> Result<(), Box<dyn Error>> {
        // Platform-specific binary signature verification
        Ok(())
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    let keyring = Keyring::new()?;
    keyring.store_key("my_key", b"supersecretkey")?;
    let key = keyring.retrieve_key("my_key")?;
    println!("Retrieved key: {:?}", key);
    Ok(())
}

Conclusion

This proposal outlines the design and implementation plan for a cross-platform keyring utility in Rust that ensures cryptographic keys are only accessible to processes with verified binaries. By leveraging platform-specific APIs and focusing on security and simplicity, this tool aims to provide a robust solution for secure key management across consumer operating systems.