nettle-benchmark.c 7.78 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/* nettle-benchmark.c
 *
 * Tries the performance of the various algorithms.
 *
 */
 
/* nettle, low-level cryptographics library
 *
 * Copyright (C) 2001 Niels Mller
 *  
 * The nettle library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * The nettle library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the nettle library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA.
 */

#include "aes.h"
Niels Möller's avatar
Niels Möller committed
28 29 30 31 32 33 34
#include "arcfour.h"
#include "blowfish.h"
#include "cast128.h"
#include "des.h"
#include "serpent.h"
#include "twofish.h"

35 36
#include "cbc.h"

Niels Möller's avatar
Niels Möller committed
37
#include <assert.h>
38 39 40 41 42 43 44
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <time.h>

Niels Möller's avatar
Niels Möller committed
45 46 47
/* Encrypt 100MB, 1K at a time. */
#define BENCH_BLOCK 1024
#define BENCH_COUNT 10240
48 49 50 51

typedef void (*crypt_func)(void *ctx,
			   unsigned length, uint8_t *dst,
			   const uint8_t *src);
Niels Möller's avatar
Niels Möller committed
52 53 54 55 56

typedef void (*setkey_func)(void *ctx,
                            unsigned length,
                            const uint8_t *key);

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
static double
time_function(void (*f)(void *arg), void *arg)
{
  clock_t before;
  clock_t after;

  before = clock();
  
  f(arg);
  
  after = clock();

  return ((double)(after - before)) / CLOCKS_PER_SEC;
}

struct bench_cipher_info
{
  void *ctx;
  crypt_func crypt;
  uint8_t *data;
};

static void
bench_cipher(void *arg)
{
  struct bench_cipher_info *info = arg;
  unsigned i;
  
Niels Möller's avatar
Niels Möller committed
85 86
  for (i = 0; i<BENCH_COUNT; i++)
    info->crypt(info->ctx, BENCH_BLOCK, info->data, info->data);
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
}

struct bench_cbc_info
{
  void *ctx;
  crypt_func crypt;

  uint8_t *data;

  unsigned block_size;
  uint8_t *iv;
};

static void
bench_cbc_encrypt(void *arg)
{
  struct bench_cbc_info *info = arg;
  unsigned i;

Niels Möller's avatar
Niels Möller committed
106
  for (i = 0; i<BENCH_COUNT; i++)
107 108
    cbc_encrypt(info->ctx, info->crypt,
		info->block_size, info->iv,
Niels Möller's avatar
Niels Möller committed
109
		BENCH_BLOCK, info->data, info->data);
110 111 112 113 114 115 116 117
}

static void
bench_cbc_decrypt(void *arg)
{
  struct bench_cbc_info *info = arg;
  unsigned i;

Niels Möller's avatar
Niels Möller committed
118
  for (i = 0; i<BENCH_COUNT; i++)
119 120
    cbc_decrypt(info->ctx, info->crypt,
		info->block_size, info->iv,
Niels Möller's avatar
Niels Möller committed
121
		BENCH_BLOCK, info->data, info->data);
122 123 124 125 126 127 128
}

/* Set data[i] = floor(sqrt(i)) */
static void
init_data(uint8_t *data)
{
  unsigned i,j;
Niels Möller's avatar
Niels Möller committed
129
  for (i = j = 0; i<BENCH_BLOCK;  i++)
130 131 132 133 134 135 136 137
    {
      if (j*j < i)
	j++;
      data[i] = j;
    }
}

static void
Niels Möller's avatar
Niels Möller committed
138 139
init_key(unsigned length,
         uint8_t *key)
140
{
Niels Möller's avatar
Niels Möller committed
141 142 143
  unsigned i;
  for (i = 0; i<length; i++)
    key[i] = i;
144 145
}

Niels Möller's avatar
Niels Möller committed
146
struct cipher
147
{
Niels Möller's avatar
Niels Möller committed
148 149
  const char *name;
  unsigned context_size;
150
  
Niels Möller's avatar
Niels Möller committed
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
  unsigned block_size;
  unsigned key_size;

  setkey_func setkey;
  crypt_func encrypt;
  crypt_func decrypt;
};
  

static void
time_cipher(struct cipher *cipher)
{
  void *ctx = alloca(cipher->context_size);
  uint8_t *key = alloca(cipher->key_size);

  uint8_t data[BENCH_BLOCK];

  printf("\n");
  
  init_data(data);
171 172 173

  {
    struct bench_cipher_info info
Niels Möller's avatar
Niels Möller committed
174
      = { ctx, cipher->encrypt, data };
175
    
Niels Möller's avatar
Niels Möller committed
176 177 178 179 180
    init_key(cipher->key_size, key);
    cipher->setkey(ctx, cipher->key_size, key);
    
    printf("%13s (ECB encrypt): %f\n", cipher->name,
           time_function(bench_cipher, &info));
181
  }
Niels Möller's avatar
Niels Möller committed
182
  
183 184
  {
    struct bench_cipher_info info
Niels Möller's avatar
Niels Möller committed
185
      = { ctx, cipher->decrypt, data };
186
    
Niels Möller's avatar
Niels Möller committed
187 188 189 190 191
    init_key(cipher->key_size, key);
    cipher->setkey(ctx, cipher->key_size, key);
    
    printf("%13s (ECB decrypt): %f\n", cipher->name,
           time_function(bench_cipher, &info));
192 193
  }

Niels Möller's avatar
Niels Möller committed
194 195 196 197 198 199 200 201
  if (cipher->block_size)
    {
      uint8_t *iv = alloca(cipher->block_size);
      
      /* Do CBC mode */
      {
        struct bench_cbc_info info
          = { ctx, cipher->encrypt, data, cipher->block_size, iv };
202
    
Niels Möller's avatar
Niels Möller committed
203
        memset(iv, 0, sizeof(iv));
204
    
Niels Möller's avatar
Niels Möller committed
205
        cipher->setkey(ctx, cipher->key_size, key);
206

Niels Möller's avatar
Niels Möller committed
207 208 209 210
        printf("%13s (CBC encrypt): %f\n", cipher->name,
               time_function(bench_cbc_encrypt,
                             &info));
      }
211

Niels Möller's avatar
Niels Möller committed
212 213 214
      {
        struct bench_cbc_info info
          = { ctx, cipher->decrypt, data, cipher->block_size, iv };
215
    
Niels Möller's avatar
Niels Möller committed
216
        memset(iv, 0, sizeof(iv));
217

Niels Möller's avatar
Niels Möller committed
218
        cipher->setkey(ctx, cipher->key_size, key);
219

Niels Möller's avatar
Niels Möller committed
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
        printf("%13s (CBC decrypt): %f\n", cipher->name,
               time_function(bench_cbc_decrypt,
                             &info));
      }
    }
}

