Files
BBeOS/packaging/security/secure-boot.c
Eliott 7b53cde2ae
Some checks failed
CI / markdown-lint (push) Failing after 14s
Complete BBeOS project implementation with BlackBerry-inspired website
- Updated .gitignore with comprehensive exclusions for build artifacts, IDE files, and OS-specific files
- Created BlackBerry-inspired website with Heroicons and Gitea integration
- Added complete project structure with all 7 phases implemented
- Included kernel drivers, UI components, telephony stack, and packaging tools
- Added emulation scripts for testing and development
- Comprehensive documentation for all development phases
- Security analysis and hardware testing guides
- SDK and application framework for third-party development
2025-08-01 10:20:28 +02:00

537 lines
16 KiB
C

/*
* BBeOS Secure Boot Implementation
* BlackBerry Classic Q20 Secure Boot Chain
*
* This module implements secure boot functionality including
* signature verification, boot chain validation, and key management.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <time.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#define BBEOS_SECURE_BOOT_VERSION "1.0.0"
#define BBEOS_KEY_SIZE 2048
#define BBEOS_SIGNATURE_SIZE 256
#define BBEOS_HASH_SIZE 32
/* Boot chain stages */
enum boot_stage {
BOOT_STAGE_PBL, /* Primary Boot Loader */
BOOT_STAGE_SBL, /* Secondary Boot Loader */
BOOT_STAGE_ABOOT, /* Android Boot Loader */
BOOT_STAGE_KERNEL, /* Linux Kernel */
BOOT_STAGE_INITRAMFS, /* Initial RAM Filesystem */
BOOT_STAGE_ROOTFS /* Root Filesystem */
};
/* Signature structure */
struct bbeos_signature {
char magic[8]; /* "BBEOSSIG" */
u32 version; /* Signature version */
u32 algorithm; /* Signature algorithm */
u32 key_id; /* Key identifier */
u32 data_size; /* Size of signed data */
u32 signature_size; /* Size of signature */
u64 timestamp; /* Signature timestamp */
char reserved[64]; /* Reserved for future use */
u8 signature[BBEOS_SIGNATURE_SIZE]; /* Digital signature */
} __attribute__((packed));
/* Key structure */
struct bbeos_key {
char magic[8]; /* "BBEOSKEY" */
u32 version; /* Key version */
u32 key_id; /* Key identifier */
u32 key_type; /* Key type (RSA, ECC, etc.) */
u32 key_size; /* Key size in bits */
u64 creation_time; /* Key creation timestamp */
u64 expiry_time; /* Key expiry timestamp */
char key_name[64]; /* Key name/description */
char reserved[64]; /* Reserved for future use */
u8 public_key[BBEOS_KEY_SIZE / 8]; /* Public key data */
} __attribute__((packed));
/* Boot verification structure */
struct bbeos_boot_verify {
char magic[8]; /* "BBEOSVER" */
u32 version; /* Verification version */
u32 stage_count; /* Number of boot stages */
u64 verification_time; /* Verification timestamp */
u32 result; /* Verification result */
char reserved[64]; /* Reserved for future use */
struct {
u32 stage; /* Boot stage */
u32 status; /* Verification status */
u32 signature_valid; /* Signature validity */
u32 hash_valid; /* Hash validity */
char stage_name[32]; /* Stage name */
} stages[6]; /* Boot stage verification results */
} __attribute__((packed));
/* Key management */
static RSA *load_public_key(const char *key_path) {
FILE *key_file;
RSA *rsa_key;
key_file = fopen(key_path, "r");
if (!key_file) {
fprintf(stderr, "Error: Cannot open key file %s: %s\n", key_path, strerror(errno));
return NULL;
}
rsa_key = PEM_read_RSA_PUBKEY(key_file, NULL, NULL, NULL);
fclose(key_file);
if (!rsa_key) {
fprintf(stderr, "Error: Invalid RSA public key in %s\n", key_path);
return NULL;
}
return rsa_key;
}
static int verify_signature(const char *data_path, const char *signature_path, const char *key_path) {
FILE *data_file, *sig_file;
struct bbeos_signature sig_header;
unsigned char data_hash[BBEOS_HASH_SIZE];
unsigned char signature[BBEOS_SIGNATURE_SIZE];
RSA *rsa_key;
int result = 0;
/* Load public key */
rsa_key = load_public_key(key_path);
if (!rsa_key) {
return -1;
}
/* Read signature file */
sig_file = fopen(signature_path, "rb");
if (!sig_file) {
fprintf(stderr, "Error: Cannot open signature file %s\n", signature_path);
RSA_free(rsa_key);
return -1;
}
/* Read signature header */
if (fread(&sig_header, sizeof(sig_header), 1, sig_file) != 1) {
fprintf(stderr, "Error: Cannot read signature header\n");
fclose(sig_file);
RSA_free(rsa_key);
return -1;
}
/* Verify signature magic */
if (strncmp(sig_header.magic, "BBEOSSIG", 8) != 0) {
fprintf(stderr, "Error: Invalid signature magic\n");
fclose(sig_file);
RSA_free(rsa_key);
return -1;
}
/* Read signature data */
if (fread(signature, sig_header.signature_size, 1, sig_file) != 1) {
fprintf(stderr, "Error: Cannot read signature data\n");
fclose(sig_file);
RSA_free(rsa_key);
return -1;
}
fclose(sig_file);
/* Calculate data hash */
data_file = fopen(data_path, "rb");
if (!data_file) {
fprintf(stderr, "Error: Cannot open data file %s\n", data_path);
RSA_free(rsa_key);
return -1;
}
SHA256_CTX sha256_ctx;
SHA256_Init(&sha256_ctx);
char buffer[4096];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), data_file)) > 0) {
SHA256_Update(&sha256_ctx, buffer, bytes_read);
}
SHA256_Final(data_hash, &sha256_ctx);
fclose(data_file);
/* Verify signature */
result = RSA_verify(NID_sha256, data_hash, BBEOS_HASH_SIZE,
signature, sig_header.signature_size, rsa_key);
RSA_free(rsa_key);
if (result == 1) {
printf("Signature verification successful for %s\n", data_path);
return 0;
} else {
fprintf(stderr, "Signature verification failed for %s\n", data_path);
return -1;
}
}
/* Create signature */
static int create_signature(const char *data_path, const char *signature_path,
const char *private_key_path, u32 key_id) {
FILE *data_file, *sig_file;
struct bbeos_signature sig_header;
unsigned char data_hash[BBEOS_HASH_SIZE];
unsigned char signature[BBEOS_SIGNATURE_SIZE];
unsigned int sig_len;
EVP_PKEY *pkey;
EVP_PKEY_CTX *ctx;
int result = 0;
/* Load private key */
FILE *key_file = fopen(private_key_path, "r");
if (!key_file) {
fprintf(stderr, "Error: Cannot open private key file %s\n", private_key_path);
return -1;
}
pkey = PEM_read_PrivateKey(key_file, NULL, NULL, NULL);
fclose(key_file);
if (!pkey) {
fprintf(stderr, "Error: Invalid private key in %s\n", private_key_path);
return -1;
}
/* Calculate data hash */
data_file = fopen(data_path, "rb");
if (!data_file) {
fprintf(stderr, "Error: Cannot open data file %s\n", data_path);
EVP_PKEY_free(pkey);
return -1;
}
SHA256_CTX sha256_ctx;
SHA256_Init(&sha256_ctx);
char buffer[4096];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), data_file)) > 0) {
SHA256_Update(&sha256_ctx, buffer, bytes_read);
}
SHA256_Final(data_hash, &sha256_ctx);
fclose(data_file);
/* Create signature */
ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!ctx) {
fprintf(stderr, "Error: Cannot create signature context\n");
EVP_PKEY_free(pkey);
return -1;
}
if (EVP_PKEY_sign_init(ctx) <= 0) {
fprintf(stderr, "Error: Cannot initialize signature\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return -1;
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
fprintf(stderr, "Error: Cannot set RSA padding\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return -1;
}
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) {
fprintf(stderr, "Error: Cannot set signature digest\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return -1;
}
sig_len = sizeof(signature);
if (EVP_PKEY_sign(ctx, signature, &sig_len, data_hash, BBEOS_HASH_SIZE) <= 0) {
fprintf(stderr, "Error: Cannot create signature\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return -1;
}
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
/* Create signature file */
sig_file = fopen(signature_path, "wb");
if (!sig_file) {
fprintf(stderr, "Error: Cannot create signature file %s\n", signature_path);
return -1;
}
/* Initialize signature header */
memset(&sig_header, 0, sizeof(sig_header));
strcpy(sig_header.magic, "BBEOSSIG");
sig_header.version = 0x010000;
sig_header.algorithm = 0x01; /* RSA-SHA256 */
sig_header.key_id = key_id;
sig_header.data_size = 0; /* Will be calculated */
sig_header.signature_size = sig_len;
sig_header.timestamp = time(NULL);
/* Calculate data size */
struct stat st;
if (stat(data_path, &st) == 0) {
sig_header.data_size = st.st_size;
}
/* Write signature header */
fwrite(&sig_header, sizeof(sig_header), 1, sig_file);
/* Write signature data */
fwrite(signature, sig_len, 1, sig_file);
fclose(sig_file);
printf("Signature created successfully for %s\n", data_path);
return 0;
}
/* Boot chain verification */
static int verify_boot_chain(const char *boot_dir) {
struct bbeos_boot_verify verify_info;
const char *boot_stages[] = {
"pbl.bin", "sbl.bin", "aboot.img", "zImage", "initramfs.img", "rootfs.img"
};
const char *stage_names[] = {
"PBL", "SBL", "ABOOT", "Kernel", "Initramfs", "Rootfs"
};
int result = 0;
printf("Verifying BBeOS boot chain...\n");
/* Initialize verification structure */
memset(&verify_info, 0, sizeof(verify_info));
strcpy(verify_info.magic, "BBEOSVER");
verify_info.version = 0x010000;
verify_info.stage_count = sizeof(boot_stages) / sizeof(boot_stages[0]);
verify_info.verification_time = time(NULL);
verify_info.result = 1; /* Assume success */
/* Verify each boot stage */
for (int i = 0; i < verify_info.stage_count; i++) {
char data_path[256];
char sig_path[256];
char key_path[256];
snprintf(data_path, sizeof(data_path), "%s/%s", boot_dir, boot_stages[i]);
snprintf(sig_path, sizeof(sig_path), "%s/%s.sig", boot_dir, boot_stages[i]);
snprintf(key_path, sizeof(key_path), "%s/bbeos_public_key.pem", boot_dir);
/* Initialize stage info */
verify_info.stages[i].stage = i;
strncpy(verify_info.stages[i].stage_name, stage_names[i],
sizeof(verify_info.stages[i].stage_name) - 1);
/* Check if files exist */
if (access(data_path, F_OK) != 0) {
printf("Warning: Boot stage %s not found\n", boot_stages[i]);
verify_info.stages[i].status = 0;
verify_info.stages[i].signature_valid = 0;
verify_info.stages[i].hash_valid = 0;
continue;
}
if (access(sig_path, F_OK) != 0) {
printf("Warning: Signature for %s not found\n", boot_stages[i]);
verify_info.stages[i].status = 0;
verify_info.stages[i].signature_valid = 0;
verify_info.stages[i].hash_valid = 0;
verify_info.result = 0;
continue;
}
/* Verify signature */
if (verify_signature(data_path, sig_path, key_path) == 0) {
printf("✓ %s signature verified\n", stage_names[i]);
verify_info.stages[i].status = 1;
verify_info.stages[i].signature_valid = 1;
verify_info.stages[i].hash_valid = 1;
} else {
printf("✗ %s signature verification failed\n", stage_names[i]);
verify_info.stages[i].status = 0;
verify_info.stages[i].signature_valid = 0;
verify_info.stages[i].hash_valid = 0;
verify_info.result = 0;
result = -1;
}
}
/* Save verification results */
char verify_path[256];
snprintf(verify_path, sizeof(verify_path), "%s/boot_verification.bin", boot_dir);
FILE *verify_file = fopen(verify_path, "wb");
if (verify_file) {
fwrite(&verify_info, sizeof(verify_info), 1, verify_file);
fclose(verify_file);
printf("Boot verification results saved to %s\n", verify_path);
}
if (verify_info.result) {
printf("✓ BBeOS boot chain verification successful\n");
} else {
printf("✗ BBeOS boot chain verification failed\n");
}
return result;
}
/* Generate key pair */
static int generate_key_pair(const char *output_dir) {
RSA *rsa_key;
BIGNUM *e;
FILE *private_file, *public_file;
int result = 0;
printf("Generating BBeOS key pair...\n");
/* Create output directory */
char cmd[256];
snprintf(cmd, sizeof(cmd), "mkdir -p %s", output_dir);
system(cmd);
/* Generate RSA key */
e = BN_new();
if (!e) {
fprintf(stderr, "Error: Cannot create BIGNUM\n");
return -1;
}
if (BN_set_word(e, RSA_F4) != 1) {
fprintf(stderr, "Error: Cannot set RSA exponent\n");
BN_free(e);
return -1;
}
rsa_key = RSA_new();
if (!rsa_key) {
fprintf(stderr, "Error: Cannot create RSA key\n");
BN_free(e);
return -1;
}
if (RSA_generate_key_ex(rsa_key, BBEOS_KEY_SIZE, e, NULL) != 1) {
fprintf(stderr, "Error: Cannot generate RSA key\n");
RSA_free(rsa_key);
BN_free(e);
return -1;
}
BN_free(e);
/* Save private key */
char private_path[256];
snprintf(private_path, sizeof(private_path), "%s/bbeos_private_key.pem", output_dir);
private_file = fopen(private_path, "w");
if (!private_file) {
fprintf(stderr, "Error: Cannot create private key file %s\n", private_path);
RSA_free(rsa_key);
return -1;
}
if (PEM_write_RSAPrivateKey(private_file, rsa_key, NULL, NULL, 0, NULL, NULL) != 1) {
fprintf(stderr, "Error: Cannot write private key\n");
fclose(private_file);
RSA_free(rsa_key);
return -1;
}
fclose(private_file);
printf("Private key saved to %s\n", private_path);
/* Save public key */
char public_path[256];
snprintf(public_path, sizeof(public_path), "%s/bbeos_public_key.pem", output_dir);
public_file = fopen(public_path, "w");
if (!public_file) {
fprintf(stderr, "Error: Cannot create public key file %s\n", public_path);
RSA_free(rsa_key);
return -1;
}
if (PEM_write_RSA_PUBKEY(public_file, rsa_key) != 1) {
fprintf(stderr, "Error: Cannot write public key\n");
fclose(public_file);
RSA_free(rsa_key);
return -1;
}
fclose(public_file);
printf("Public key saved to %s\n", public_path);
RSA_free(rsa_key);
printf("BBeOS key pair generated successfully\n");
return 0;
}
/* Main function */
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("BBeOS Secure Boot Tool\n");
printf("======================\n");
printf("Usage:\n");
printf(" %s generate <output_dir> - Generate key pair\n", argv[0]);
printf(" %s sign <data> <sig> <key> - Sign data file\n", argv[0]);
printf(" %s verify <data> <sig> <key> - Verify signature\n", argv[0]);
printf(" %s chain <boot_dir> - Verify boot chain\n", argv[0]);
return 1;
}
if (strcmp(argv[1], "generate") == 0) {
if (argc != 3) {
fprintf(stderr, "Usage: %s generate <output_dir>\n", argv[0]);
return 1;
}
return generate_key_pair(argv[2]);
} else if (strcmp(argv[1], "sign") == 0) {
if (argc != 5) {
fprintf(stderr, "Usage: %s sign <data> <sig> <key>\n", argv[0]);
return 1;
}
return create_signature(argv[2], argv[3], argv[4], 1);
} else if (strcmp(argv[1], "verify") == 0) {
if (argc != 5) {
fprintf(stderr, "Usage: %s verify <data> <sig> <key>\n", argv[0]);
return 1;
}
return verify_signature(argv[2], argv[3], argv[4]);
} else if (strcmp(argv[1], "chain") == 0) {
if (argc != 3) {
fprintf(stderr, "Usage: %s chain <boot_dir>\n", argv[0]);
return 1;
}
return verify_boot_chain(argv[2]);
} else {
fprintf(stderr, "Unknown command: %s\n", argv[1]);
return 1;
}
return 0;
}