+ if (r == -ENOTSUP)
+ r = 0;
+ return r;
+}
+
+static int action_benchmark(int arg __attribute__((unused)))
+{
+ static struct {
+ char *cipher;
+ char *mode;
+ size_t key_size;
+ size_t iv_size;
+ } bciphers[] = {
+ { "aes", "cbc", 16, 16 },
+ { "serpent", "cbc", 16, 16 },
+ { "twofish", "cbc", 16, 16 },
+ { "aes", "cbc", 32, 16 },
+ { "serpent", "cbc", 32, 16 },
+ { "twofish", "cbc", 32, 16 },
+ { "aes", "xts", 32, 16 },
+ { "serpent", "xts", 32, 16 },
+ { "twofish", "xts", 32, 16 },
+ { "aes", "xts", 64, 16 },
+ { "serpent", "xts", 64, 16 },
+ { "twofish", "xts", 64, 16 },
+ { NULL, NULL, 0, 0 }
+ };
+ char *header = "# Tests are approximate using memory only (no storage IO).\n"
+ "# Algorithm | Key | Encryption | Decryption\n";
+ char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ double enc_mbr = 0, dec_mbr = 0;
+ int key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS);
+ int iv_size = 16;
+ int buffer_size = 1024 * 1024;
+ char *c;
+ int i, r;
+
+ if (opt_cipher) {
+ r = crypt_parse_name_and_mode(opt_cipher, cipher, NULL, cipher_mode);
+ if (r < 0) {
+ log_err(_("No known cipher specification pattern detected.\n"));
+ return r;
+ }
+ if ((c = strchr(cipher_mode, '-')))
+ *c = '\0';
+
+ /* FIXME: not really clever :) */
+ if (strstr(cipher, "des"))
+ iv_size = 8;
+
+ r = crypt_benchmark(NULL, cipher, cipher_mode,
+ key_size / 8, iv_size, buffer_size,
+ &enc_mbr, &dec_mbr);
+ if (!r) {
+ log_std("%s", header);
+ strncat(cipher, "-", MAX_CIPHER_LEN);
+ strncat(cipher, cipher_mode, MAX_CIPHER_LEN);
+ log_std("%11s %4db %5.1f MiB/s %5.1f MiB/s\n",
+ cipher, key_size, enc_mbr, dec_mbr);
+ } else if (r == -ENOTSUP)
+ log_err(_("Cipher %s is not available.\n"), opt_cipher);
+ } else {
+ for (i = 0; bciphers[i].cipher; i++) {
+ r = crypt_benchmark(NULL, bciphers[i].cipher, bciphers[i].mode,
+ bciphers[i].key_size, bciphers[i].iv_size,
+ buffer_size, &enc_mbr, &dec_mbr);
+ if (r == -ENOENT)
+ break;
+ if (i == 0)
+ log_std("%s", header);
+
+ snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
+ bciphers[i].cipher, bciphers[i].mode);
+ if (!r)
+ log_std("%11s %4db %5.1f MiB/s %5.1f MiB/s\n",
+ cipher, bciphers[i].key_size*8, enc_mbr, dec_mbr);
+ else
+ log_std("%11s %4db %12s %12s\n", cipher,
+ bciphers[i].key_size*8, _("N/A"), _("N/A"));
+ }
+ }
+
+ if (r == -ENOENT)
+ log_err( _("Required kernel crypto interface is not available.\n"
+ "Ensure you have af_skcipher kernel module loaded.\n"));