Skip to content

Commit

Permalink
Use 4-way key shares for AES private keys
Browse files Browse the repository at this point in the history
The privateaes.bin key file is now 4x256bit numbers (A,B,C,D), and the AES key X is A^B^C^D
  • Loading branch information
will-v-pi committed Jan 14, 2025
1 parent a672c24 commit 4fce151
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 12 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,8 @@ The encrypted binary will have the following structure:
- Padding to ensure the encrypted length is a multiple of 4 words
- Signature metadata block

The AES key must be provided as a .bin file of the 256 bit AES key to be used for encryption.
The AES key must be provided as a .bin file containing a 4-way share of the 256 bit AES key to be used for encryption.
Eg if the 256 bit key is X, the bin file should contain the 256 bit numbers A B C D where X = A ^ B ^ C ^ D.

```text
$ picotool help encrypt
Expand Down
4 changes: 2 additions & 2 deletions bintool/bintool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runt
}


int encrypt(elf_file *elf, block *new_block, const private_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign) {
int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign) {

std::vector<uint8_t> to_enc = get_lm_hash_data(elf, new_block);

Expand Down Expand Up @@ -975,7 +975,7 @@ int encrypt(elf_file *elf, block *new_block, const private_t aes_key, const publ
}


std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const private_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign) {
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign) {
std::random_device rand{};
assert(rand.max() - rand.min() >= 256);

Expand Down
4 changes: 2 additions & 2 deletions bintool/bintool.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ std::unique_ptr<block> find_first_block(elf_file *elf);
block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block);
#if HAS_MBEDTLS
int hash_andor_sign(elf_file *elf, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram = false);
int encrypt(elf_file *elf, block *new_block, const private_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign);
int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign);
#endif

// Bins
Expand All @@ -37,6 +37,6 @@ block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::uni
uint32_t calc_checksum(std::vector<uint8_t> bin);
#if HAS_MBEDTLS
std::vector<uint8_t> hash_andor_sign(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram = false);
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const private_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign);
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign);
void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, verified_t &hash_verified, verified_t &sig_verified);
#endif
2 changes: 1 addition & 1 deletion bintool/mbedtls_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void mb_sha256_buffer(const uint8_t *data, size_t len, message_digest_t *digest_
mbedtls_sha256(data, len, digest_out->bytes, 0);
}

void mb_aes256_buffer(const uint8_t *data, size_t len, uint8_t *data_out, const private_t *key, iv_t *iv) {
void mb_aes256_buffer(const uint8_t *data, size_t len, uint8_t *data_out, const aes_key_t *key, iv_t *iv) {
mbedtls_aes_context aes;

assert(len % 16 == 0);
Expand Down
16 changes: 15 additions & 1 deletion bintool/mbedtls_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,25 @@ typedef struct iv {
uint8_t bytes[16];
} iv_t; /**< Convenience typedef */

typedef struct aes_key_share {
union {
struct {
/** A 4-way share of the 256-bit value. */
uint8_t bytes_a[32];
uint8_t bytes_b[32];
uint8_t bytes_c[32];
uint8_t bytes_d[32];
};
uint8_t bytes[128];
};
} aes_key_share_t; /**< Convenience typedef */

typedef signature_t public_t;
typedef message_digest_t private_t;
typedef message_digest_t aes_key_t;

void mb_sha256_buffer(const uint8_t *data, size_t len, message_digest_t *digest_out);
void mb_aes256_buffer(const uint8_t *data, size_t len, uint8_t *data_out, const private_t *key, iv_t *iv);
void mb_aes256_buffer(const uint8_t *data, size_t len, uint8_t *data_out, const aes_key_t *key, iv_t *iv);
void mb_sign_sha256(const uint8_t *entropy, size_t entropy_size, const message_digest_t *m, const public_t *p, const private_t *d, signature_t *out);

uint32_t mb_verify_signature_secp256k1(
Expand Down
16 changes: 11 additions & 5 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ struct encrypt_command : public cmd {
hex("offset").set(settings.offset) % "Load offset (memory address; default 0x10000000)"
).force_expand_help(true) % "BIN file options" +
named_file_selection_x("outfile", 1) % "File to save to" +
named_typed_file_selection_x("aes_key", 2, "bin") % "AES Key" +
named_typed_file_selection_x("aes_key", 2, "bin") % "AES Key Share" +
optional_typed_file_selection_x("signing_key", 3, "pem") % "Signing Key file"
);
}
Expand Down Expand Up @@ -4699,7 +4699,7 @@ bool encrypt_command::execute(device_map &devices) {
}

if (get_file_type_idx(2) != filetype::bin) {
fail(ERROR_ARGS, "Can only read AES key from BIN file");
fail(ERROR_ARGS, "Can only read AES key share from BIN file");
}

if (settings.seal.sign && settings.filenames[3].empty()) {
Expand All @@ -4712,10 +4712,16 @@ bool encrypt_command::execute(device_map &devices) {


auto aes_file = get_file_idx(ios::in|ios::binary, 2);

private_t aes_key;
aes_file->read((char*)aes_key.bytes, sizeof(aes_key.bytes));
aes_file->exceptions(std::iostream::failbit | std::iostream::badbit);

// Key is stored as a 4-way share, ie X = A ^ B ^ C ^ D
aes_key_share_t aes_key_share;
aes_file->read((char*)aes_key_share.bytes, sizeof(aes_key_share.bytes));

aes_key_t aes_key;
for (int i=0; i < sizeof(aes_key); i++) {
aes_key.bytes[i] = aes_key_share.bytes_a[i] ^ aes_key_share.bytes_b[i] ^ aes_key_share.bytes_c[i] ^ aes_key_share.bytes_d[i];
}

private_t private_key = {};
public_t public_key = {};
Expand Down

0 comments on commit 4fce151

Please sign in to comment.