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
37 changes: 25 additions & 12 deletions py/dbb_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import hid # hidapi (requires cython)
import hashlib
import struct
import hmac


# ----------------------------------------------------------------------------------
Expand All @@ -21,6 +22,7 @@
boot_buf_size_send = 4098
boot_buf_size_reply = 256

sha256_byte_len = 32

# ----------------------------------------------------------------------------------
# Crypto
Expand All @@ -40,28 +42,33 @@ def aes_decrypt_with_iv(key, iv, data):
return s


def EncodeAES(secret, s):
def encrypt_aes(key, s):
iv = bytes(os.urandom(16))
ct = aes_encrypt_with_iv(secret, iv, s)
ct = aes_encrypt_with_iv(key, iv, s)
e = iv + ct
return base64.b64encode(e)
return e


def DecodeAES(secret, e):
e = bytes(base64.b64decode(e))
def decrypt_aes(key, e):
iv, e = e[:16], e[16:]
s = aes_decrypt_with_iv(secret, iv, e)
s = aes_decrypt_with_iv(key, iv, e)
return s


def sha256(x):
return hashlib.sha256(x).digest()

def sha512(x):
return hashlib.sha512(x).digest()

def Hash(x):
def double_hash(x):
if type(x) is not bytearray: x=x.encode('utf-8')
return sha256(sha256(x))

def derive_keys(x):
h = double_hash(x)
h = sha512(h)
return (h[:len(h)/2],h[len(h)/2:])

# ----------------------------------------------------------------------------------
# HID
Expand Down Expand Up @@ -152,16 +159,22 @@ def hid_send_plain(msg):
print('Exception caught ' + str(e))
return reply


def hid_send_encrypt(msg, password):
print("Sending: {}".format(msg))
reply = ""
try:
secret = Hash(password)
msg = EncodeAES(secret, msg)
reply = hid_send_plain(msg)
encryption_key, authentication_key = derive_keys(password)
msg = encrypt_aes(encryption_key, msg)
hmac_digest = hmac.new(authentication_key, msg, digestmod=hashlib.sha256).digest()
authenticated_msg = base64.b64encode(msg + hmac_digest)
reply = hid_send_plain(authenticated_msg)
if 'ciphertext' in reply:
reply = DecodeAES(secret, ''.join(reply["ciphertext"]))
b64_unencoded = bytes(base64.b64decode(''.join(reply["ciphertext"])))
reply_hmac = b64_unencoded[-sha256_byte_len:]
hmac_calculated = hmac.new(authentication_key, b64_unencoded[:-sha256_byte_len], digestmod=hashlib.sha256).digest()
if not hmac.compare_digest(reply_hmac, hmac_calculated):
raise Exception("Failed to validate HMAC")
reply = decrypt_aes(encryption_key, b64_unencoded[:-sha256_byte_len])
print("Reply: {}\n".format(reply))
reply = json.loads(reply)
if 'error' in reply:
Expand Down
2 changes: 1 addition & 1 deletion py/load_firmware.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def printFirmwareHash(filename):
break
data = data + bytearray(d)
data = data + b'\xFF' * (applen - len(data))
print('\nHashed firmware', binascii.hexlify(Hash((data))))
print('\nHashed firmware', binascii.hexlify(double_hash((data))))


# ----------------------------------------------------------------------------------
Expand Down
34 changes: 32 additions & 2 deletions src/cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ static uint8_t *cipher_aes_encrypt(const unsigned char *in, int inlen,
return enc_cat;
}


// Encrypts a given constant char array of length inlen using the AES algorithm with CBC mode
// and base64 encodes the result.
//
Expand Down Expand Up @@ -212,7 +211,6 @@ static char *cipher_aes_decrypt(const uint8_t *in, int inlen, int *outlen,
return dec;
}


