Hi,

I am not the best C reader and programmer out there so I try to make
myself tools that may seem useless in order to better understand.  I see
this in /sys/dev/softraid_crypto.c

----
int
sr_crypto_encrypt(u_char *p, u_char *c, u_char *key, size_t size, int alg)
{
        rijndael_ctx            ctx;
        int                     i, rv = 1;

        switch (alg) {
        case SR_CRYPTOM_AES_ECB_256:
                if (rijndael_set_key_enc_only(&ctx, key, 256) != 0)
                        goto out;
                for (i = 0; i < size; i += RIJNDAEL128_BLOCK_LEN)
                        rijndael_encrypt(&ctx, &p[i], &c[i]);
                rv = 0;
                break;
        default:
                DNPRINTF(SR_D_DIS, "%s: unsupported encryption algorithm
%d\n",
                    "softraid", alg);
                rv = -1;
                goto out;
        }
----

so it says SR_CRYPTOM_AES_ECB_256:
                          ^^^

1. wikipedia has this to say about the ECB mode:

"The disadvantage of this method is that identical plaintext blocks are
encrypted into identical ciphertext blocks; thus it does not hide data
patterns well."

http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
section 4.1

2. In the book "Cryptographic Engineering" by Niels Ferguson, Bruce
Schneier and Tadayoshi Kohno, it says on page 65, section 4.2

"Do not ever use ECB for anything."


So I slept on this many nights and wondered if perhaps I read the code
wrong, misunderstood something.  So then I wrote a program to analyse a
sparse file which contains a softraid encrypted volume.  The sparse file
I created with something like (not true sequence):

dd if=/dev/zero of=EFS2 bs=1g count=1
vnconfig vnd0 EFS2
bioctl -c C -l /dev/vnd0a softraid0

And I created a filesystem on it and populated it.  In fact I use this
EFS2 file for storing work related things in it (so I can never share
it).  I ran this program over the EFS2 file:

----
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int mycmp(const void *, const void*);
void uniq(char *addr, u_int64_t size);

int
main(void)
{
        int fd;
        uint64_t i, j;
        uint64_t count;
        struct stat sb;
        char *addr;

        printf("opening file\n");
        fd = open("/tmp/EFS2", O_RDWR, 0600);

        if (fd < 0) {
                perror("open");
                exit(1);
        }

        if (fstat(fd, &sb) < 0) {
                perror("fstat");
                exit(1);
        }

        addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED
| MAP_ANON, -1, 0);

        if (addr == MAP_FAILED) {
                perror("mmap");
                exit(1);
        }

        printf("reading in file, %lld bytes\n", sb.st_size);
        count = 1;
        for (i = sb.st_size, j = 0; i >= 0; i -= (16), j += (16)) {
                if (read(fd, &addr[j], 16) == 0)
                        break;

                if (j >= count) {
                        printf("%d, ", count);
                        fflush(stdout);
                        count <<= 1;
                }
        }

        close(fd);

        printf("\nsorting memory\n");
        heapsort((void*)addr, sb.st_size / 16, 16, mycmp);

        printf("finding duplicates\n");
        uniq(addr, sb.st_size);

        printf("munmaping file\n");
        munmap(addr, sb.st_size);
        exit(0);
}

int
mycmp(const void *p, const void *e)
{
        return (memcmp(p, e, 16));
}

void
uniq(char *addr, u_int64_t size)
{
        char *last = addr;
        u_int64_t i, j;
        int uniq = 0;

        for (j = size, i = 0; j > 0; j -= 16, i += 16) {
                if (i && memcmp(last, &addr[i], 16) == 0) {
                        uniq++;
                }

                last = &addr[i];
        }

        printf("duplicates (> 1) == %d\n", uniq);
}
----

The program mmaps anonymous space the size of the EFS2 file (1GB) then
copies the sparse file to this memory region, sorts it and does
something like a uniq only counting how many times there is a duplicate
occurance.  The output looks like this:

----
mercury$ ./probe
opening file
reading in file, 1073741824 bytes
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912,
sorting memory
finding duplicates
duplicates (> 1) == 652063
munmaping file
----

so it says that there is 652063 occurences where AES blocks were
duplicated, to me that's near 10 MB of material someone can use like the
above [1] where it says it could describe the data pattern.

So I'm sorta stuck with this still, was there any point of me doing this
program, or is softraid_crypto still safe from cryptanalysis?

If indeed it is ECB would it be worth it to listen to [2] and not use
it?  Would a counter mode be better for this perhaps?

Regards,

-peter

Reply via email to