/* DES uses a different signature for the key set function.
 * And we have to adjust parity. */
static void
des_set_key_hack(void *c, unsigned length, const uint8_t *key)
{
  struct des_ctx *ctx = c;
  uint8_t pkey[DES_KEY_SIZE];
  
  assert(length == DES_KEY_SIZE);
  des_fix_parity(DES_KEY_SIZE, pkey, key);
  if (!des_set_key(ctx, pkey))
    abort();
}

static void
des3_set_key_hack(void *c, unsigned length, const uint8_t *key)
{
  struct des3_ctx *ctx = c;
  uint8_t pkey[DES3_KEY_SIZE];
  
  assert(length == DES3_KEY_SIZE);
  des_fix_parity(DES3_KEY_SIZE, pkey, key);
  if (!des3_set_key(ctx, pkey))
    abort();
}

#define NCIPHERS 12

int
main(int argc, char **argv)
{
  unsigned i;
  struct cipher ciphers[NCIPHERS] =
    {
      { "AES-128", sizeof(struct aes_ctx),
        AES_BLOCK_SIZE, 16,
        (setkey_func) aes_set_key,
        (crypt_func) aes_encrypt,
        (crypt_func) aes_decrypt
      },
      { "AES-192", sizeof(struct aes_ctx),
        AES_BLOCK_SIZE, 24,
        (setkey_func) aes_set_key,
        (crypt_func) aes_encrypt,
        (crypt_func) aes_decrypt
      },
      { "AES-256", sizeof(struct aes_ctx),
        AES_BLOCK_SIZE, 32,
        (setkey_func) aes_set_key,
        (crypt_func) aes_encrypt,
        (crypt_func) aes_decrypt
      },
      { "ARCFOUR-128", sizeof(struct arcfour_ctx),
        0, ARCFOUR_KEY_SIZE,
        (setkey_func) arcfour_set_key,
        (crypt_func) arcfour_crypt,
        (crypt_func) arcfour_crypt
      },
      { "BLOWFISH-128", sizeof(struct blowfish_ctx),
        BLOWFISH_BLOCK_SIZE, BLOWFISH_KEY_SIZE,
        (setkey_func) blowfish_set_key,
        (crypt_func) blowfish_encrypt,
        (crypt_func) blowfish_decrypt
      },
      { "CAST-128", sizeof(struct cast128_ctx),
        CAST128_BLOCK_SIZE, CAST128_KEY_SIZE,
        (setkey_func) cast128_set_key,
        (crypt_func) cast128_encrypt,
        (crypt_func) cast128_decrypt
      },
      { "DES", sizeof(struct des_ctx),
        DES_BLOCK_SIZE, DES_KEY_SIZE,
        des_set_key_hack,
        (crypt_func) des_encrypt,
        (crypt_func) des_decrypt
      },
      { "DES3", sizeof(struct des3_ctx),
        DES3_BLOCK_SIZE, DES3_KEY_SIZE,
        des3_set_key_hack,
        (crypt_func) des3_encrypt,
        (crypt_func) des3_decrypt
      },
      { "SERPENT-256", sizeof(struct serpent_ctx),
        SERPENT_BLOCK_SIZE, SERPENT_KEY_SIZE,
        (setkey_func) serpent_set_key,
        (crypt_func) serpent_encrypt,
        (crypt_func) serpent_decrypt
      },
      { "TWOFISH-128", sizeof(struct twofish_ctx),
        TWOFISH_BLOCK_SIZE, 16,
        (setkey_func) twofish_set_key,
        (crypt_func) twofish_encrypt,
        (crypt_func) twofish_decrypt
      },
      { "TWOFISH-192", sizeof(struct twofish_ctx),
        TWOFISH_BLOCK_SIZE, 24,
        (setkey_func) twofish_set_key,
        (crypt_func) twofish_encrypt,
        (crypt_func) twofish_decrypt
      },
      { "TWOFISH-256", sizeof(struct twofish_ctx),
        TWOFISH_BLOCK_SIZE, 32,
        (setkey_func) twofish_set_key,
        (crypt_func) twofish_encrypt,
        (crypt_func) twofish_decrypt
      },
    };
334

Niels Möller's avatar
Niels Möller committed
335 336 337
  for (i = 0; i<NCIPHERS; i++)
    time_cipher(ciphers + i);
  
338 339
  return 0;
}