char *cipher_aes_hmac_decrypt(const uint8_t *in, int inlen,
int *outlen, const uint8_t *key)
{
Expand Down Expand Up @@ -242,6 +240,38 @@ char *cipher_aes_hmac_decrypt(const uint8_t *in, int inlen,
return ret;
}

// Decrypts a given constant char array of length inlen using the AES algorithm with CBC mode
// and base64 decodes the result.
//
// Must free() returned value (allocated inside base64() function)
char *cipher_aes_b64_hmac_decrypt(const unsigned char *in, int inlen, int *out_msg_len,
const uint8_t *secret)
{
unsigned char *ub64;
char *decrypted;
int ub64len;

if (!in || inlen == 0 || !secret) {
return NULL;
}

// Unbase64
ub64 = unbase64((const char *)in, inlen, &ub64len);
if (!ub64) {
return NULL;
}
if ((ub64len % N_BLOCK) || ub64len < N_BLOCK) {
memset(ub64, 0, ub64len);
free(ub64);
return NULL;
}

decrypted = cipher_aes_hmac_decrypt(ub64, ub64len, out_msg_len, secret);

memset(ub64, 0, ub64len);
free(ub64);
return decrypted;
}

// Must free() returned value
char *cipher_aes_b64_decrypt(const unsigned char *in, int inlen, int *outlen,
Expand Down
3 changes: 3 additions & 0 deletions src/cipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ uint8_t *cipher_aes_hmac_encrypt(const unsigned char *in, int inlen,
char *cipher_aes_b64_encrypt(const unsigned char *in, int inlen,
int *out_b64len, const uint8_t *key);

char *cipher_aes_b64_hmac_decrypt(const unsigned char *in, int inlen, int *out_msg_len,
const uint8_t *secret);

char *cipher_aes_b64_decrypt(const unsigned char *in, int inlen,
int *outlen, const uint8_t *key);

Expand Down
20 changes: 10 additions & 10 deletions src/commander.c
Original file line number Diff line number Diff line change
Expand Up @@ -1425,9 +1425,9 @@ static void commander_parse(char *command)
}

exit:
encoded_report = cipher_aes_b64_encrypt((unsigned char *)json_report,
strlens(json_report), &encrypt_len,
memory_active_key_get());
encoded_report = cipher_aes_b64_hmac_encrypt((unsigned char *)json_report,
strlens(json_report), &encrypt_len,
memory_active_key_get());

commander_clear_report();
if (encoded_report) {
Expand All @@ -1451,11 +1451,11 @@ static uint8_t commander_find_active_key(const char *encrypted_command)
key_std = memory_report_aeskey(PASSWORD_STAND);
key_hdn = memory_report_aeskey(PASSWORD_HIDDEN);

cmd_std = cipher_aes_b64_decrypt((const unsigned char *)encrypted_command,
strlens(encrypted_command), &len_std, key_std);
cmd_std = cipher_aes_b64_hmac_decrypt((const unsigned char *)encrypted_command,
strlens(encrypted_command), &len_std, key_std);

cmd_hdn = cipher_aes_b64_decrypt((const unsigned char *)encrypted_command,
strlens(encrypted_command), &len_hdn, key_hdn);
cmd_hdn = cipher_aes_b64_hmac_decrypt((const unsigned char *)encrypted_command,
strlens(encrypted_command), &len_hdn, key_hdn);

if (strlens(cmd_std)) {
if (BRACED(cmd_std)) {
Expand Down Expand Up @@ -1499,9 +1499,9 @@ static char *commander_decrypt(const char *encrypted_command)
size_t json_object_len = 0;

if (commander_find_active_key(encrypted_command) == DBB_OK) {
command = cipher_aes_b64_decrypt((const unsigned char *)encrypted_command,
strlens(encrypted_command), &command_len,
memory_active_key_get());
command = cipher_aes_b64_hmac_decrypt((const unsigned char *)encrypted_command,
strlens(encrypted_command), &command_len,
memory_active_key_get());
}

err_count = memory_report_access_err_count();
Expand Down
9 changes: 5 additions & 4 deletions tests/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ static void api_decrypt_report(const char *report, uint8_t *key)
const char *ciphertext = YAJL_GET_STRING(yajl_tree_get(json_node, ciphertext_path,
yajl_t_string));
if (ciphertext) {
dec = cipher_aes_b64_decrypt((const unsigned char *)ciphertext, strlens(ciphertext),
&decrypt_len, key);
dec = cipher_aes_b64_hmac_decrypt((const unsigned char *)ciphertext, strlens(ciphertext),
&decrypt_len, key);
if (!dec) {
strcpy(decrypted_report, "/* error: Failed to decrypt. */");
goto exit;
Expand Down Expand Up @@ -393,8 +393,9 @@ static void api_hid_send(const char *cmd)
static void api_hid_send_encrypt(const char *cmd, uint8_t *key)
{
int enc_len;
char *enc = cipher_aes_b64_encrypt((const unsigned char *)cmd, strlens(cmd), &enc_len,
key);
char *enc = cipher_aes_b64_hmac_encrypt((const unsigned char *)cmd, strlens(cmd),
&enc_len,
key);
api_hid_send_len(enc, enc_len);
free(enc);
}
Expand Down
74 changes: 0 additions & 74 deletions tests/hmac_check.h

This file was deleted.

1 change: 0 additions & 1 deletion tests/tests_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
#include "secp256k1/include/secp256k1_recovery.h"

#include "api.h"
#include "hmac_check.h"


#define HASH_DEFAULT "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
Expand Down
1 change: 0 additions & 1 deletion tests/tests_unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
#include "uECC.h"
#include "ecc.h"
#include "aes.h"
#include "hmac_check.h"


int U_TESTS_RUN = 0;
Expand Down