Hamid Fadishei's Blog

July 9, 2013

iMX233 and Full-disk Encryption of Linux on SD Card

Filed under: Uncategorized — fadishei @ 2:54 pm
Tags: , , ,

After weeks of work, I finally was able to boot my iMX233 ARM processor from a fully encrypted linux partition… and most importantly, I was able to use the hardware-stored encryption key for this purpose. What a pleasure!

iMX233 features a hardware engine (known as DCP) which can perform 128-bit AES encryption using either a software-provided or the hardware-stored key. The latter key is burnt into the CPU’s OTP ROM and can be made totally hidden from software. This adds extra security: cryptography without any chance of revealling the encryption key.

To me, an ultimate disk encryption method for protecting an embedded application is one whose boot procedure does not include any non-encrypted stage. Otherwise, a malicious user can use her own modified version of that non-encrypted stage in order to boot her own code and try to break the encryption key by generating lot of plain/cipher patterns. The first boot stage of iMX233 (booting kernel from first SD partition) can be encrypted using the same OTP key (see elftosb -k parameter). Then the next stage of booting an encrypted Linux from the second partition was what I was looking for.

I had several obstacles to overcome:

  • First of all, I had to write my own version of kernel crypto module that can use the OTP hard-key instead of always expecting a soft-key to be provided [see this quesion].
  • Second, the original dm-crypt essiv IV method was not possible without modification in my case. Why? because it relies on the explicit value of the key for IV generation, and as I said, the key value is burried into hardware fuses and unknown to software.
  • Finally, I needed to add my custom initramfs into my compiled Freescale’s kernel. It is responsible to cryptsetup, mount the encrypted root partition, and switch_root to it.
Advertisements

March 20, 2013

Know The Hardware Crypto Engine of iMX23 ARM9 Platform Better!

Filed under: Uncategorized — fadishei @ 10:55 am
Tags: , , , ,

Introduction

The iMX233 ARM processor from Freescale comes with a Data Coprocessor (DCP) which contains a cryptography acceleration engine. It can offload some hashing/encryption/decryption algorithms from CPU core. Using my iMX233-Olinuxino-Micro board running Arch Linux ARM I am going to shed some light on this part of that processor.

Kernel Drivers

The iMX kernel tree well integrates the engine into standard linux crypto layer (see drivers/crypto/dcp.c, and drivers/crypto/dcp.h). Thus you can inspect what you have by issuing this command from shell and looking for dcp driver names:

> cat /proc/crypto
name         : sha1
driver       : sha1-dcp
module       : kernel
priority     : 300
refcnt       : 1
selftest     : passed
type         : shash
blocksize    : 64
digestsize   : 20

name         : cbc(aes)
driver       : dcp-cbc-aes
module       : kernel
priority     : 400
refcnt       : 1
selftest     : passed
type         : blkcipher
blocksize    : 16
min keysize  : 16
max keysize  : 32
ivsize       : 16
geniv        :

...

Judging from the priority values we can say that hardware accelerated dcp drivers take precedence over generic kernel implementations.

AES with Key in OTP ROM

One scarcely discussed feature that I am going to talk more about is the AES with OTP key. What’s that? iMX233 can perform hardware AES with the encryption key stored somewhere in its One-Time-Programmable (OTP) ROM. This key is not directly accessible by software running on the processor. Running software can only request encryption/decryption of their data without knowing what the key is. You can burn a key specific to each device into OTP and hide it totally by locking the key permanently. Security people know what treasure this feature is!

Manipulating the OTP key

In order to see what the key value of your device is, you’ll need to access the board in recovery mode by connecting your it via USB to a PC running the BitBurner software. The VCC pin of the USB cable needs to be disconnected (Only connect D+, D-, GND) and the SD card should be removed. Then power up the board and select HID device in BitBurner. You will see 4 32-bit ROM words CRYPTO0..CRYPTO3. You can see the current value of the key (the default key value is 0x00000000000000000000000000000000). You can also program your desired key value. But remember! It’s One-Time-Programmable! I haven’t dared enough to program a key myself yet! There are also lock bits that can be set in order to hide the key even from BitBurner. I have’nt dared to play with them either!

Kernel Drivers for AES with OTP Key

Unfortunately, AES with OTP key is not integrated into kernel crypto layer due to its different nature. See drivers/crypto/dcp_bootstream_ioctl.h. The name comes from the fact that Freescale uses this feature mainly for bootstream encryption. The driver provides an IOCTL for userspace programs. Some information on using this IOCTL is given in the Freescale iMX233 Evaluation Kit Reference Manual. I wrote a sample otpcrypt tool for demonstrating usage of AES with OTP key. Compile the code on your board and run it like this to encrypt/decrypt data:

> echo fadishei | otpcrypt | base64
oUP5IdEbv4RePVo7mF4hZw==
> echo oUP5IdEbv4RePVo7mF4hZw== | base64 -d | otpcrypt -d
fadishei

I used base64 coding for encrypted data above in order to make it possible to see it on terminal. In order to verify the correctness of the result, you can compare it with OpenSSL encryption results on any computer:

> echo fadishei | openssl enc -aes-128-ecb -K 00000000000000000000000000000000 | base64
oUP5IdEbv4RePVo7mF4hZw==
> echo oUP5IdEbv4RePVo7mF4hZw== | base64 -d | openssl enc -d -aes-128-ecb -K 00000000000000000000000000000000
fadishei

Notes on ECB mode and IV

iMX23 OTP AES is only capable of doing basic AES128 ECB mode on 128-bit data blocks. ECB is not quite secure. CBC is a more secure mode in which every data bloack is XORed with previous block result prior to encryption. A unique IV (Init Vector) is suggested to be used for each data item under encryption in order to have different ciphers for similar plaintexts. The OTP AES IOCTL does not feature CBC and IV. It should be implemented separately in software and needs some knowledge about AES algorithm and data padding. Refer to my otpcrypt tool to see how I managed to do that in a user-space applicaiton.

Request for Information

If you have further information on the DCP crypto engine of iMX233, specially the OTP AES, please comment!

November 24, 2012

Why does jbd2 constantly accesses my partition?

Filed under: Uncategorized — fadishei @ 5:46 pm
Tags: , , , ,

Are you frustrated by your HDD LED blinking constantly after mounting your newly formatted ext4 partition? Don’t go any further by killing innocent suspect processes! mkfs.ext4 holds some init ops for when you mount the fs to be done in background. You could disable such behavior by using -E lazy_itable_init=0.

October 13, 2012

Emulate OLinuxino Archlinux Image

Filed under: Uncategorized — fadishei @ 11:14 pm
Tags: , , , ,

OLinuxino is getting more and more popular for offering a good price-performance-size tradeoff. Archlinux now officially supports OLinuxino which means you have access to many prebuilt packages (openjdk, multimedia recorders and players, web servers, etc, etc) ready to be installed by the ‘pacman’ command.
A problem that you may still face as a developer is that due to the limited board resources, compiling programs and building new packages consumes lots of time, if possible at all.
If you want to use the power of your PC in develping for OLinuxino you can either setup a cross compilation environment or an emulation environment. In this post I describe an easy method for emulating the official Archlinux image of OLinuxino.

1. Download kernel, initrd, and filesystem provided by aurel32 for debian emulation from here
kernel: vmlinuz-2.6.32-5-versatile
initrd: initrd.img-2.6.32-5-versatile
filesystem image: debian_squeeze_armel_standard.qcow2

2. mount the first partition of debian_squeeze_armel_standard.qcow2 in /mnt (see here if you don’nt know how)

