Thursday, July 12, 2012

Centos vlan configuration

On our Centos boxes, we start with a minimal installation, and then add additional rpm packages as required. Today, we wanted to add a vlan trunk interface on an existing box. We created the config file as follows:
# cat /etc/sysconfig/network-scripts/ifcfg-eth5.800
# Intel Corporation 82546GB Gigabit Ethernet Controller (Copper)

But when we tried to bring up the vlan interface, we got this error:
# ifup eth5.800
Device eth5.800 does not seem to be present, delaying initialization.

This was caused because the 'vconfig' program was missing, and so we had to install that package:
# which vconfig
/usr/bin/which: no vconfig in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
# yum install vconfig
# which vconfig

Then everything worked as expected:
# ifup eth5.800
Added VLAN with VID == 800 to IF -:eth5:-
# ls -l /proc/net/vlan
-rw------- 1 root root 0 Jul 12 10:35 config
-rw------- 1 root root 0 Jul 12 10:35 eth5.800
# lsmod | grep 8021q
8021q 57425 0

BTW, the above commands were run on the following version of Centos:
# cat /etc/redhat-release
CentOS release 5.8 (Final)

Thursday, July 05, 2012

AES Encryption & Decryption from the command line with OpenSSL

Today, I wanted to gain a deeper understanding of AES encryption. I have succesfully used AES encryption with ipsec vpn's. But here I want to examine what are the inputs and outputs from the AES algorithm, and do some sanity checks with test data using openssl from the command-line.

On the wikipedia page for AES, they mention, "..Test vectors are a set of known ciphers for a given input and key. NIST distributes the reference of AES test vectors as AES Known Answer Test (KAT) Vectors (in ZIP format)."

That sounds like what I need as a reference, so I downloaded:

...and selected (guessed?) file "CBCVarKey128.rsp" as suitable, because I wanted to use a 128 bit key length,

Here is one example (from 128 possible examples) from that file:
KEY = 80000000000000000000000000000000
IV = 00000000000000000000000000000000
PLAINTEXT = 00000000000000000000000000000000
CIPHERTEXT = 0edd33d3c621e546455bd8ba1418bec8

Ok, first let's sanity check we can generate the required PLAINTEXT. I'm using xxd to do this, as I explained in an earlier blog post.

# echo -n '00000000000000000000000000000000' | xxd -p -r | hexdump -C
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|

So the above looks good. We are generating the 16 bytes of test data, from a 32 character hexadecimal string.

Openssl allow you to specify the Key and the 'Initialization Vector' on the command like, as hexadecimal strings, using the '-K' and '-iv' parameters. Be careful, thats an uppercase K for the key. As another sanity check, it is useful to use the '-P' option, again uppercase, to get openssl to report back what it thinks are the values of the Key and IV. So lets try this:

# echo -n '00000000000000000000000000000000' | xxd -p -r | openssl enc -aes-128-cbc -P -nosalt -K '80000000000000000000000000000000' -iv '00000000000000000000000000000000'
iv =00000000000000000000000000000000

