Skip to content

Commit

Permalink
add blowfish cipher
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitrystu committed Jul 15, 2019
1 parent 9ec754c commit 5d9af6a
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 3 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ FWSTARTUP ?= mcu/stm32l0xx.S
LDPARAMS ?= ROMLEN=64K RAMLEN=8K

#sources
CRYPT_SRC = src/arc4.c src/chacha.c src/gost.c src/raiden.c src/rc5.c src/speck.c src/xtea.c
CRYPT_SRC = src/arc4.c src/chacha.c src/gost.c src/raiden.c src/rc5.c src/speck.c
CRYPT_SRC += src/xtea.c src/blowfish.c
FW_SRC = $(CRYPT_SRC) $(FWSTARTUP) src/descriptors.c src/bootloader.c src/rc5a.S src/chacha_a.S
SW_SRC = $(CRYPT_SRC) src/encrypter.c

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
+ RAIDEN block cipher in CBC mode
+ SPECK 64/128 block cipher in CBC mode
+ XTEA (classic and XTEA-1) block cipher in CBC mode
+ BLOWFISH block cipher in CBC mode
+ Different interfaces for flash and eeprom programming
+ Autoseal using RDP level 1 or 2 (prevents reading decrypted FW trough debug interface).
Be careful when you set RDP to level 2. This operation is irreversible and disables
Expand Down
5 changes: 3 additions & 2 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
#define DFU_CIPHER_SPECK 17 /* SPECK 64/128 block cipher in CBC mode */
#define DFU_CIPHER_XTEA 18 /* XTEA block cipher in CBC mode */
#define DFU_CIPHER_XTEA1 19 /* XTEA-1 block cipher in CBC mode */

#define DFU_CIPHER_BLOWFISH 20 /* Blowfish block cipher in CBC mode */
#define DFU_CIPHER_RTEA 21 /* Ruptor's TEA or Repaired TEA in CBC mode */

/* CONFIG STARTS HERE */
/* Skip unwanted dfuDNLOAD_SYNC phase. Slightly improve speed, but don't meets DFU1.1 state diagram */
Expand Down Expand Up @@ -83,7 +84,7 @@
/* User application size. _AUTO or required size in bytes. */
#define DFU_APP_SIZE _AUTO
/* Cipher to use. set _DISABLE or choose from implemented ciphers */
#define DFU_CIPHER DFU_CIPHER_GOST
#define DFU_CIPHER DFU_CIPHER_BLOWFISH
/** DFU secure key. */
#define DFU_AES_KEY_A 0x2D, 0x4D, 0x61, 0x6B, 0x65, 0x4C, 0x6F, 0x76, \
0x65, 0x4E, 0x6F, 0x74, 0x57, 0x61, 0x72, 0x2D
Expand Down
32 changes: 32 additions & 0 deletions inc/blowfish.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* This file is the part of the STM32 secure bootloader
*
* Copyright ©2017 Dmitry Filimonchuk <dmitrystu[at]gmail[dot]com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef _BLOWFISH_H_
#define _BLOWFISH_H_
#if defined(__cplusplus)
extern "C" {
#endif

#define CRYPTO_BLKSIZE 8
#define CRYPTO_NAME "BLOWFISH 64/16/256-CBC"

void blowfish_init(void);
void blowfish_encrypt(uint32_t *out, const uint32_t *in, int32_t bytes);
void blowfish_decrypt(uint32_t *out, const uint32_t *in, int32_t bytes);

#if defined(__cplusplus)
}
#endif
#endif // _BLOWFISH_H_
6 changes: 6 additions & 0 deletions inc/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@
#define aes_encrypt(out, in, b) chacha_crypt(out, in, b)
#define aes_decrypt(out, in, b) chacha_crypt(out, in, b)

#elif (DFU_CIPHER == DFU_CIPHER_BLOWFISH)
#include "blowfish.h"
#define aes_init(key) blowfish_init()
#define aes_encrypt(out, in, b) blowfish_encrypt(out, in, b)
#define aes_decrypt(out, in, b) blowfish_decrypt(out, in, b)