3. backup /mnt/lib/modules/* somewhere safe, then remove all the files in /mnt

4. extract the official OLinuxino Archlinux filesystem as root into /mnt

5. restore the the backup modules/* folder into /mnt/usr/lib/modules

6. Adjust the filesystem for changes posed by the emulation environment, such as:
change ttyAMA0 to tty1 in /mnt/etc/inittab
change usb0 to eth0 in /etc/rc.conf

7. unmount debian_squeeze_armel_standard.qcow2 and rename it to archlinux_olinuxino.qcow2

8. startup your emulated environment:
sudo qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.32-5-versatile -initrd initrd.img-2.6.32-5-versatile -hda archlinux_olinuxino.qcow2 -append “root=/dev/sda1”

January 29, 2012

Adding RTL (Right-to-Left) Support to Zotero

Filed under: Research,Uncategorized — fadishei @ 3:09 am
Tags: , , , , ,

Update (2012-08-16): I’ve patched the Zotero source and posted a pull request on github. I asked Zotero developers to add this feature to the main distribution. Please support it by asking the Zotero developers to merge the pull request via email or forum.

Pull request page: https://github.com/zotero/zotero/pull/157
Related forum post: http://forums.zotero.org/discussion/10879

In a previous post, I wrote about Zotero and the lack for supporting RTL languages in its note editor and how to work around this problem. In this post a better procedure for adding RTL support to Zotero is presented that also works in newer versions of Firefox.
The procedure is similar to the previous post with one difference: This time, you modify the Zotero plugin before installing it in Firefox.

mkdir ~/work
cd ~/work
wget http://download.zotero.org/extension/zotero-2.1.10.xpi
unzip -d xpi zotero-2.1.10.xpi
mkdir jar
cd jar
jar -xf ../xpi/chrome/zotero.jar
cd ..
wget http://downloads.sourceforge.net/project/tinymce/TinyMCE/3.3.9.2/tinymce_3_3_9_2.zip
unzip tinymce_3_3_9_2.zip
cp -au tinymce/jscripts/tiny_mce/* jar/content/zotero/tinymce/
sed -i 's/paste,contextmenu/paste,contextmenu,directionality/g' jar/content/zotero/tinymce/note.html
sed -i 's/sup,|,forecolor/sup,|,ltr,rtl,|,forecolor/g' jar/content/zotero/tinymce/note.html
cd jar
jar -c0f ../xpi/chrome/zotero.jar *
cd ../xpi
zip -r ../zotero-2.1.10-rtl.xpi *

The above procedure worked for me on Zotero 2.1.10 and Firefox 9.0.1.
The version of TinyMCE that should be downloaded can be determined by inspecting the file jar/content/zotero/tinymce/tiny_mce.js before downloading it.

July 8, 2011

perf_events and the secret behind very very large outlier values

During my research on power/performance analysis of computational workloads, I frequently use the perf_events kernel subsystem to get a graph of relevant performance counter values such as cache misses and instructions retired. You can examine this if you want by installing the libpfm4 library on a Linux machine with an enough up-to-date kernel. For me, Ubuntu 10.10 or newer works perfect. After compilation of libpfm4, you can find a “syst” tool in the “perf_examples” folder which can be used to examine the perf_events. A sample output of this command is given below (Note: the long output lines seem a mess on small monitors. If this is the case for you, copy and paste them in a text editor with line wrapping disabled):

$ sudo ./syst -c 0 -e PERF_COUNT_HW_CACHE_L1D:MISS,PERF_COUNT_HW_CACHE_L1I:MISS,PERF_COUNT_HW_CACHE_LL:MISS,PERF_COUNT_HW_CACHE_L1D:ACCESS,PERF_COUNT_HW_CACHE_L1I:ACCESS,PERF_COUNT_HW_CACHE_LL:ACCESS
------------------------
CPU0 val=409989               raw=199299 ena=2000395421 run=972407540 ratio=0.49 delta=369213          PERF_COUNT_HW_CACHE_L1D:MISS
CPU0 val=203841               raw=99091 ena=2000432800 run=972446620 ratio=0.49 delta=164564           PERF_COUNT_HW_CACHE_L1I:MISS
CPU0 val=211172               raw=844 ena=2000444925 run=7995247 ratio=0.00 delta=105590               PERF_COUNT_HW_CACHE_LL:MISS
CPU0 val=16091475             raw=8108192 ena=2000465017 run=1007996718 ratio=0.50 delta=9654365       PERF_COUNT_HW_CACHE_L1D:ACCESS
CPU0 val=42724654             raw=21784141 ena=2000484350 run=1019992634 ratio=0.51 delta=30353998     PERF_COUNT_HW_CACHE_L1I:ACCESS
CPU0 val=10031112             raw=100233 ena=2000504170 run=19989462 ratio=0.01 delta=10031112         PERF_COUNT_HW_CACHE_LL:ACCESS
------------------------
CPU0 val=501430               raw=261466 ena=3000602105 run=1564635603 ratio=0.52 delta=91441          PERF_COUNT_HW_CACHE_L1D:MISS
CPU0 val=347087               raw=182375 ena=3000612244 run=1576652337 ratio=0.53 delta=143246         PERF_COUNT_HW_CACHE_L1I:MISS
CPU0 val=375206               raw=5499 ena=3000615126 run=43976828 ratio=0.01 delta=164034             PERF_COUNT_HW_CACHE_LL:MISS
CPU0 val=33934452             raw=14475612 ena=3000617370 run=1279990387 ratio=0.43 delta=17842977     PERF_COUNT_HW_CACHE_L1D:ACCESS
CPU0 val=64070808             raw=29722497 ena=3000619469 run=1391989674 ratio=0.46 delta=21346154     PERF_COUNT_HW_CACHE_L1I:ACCESS
CPU0 val=2344440              raw=112486 ena=3000622062 run=143969520 ratio=0.05 delta=18446744073701864944 PERF_COUNT_HW_CACHE_LL:ACCESS
------------------------
CPU0 val=693081               raw=273320 ena=4000722671 run=1577704276 ratio=0.39 delta=191651         PERF_COUNT_HW_CACHE_L1D:MISS
CPU0 val=567389               raw=227722 ena=4000729723 run=1605693997 ratio=0.40 delta=220302         PERF_COUNT_HW_CACHE_L1I:MISS
CPU0 val=509063               raw=8139 ena=4000731389 run=63964418 ratio=0.02 delta=133857             PERF_COUNT_HW_CACHE_LL:MISS
CPU0 val=48617260             raw=21047221 ena=4000733390 run=1731984034 ratio=0.43 delta=14682808     PERF_COUNT_HW_CACHE_L1D:ACCESS
CPU0 val=67881736             raw=40027485 ena=4000739182 run=2359095923 ratio=0.59 delta=3810928      PERF_COUNT_HW_CACHE_L1I:ACCESS
CPU0 val=852461               raw=141288 ena=4000745498 run=663088489 ratio=0.17 delta=18446744073708059637 PERF_COUNT_HW_CACHE_LL:ACCESS
------------------------
CPU0 val=1271202              raw=406130 ena=5000845112 run=1597694641 ratio=0.32 delta=578121                 PERF_COUNT_HW_CACHE_L1D:MISS
CPU0 val=812083               raw=316607 ena=5000851173 run=1949682622 ratio=0.39 delta=244694                 PERF_COUNT_HW_CACHE_L1I:MISS
CPU0 val=68883                raw=14204 ena=5000856091 run=1031189733 ratio=0.21 delta=18446744073709111436    PERF_COUNT_HW_CACHE_LL:MISS
CPU0 val=45801721             raw=21607567 ena=5000861964 run=2359222674 ratio=0.47 delta=18446744073706736077 PERF_COUNT_HW_CACHE_L1D:ACCESS
CPU0 val=87662128             raw=41579483 ena=5000865063 run=2371986478 ratio=0.47 delta=19780392             PERF_COUNT_HW_CACHE_L1I:ACCESS
CPU0 val=1364606              raw=188820 ena=5000867812 run=691967970 ratio=0.14 delta=512145                  PERF_COUNT_HW_CACHE_LL:ACCESS
------------------------
CPU0 val=1427100              raw=511222 ena=6000961317 run=2149690055 ratio=0.36 delta=155898               PERF_COUNT_HW_CACHE_L1D:MISS
CPU0 val=979620               raw=350930 ena=6000967977 run=2149729928 ratio=0.36 delta=167537               PERF_COUNT_HW_CACHE_L1I:MISS
CPU0 val=89669                raw=18827 ena=6000969658 run=1259961587 ratio=0.21 delta=20786                 PERF_COUNT_HW_CACHE_LL:MISS
CPU0 val=57523422             raw=26794792 ena=6000974528 run=2795293771 ratio=0.47 delta=11721701           PERF_COUNT_HW_CACHE_L1D:ACCESS
CPU0 val=131362760            raw=56725304 ena=6000980367 run=2591354160 ratio=0.43 delta=43700632           PERF_COUNT_HW_CACHE_L1I:ACCESS
CPU0 val=1733386              raw=305015 ena=6000983863 run=1055962131 ratio=0.18 delta=368780               PERF_COUNT_HW_CACHE_LL:ACCESS

The delta values reported above state the counted values within the periods of 1s. One odd thing about that output is the very large outlier values such as the last-level cache misses of 18446744073701864944 in the second measurement interval. It got me quite a time until I found the reason for getting such values. First of all, if you look at the source code, you will see that they are not big outliers, but in fact small negative values which are interpreted as unsigned 64-bit integers. For example, 18446744073701864944 is in fact -7686672 when interpreted as unsigned integer. But why do we get negative numbers at all?
The root of the problem lies in a concept known as “event multiplexing”. The number or CPU performance counters are limited. For example, my Core 2 Quad Intel CPU only allows two cache-related events to be counted simultaneously. To overcome this limitation, the counters are time-shared among the desired counted events in software (in perf_events kernel subsystem). Thus, an event is in fact counted at only a fraction of the real time passed. For the fraction in which a counter is not counted, the value is estimated based on the other fraction. This causes some error in the event counting, which obviously may deviate the value into a negative number. We, in fact, trade accuracy for counting more events.

January 4, 2010

Hello world!

Filed under: Uncategorized — fadishei @ 4:06 pm
public class Hello
{
	public static void main(String args[])
	{
		System.out.println("hello");
	}
}

Blog at WordPress.com.