Ok, thats good. They Key and IV values are what we were expecting.
By the way, for this sort of validation check, we don't want to use a salt, hence the use of the '-nosalt' option.
Right, lets remove the '-P' and see what data comes out:
# echo -n '00000000000000000000000000000000' | xxd -p -r | openssl enc -aes-128-cbc -nosalt -K '80000000000000000000000000000000' -iv '00000000000000000000000000000000' | hexdump -C
00000000 0e dd 33 d3 c6 21 e5 46 45 5b d8 ba 14 18 be c8 |.Ý3ÓÆ!åFE[غ..¾È|
00000010 fe 3d e6 e1 86 98 08 4f 63 de e5 04 42 ff 94 d2 |þ=æá...OcÞå.Bÿ.Ò|

Oh, that strange!
I'm trying to encrypt 16-bytes, but the output is 32 bytes long!
But the first 16 bytes of output looks correct!

The answer to this is padding. If you specify the '-nopad' option, then you get the expected 16 bytes of output:

echo -n '00000000000000000000000000000000' | xxd -p -r | openssl enc -aes-128-cbc -nopad -nosalt -K '80000000000000000000000000000000' -iv '00000000000000000000000000000000' | xxd -p

Good. Thats the CIPHERTEXT output we were expecting!

If you check 'man enc' you see that the '-nopad' option, disables standard block padding. And the man page also notes "All the block ciphers normally use PKCS#5 padding also known as standard block padding".

By the way, in the above tests, the IV is all-zeroes, so we can abbreviate the command like this:

echo -n '00000000000000000000000000000000' | xxd -p -r | openssl enc -aes-128-cbc -nopad -nosalt -K 80000000000000000000000000000000 -iv 0 | xxd -p

To finish off, lets try some decryption, reversing what we did above:
# echo -n '0edd33d3c621e546455bd8ba1418bec8' | xxd -p -r | openssl enc -aes-128-cbc -d -nosalt -K 80000000000000000000000000000000 -iv 0 -nopad | xxd -p

Ok, that looks good. I think I am begining to get the hang of this!

Using openssl to generate HMAC using a binary key

If you want to do a quick command-line generation of a HMAC, then the openssl command is useful.
For example:
# echo -n 'value' | openssl dgst -sha1 -hmac 'key'
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# echo -n 'value' | openssl dgst -md5 -hmac 'key'
(stdin)= 01433efd5f16327ea4b31144572c67f6

...or alternatively...
# echo -n 'value' | openssl sha1 -hmac 'key'
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# echo -n 'value' | openssl md5 -hmac 'key'
(stdin)= 01433efd5f16327ea4b31144572c67f6


BUT, note in the above commands, the 'value' and 'key' are ascii strings. The above syntax is problematic if you want to specify a Binary value for the key, which does not correspond to printable characters.

This had been a problem reported in the past:

But I can report here, that certainly with openssl v1.0.0, the following method allows you to specify a binary key, by passing it as a string of hex values.

To demonstate the point, let's get the hex string equivalent of the three character acsii string 'key', so that we can use the same hashes as in the examples above. To do this, I use utility 'xxd' which does a hexdump. (For further information on 'xdd' see my previous blog posts.)

# echo -n 'key' | xxd -p

Ok, so the hex-string "6b6579" corresponds to ascii string "key".

So after reading up the man page for 'openssl dgst', we try a further alternate form of the command, like this:

# echo -n 'value' | openssl dgst -sha1 -mac HMAC -macopt key:key
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# echo -n 'value' | openssl dgst -sha1 -mac HMAC -macopt hexkey:6b6579
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# echo -n 'value' | openssl dgst -md5 -mac HMAC -macopt key:key
(stdin)= 01433efd5f16327ea4b31144572c67f6

# echo -n 'value' | openssl dgst -md5 -mac HMAC -macopt hexkey:6B6579
(stdin)= 01433efd5f16327ea4b31144572c67f6

Note the use of the '-macopt hexkey:string' option which allows you to specify the key in hexadecimal (two hex digits per byte).

Nice! So now we can do something like this:

# echo -n '55f80d132e8b68eb' | xxd -r -p | openssl dgst -sha1 -mac HMAC -macopt key:645a487340f4c7f0
(stdin)= 2f0928b4bb365b4a590d84960a7cd04fd2d80221

I hope to show a practical use of the above in a future blog post!

Finally, I will just confirm some details of the system that gave the above output:

# rpm -qa | grep openssl

# cat /etc/redhat-release
CentOS release 6.2 (Final)

By the way, if your wondering about the '(stdin)= ' that openssl is outputing, then see my previous blog post on this subject.

Convert a Hex dump to Binary data with xxd

In my last blog post, I demonstarted how to dump a binary file, using either 'hexdump' or 'xxd'.
In summary, we can do this:
# ls -l hash-file.bin
-rw-r--r-- 1 root root 20 Jul 4 10:05 hash-file.bin
# xxd -p hash-file.bin

Ok, what if we want to do the reverse of this.
That is to take a string of hex characters and create a binary file!
The utility 'xxd' can also do this.

To demonstrate, lets first save the hex representation into a separate file:

# xxd -p hash-file.bin > hash-file.hex
# ls -l hash-file.hex
-rw-r--r-- 1 root root 41 Jul 4 12:04 hash-file.hex
# cat hash-file.hex

Ok, here's the clever part. Note we now pass the '-r' option to xdd to 'reverse' it's operation.
# xxd -p -r hash-file.hex > new-file.bin
# ls -l new-file.bin
-rw-r--r-- 1 root root 20 Jul 4 12:19 new-file.bin
# xxd -p new-file.bin
# cmp hash-file.bin new-file.bin

So we recreated the binary file, as 'new-file.bin' from the hex dump and we proved it is identical to the file we started with.

You can also feed into xdd from the pipeline, like this:

# cat hash-file.hex | xxd -p -r > new-file.bin
# xxd -p new-file.bin

..and here are some more examples:
# echo -n 'password' | xxd -p | xxd -p -r | hexdump -C
00000000  70 61 73 73 77 6f 72 64                           |password|

# echo -n 'c0a06003' | xxd -p -r | hexdump -C
00000000  c0 a0 60 03                                       |..`.|

hexdump and xxd output compared

Here I'm working with a Centos Linux system, and I've found two seperate utility programs that can produced a hex dump. One is called hexdump and the other is xxd, and they are provided as part of two seperate packages.
# which hexdump
# rpm -qf /usr/bin/hexdump

# which xxd
# rpm -qf /usr/bin/xxd

Ok, so lets compare the output format of the hex dump with these utilities. But first we need some test data, which I'm going to generate with 'openssl'. Conveniently, openssl can output the data in either hex (the default) or binary.

# echo -n 'value' | openssl dgst -sha1 -hmac "key"
# echo -n 'value' | openssl dgst -sha1 -hmac "key" -binary > hash-file.bin
# ls -l hash-file.bin
-rw-r--r-- 1 root root 20 Jul 4 10:05 hash-file.bin

So we have our test data in a file called 'hash-file.bin'. It's 20 bytes long as it contains a 160 bit sha1 hash. Ok, let's try dumping that file and see what we get:
# hexdump hash-file.bin
0000000 4457 4c3a 2305 a450 3846 5d83 fd64 8266
0000010 812f 1933

# xxd hash-file.bin
0000000: 5744 3a4c 0523 50a4 4638 835d 64fd 6682  WD:L.#P.F8.]d.f.
0000010: 2f81 3319                                /.3.

Um, interesting!
Note the default output is grouping the bytes into 16-bit values and there is a difference in how to interpret the endianness.

Let's try customizing the output with some options:

# hexdump -C hash-file.bin
00000000  57 44 3a 4c 05 23 50 a4  46 38 83 5d 64 fd 66 82  |WD:L.#P.F8.]d.f.|
00000010  2f 81 33 19                                       |/.3.|

# xxd -g 1 hash-file.bin
0000000: 57 44 3a 4c 05 23 50 a4 46 38 83 5d 64 fd 66 82  WD:L.#P.F8.]d.f.
0000010: 2f 81 33 19                                      /.3.

# xxd -p hash-file.bin

So this is 'better' for seeing the byte sequence.

Openssl and the "(stndin)= " prefix

Recently, I've been playing around with the openssl utility. Doing things like this:
# echo -n 'value' | openssl dgst -sha1 -hmac 'key'

# rpm -qa | grep openssl

# cat /etc/redhat-release
CentOS release 5.8 (Final)

Note that I show the version and operating system I'm using. Here's why. Look at the following:
# echo -n 'value' | openssl dgst -sha1 -hmac 'key'
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# rpm -qa | grep openssl

# cat /etc/redhat-release
CentOS release 6.2 (Final)

So on a more recent system, openssl has prefixed it's output with "(stndin)= ".
I'm not finding this particularly helpful for my application.
One workaround, suggested here, is to use sed to remove it, like this:
# echo -n 'value' | openssl dgst -sha1 -hmac 'key' | sed 's/^.*= //'