#else
#undef DFU_USE_CIPHER
#define CRYPTO_BLKSIZE 1
Expand Down
148 changes: 148 additions & 0 deletions src/blowfish.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/* This file is the part of the STM32 secure bootloader
*
* Blowfish cypher implementation based on
* https://www.schneier.com/academic/archives/1994/09/description_of_a_new.html
*
* Xorshift implementation based on Xorshift RNGs by George Marsaglia
* https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
*
* Copyright ©2017 Dmitry Filimonchuk <dmitrystu[at]gmail[dot]com>
* *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <stdint.h>
#include "misc.h"
#include "config.h"
#include "blowfish.h"

#define rounds 16

static const union {
uint32_t key32[8];
uint8_t key8[32];
} key = {.key8 = {DFU_AES_KEY_A, DFU_AES_KEY_B}};

static struct {
uint32_t P[18];
uint32_t S[4][256];
} D;

static uint32_t CK[2];

static uint32_t F(uint32_t x) {
uint32_t h = D.S[0][x >> 24] + D.S[1][(x >> 16) & 0xFF];
return (h ^ D.S[2][(x >> 8) & 0xFF]) + D.S[3][x & 0xFF];
}

static void encrypt(uint32_t *A, uint32_t *B){
uint32_t L = *A;
uint32_t R = *B;
for (int i = 0; i < rounds; i+=2) {
L ^= D.P[i];
R ^= F(L);
R ^= D.P[i+1];
L ^= F(R);
}
L ^= D.P[16];
R ^= D.P[17];
*A = R;
*B = L;
}

static void decrypt(uint32_t *A, uint32_t *B) {
uint32_t L = *A;
uint32_t R = *B;
for (int i = rounds; i > 0; i-=2) {
L ^= D.P[i+1];
R ^= F(L);
R ^= D.P[i];
L ^= F(R);
}
L ^= D.P[1];
R ^= D.P[0];
*A = R;
*B = L;
}

void blowfish_init(void) {
uint32_t L = 0;
uint32_t R = 0;
/* Original implementation is based on PI digits, but
* "There is nothing sacred about pi; any string of random bits--digits
* of e, RAND tables, output of a random number generator--will suffice.
* B. Schneier"
* So, we will use pseudo random numbers fom xorshift
*/
uint32_t S = 0xDEADBEEF;
uint32_t *K = (uint32_t*)&D;
for (int i = 0; i < sizeof(D) / 4; i++) {
S ^= S << 13;
S ^= S >> 17;
S ^= S << 5;
K[i] = S;
}

for (int i = 0; i < 18; i++) {
D.P[i] ^= key.key32[i & 0x07];
}

for (int i = 0; i < 18; i+=2) {
encrypt(&L, &R);
D.P[i] = L;
D.P[i+1] = R;
}
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 256; j+=2) {
encrypt(&L, &R);
D.S[i][j] = L;
D.S[i][j+1] = R;
}
}
CK[0] = DFU_AES_NONCE0;
CK[1] = DFU_AES_NONCE1;
}


static void blowfish_encrypt_block(uint32_t *out, const uint32_t *in) {
uint32_t A = in[0] ^ CK[0];
uint32_t B = in[1] ^ CK[1];
encrypt(&A, &B);
out[0] = CK[0] = A;
out[1] = CK[1] = B;
}

static void blowfish_decrypt_block(uint32_t *out, const uint32_t *in) {
uint32_t A = in[0];
uint32_t B = in[1];
decrypt(&A, &B);
A ^= CK[0]; CK[0] = in[0]; out[0] = A;
B ^= CK[1]; CK[1] = in[1]; out[1] = B;
}


void blowfish_encrypt(uint32_t *out, const uint32_t *in, int32_t bytes) {
while(bytes > 0) {
blowfish_encrypt_block(out, in);
in += 2;
out += 2;
bytes -= 0x08;
}
}

void blowfish_decrypt(uint32_t *out, const uint32_t *in, int32_t bytes) {
while(bytes > 0) {
blowfish_decrypt_block(out, in);
in += 2;
out += 2;
bytes -= 0x08;
}
}

0 comments on commit 5d9af6a

Please sign in to comment.