static void check_ciphers (void) { static int algos[] = { GCRY_CIPHER_3DES, GCRY_CIPHER_CAST5, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_AES, GCRY_CIPHER_AES192, GCRY_CIPHER_AES256, GCRY_CIPHER_TWOFISH, GCRY_CIPHER_TWOFISH128, GCRY_CIPHER_DES, GCRY_CIPHER_SERPENT128, GCRY_CIPHER_SERPENT192, GCRY_CIPHER_SERPENT256, 0 }; static int algos2[] = { GCRY_CIPHER_ARCFOUR, 0 }; int i; for (i = 0; algos[i]; i++) { if (verbose) fprintf (stderr, "checking `%s' [%i]\n", gcry_cipher_algo_name (algos[i]), gcry_cipher_map_name (gcry_cipher_algo_name (algos[i]))); check_one_cipher (algos[i], GCRY_CIPHER_MODE_ECB, 0); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB, 0); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, 0); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CTR, 0); } for (i = 0; algos2[i]; i++) { if (verbose) fprintf (stderr, "checking `%s'\n", gcry_cipher_algo_name (algos2[i])); check_one_cipher (algos2[i], GCRY_CIPHER_MODE_STREAM, 0); } /* we have now run all cipher's selftests */ /* TODO: add some extra encryption to test the higher level functions */ }
static int bench_encrypt_init (struct bench_obj *obj) { struct bench_cipher_mode *mode = obj->priv; gcry_cipher_hd_t hd; int err, keylen; obj->min_bufsize = BUF_START_SIZE; obj->max_bufsize = BUF_END_SIZE; obj->step_size = BUF_STEP_SIZE; obj->num_measure_repetitions = num_measurement_repetitions; err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'\n", gcry_cipher_algo_name (mode->algo)); exit (1); } keylen = gcry_cipher_get_algo_keylen (mode->algo); if (keylen) { char key[keylen]; int i; for (i = 0; i < keylen; i++) key[i] = 0x33 ^ (11 - i); err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } else { fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", gcry_cipher_algo_name (mode->algo)); gcry_cipher_close (hd); exit (1); } obj->priv = hd; return 0; }
gcry_cipher_hd_t gkm_aes_key_get_cipher (GkmAesKey *self, int mode) { gcry_cipher_hd_t cih; gcry_error_t gcry; int algorithm; g_return_val_if_fail (GKM_IS_AES_KEY (self), NULL); algorithm = algorithm_for_length (self->n_value); g_return_val_if_fail (algorithm != 0, NULL); gcry = gcry_cipher_open (&cih, algorithm, mode, 0); if (gcry != 0) { g_warning ("couldn't open %s cipher: %s", gcry_cipher_algo_name (algorithm), gcry_strerror (gcry)); return NULL; } /* Setup the key */ gcry = gcry_cipher_setkey (cih, self->value, self->n_value); g_return_val_if_fail (gcry == 0, NULL); return cih; }
static void _cipher_bench (int algo) { const char *algoname; int i; algoname = gcry_cipher_algo_name (algo); bench_print_header (14, algoname); for (i = 0; cipher_modes[i].mode; i++) cipher_bench_one (algo, &cipher_modes[i]); bench_print_footer (14); }
/* Initialize the data encryption key (session key). */ static int init_dek (DEK dek) { int rc=0, mode, i; dek->algo = gcry_cipher_map_name (dek->algoid); mode = gcry_cipher_mode_from_oid (dek->algoid); if (!dek->algo || !mode) { log_error ("unsupported algorithm `%s'\n", dek->algoid); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); } /* Extra check for algorithms we consider to be too weak for encryption, although we support them for decryption. Note that there is another check below discriminating on the key length. */ switch (dek->algo) { case GCRY_CIPHER_DES: case GCRY_CIPHER_RFC2268_40: log_error ("cipher algorithm `%s' not allowed: too weak\n", gcry_cipher_algo_name (dek->algo)); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); default: break; } dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); if (!dek->keylen || dek->keylen > sizeof (dek->key)) return gpg_error (GPG_ERR_BUG); dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo); if (!dek->ivlen || dek->ivlen > sizeof (dek->iv)) return gpg_error (GPG_ERR_BUG); /* Make sure we don't use weak keys. */ if (dek->keylen < 100/8) { log_error ("key length of `%s' too small\n", dek->algoid); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); } rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE); if (rc) { log_error ("failed to create cipher context: %s\n", gpg_strerror (rc)); return rc; } for (i=0; i < 8; i++) { gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen); if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY) break; log_info(_("weak key created - retrying\n") ); } if (rc) { log_error ("failed to set the key: %s\n", gpg_strerror (rc)); gcry_cipher_close (dek->chd); dek->chd = NULL; return rc; } gcry_create_nonce (dek->iv, dek->ivlen); rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen); if (rc) { log_error ("failed to set the IV: %s\n", gpg_strerror (rc)); gcry_cipher_close (dek->chd); dek->chd = NULL; return rc; } return 0; }
gboolean egg_symkey_generate_pbe (int cipher_algo, int hash_algo, const gchar *password, gssize n_password, const guchar *salt, gsize n_salt, int iterations, guchar **key, guchar **iv) { gcry_md_hd_t mdh; gcry_error_t gcry; guchar *digest; guchar *digested; guint i, n_digest; gint needed_iv, needed_key; g_assert (cipher_algo); g_assert (hash_algo); g_return_val_if_fail (iterations >= 1, FALSE); if (!password) n_password = 0; if (n_password == -1) n_password = strlen (password); /* * We only do one pass here. * * The key ends up as the first needed_key bytes of the hash buffer. * The iv ends up as the last needed_iv bytes of the hash buffer. * * The IV may overlap the key (which is stupid) if the wrong pair of * hash/cipher algorithms are chosen. */ n_digest = gcry_md_get_algo_dlen (hash_algo); g_return_val_if_fail (n_digest > 0, FALSE); needed_key = gcry_cipher_get_algo_keylen (cipher_algo); needed_iv = gcry_cipher_get_algo_blklen (cipher_algo); if (needed_iv + needed_key > 16 || needed_iv + needed_key > n_digest) { g_warning ("using PBE symkey generation with %s using an algorithm that needs " "too many bytes of key and/or IV: %s", gcry_cipher_algo_name (hash_algo), gcry_cipher_algo_name (cipher_algo)); return FALSE; } gcry = gcry_md_open (&mdh, hash_algo, 0); if (gcry) { g_warning ("couldn't create '%s' hash context: %s", gcry_md_algo_name (hash_algo), gcry_strerror (gcry)); return FALSE; } digest = egg_secure_alloc (n_digest); g_return_val_if_fail (digest, FALSE); if (key) { *key = egg_secure_alloc (needed_key); g_return_val_if_fail (*key, FALSE); } if (iv) *iv = g_new0 (guchar, needed_iv); if (password) gcry_md_write (mdh, password, n_password); if (salt && n_salt) gcry_md_write (mdh, salt, n_salt); gcry_md_final (mdh); digested = gcry_md_read (mdh, 0); g_return_val_if_fail (digested, FALSE); memcpy (digest, digested, n_digest); for (i = 1; i < iterations; ++i) gcry_md_hash_buffer (hash_algo, digest, digest, n_digest); /* The first x bytes are the key */ if (key) { g_assert (needed_key <= n_digest); memcpy (*key, digest, needed_key); } /* The last 16 - x bytes are the iv */ if (iv) { g_assert (needed_iv <= n_digest && n_digest >= 16); memcpy (*iv, digest + (16 - needed_iv), needed_iv); } egg_secure_free (digest); gcry_md_close (mdh); return TRUE; }
/** * ntfs_fek_import_from_raw */ static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf, unsigned fek_size) { ntfs_fek *fek; u32 key_size, wanted_key_size, gcry_algo; int gcry_mode; gcry_error_t err; ntfs_desx_ctx *ctx; key_size = le32_to_cpup(fek_buf); ntfs_log_debug("key_size 0x%x\n", key_size); if (key_size + 16 > fek_size) { ntfs_log_debug("Invalid FEK. It was probably decrypted with " "the incorrect RSA key."); errno = EINVAL; return NULL; } fek = malloc(((((sizeof(*fek) + 7) & ~7) + key_size + 7) & ~7) + sizeof(gcry_cipher_hd_t)); if (!fek) { errno = ENOMEM; return NULL; } ctx = &fek->desx_ctx; fek->alg_id = *(le32*)(fek_buf + 8); //ntfs_log_debug("alg_id 0x%x\n", le32_to_cpu(fek->alg_id)); fek->key_data = (u8*)fek + ((sizeof(*fek) + 7) & ~7); memcpy(fek->key_data, fek_buf + 16, key_size); fek->des_gcry_cipher_hd_ptr = NULL; *(gcry_cipher_hd_t***)(fek->key_data + ((key_size + 7) & ~7)) = &fek->des_gcry_cipher_hd_ptr; switch (fek->alg_id) { case CALG_DESX: wanted_key_size = 16; gcry_algo = GCRY_CIPHER_DES; gcry_mode = GCRY_CIPHER_MODE_ECB; break; case CALG_3DES: wanted_key_size = 24; gcry_algo = GCRY_CIPHER_3DES; gcry_mode = GCRY_CIPHER_MODE_CBC; break; case CALG_AES_256: wanted_key_size = 32; gcry_algo = GCRY_CIPHER_AES256; gcry_mode = GCRY_CIPHER_MODE_CBC; break; default: wanted_key_size = 8; gcry_algo = GCRY_CIPHER_DES; gcry_mode = GCRY_CIPHER_MODE_CBC; if (fek->alg_id == CALG_DES) ntfs_log_error("DES is not supported at present\n"); else ntfs_log_error("Unknown crypto algorithm 0x%x\n", le32_to_cpu(fek->alg_id)); ntfs_log_error(". Please email %s and say that you saw this " "message. We will then try to implement " "support for this algorithm.\n", NTFS_DEV_LIST); err = EOPNOTSUPP; goto out; } if (key_size != wanted_key_size) { ntfs_log_error("%s key of %u bytes but needed size is %u " "bytes, assuming corrupt or incorrect key. " "Aborting.\n", gcry_cipher_algo_name(gcry_algo), (unsigned)key_size, (unsigned)wanted_key_size); err = EIO; goto out; } err = gcry_cipher_open(&fek->gcry_cipher_hd, gcry_algo, gcry_mode, 0); if (err != GPG_ERR_NO_ERROR) { ntfs_log_error("gcry_cipher_open() failed: %s\n", gcry_strerror(err)); err = EINVAL; goto out; } if (fek->alg_id == CALG_DESX) { err = ntfs_desx_key_expand(fek->key_data, (u32*)ctx->des_key, &ctx->out_whitening, &ctx->in_whitening); if (err == GPG_ERR_NO_ERROR) err = gcry_cipher_setkey(fek->gcry_cipher_hd, ctx->des_key, 8); } else { err = gcry_cipher_setkey(fek->gcry_cipher_hd, fek->key_data, key_size); } if (err != GPG_ERR_NO_ERROR) { ntfs_log_error("gcry_cipher_setkey() failed: %s\n", gcry_strerror(err)); gcry_cipher_close(fek->gcry_cipher_hd); err = EINVAL; goto out; } return fek; out: free(fek); errno = err; return NULL; }
static void cipher_bench ( const char *algoname ) { static int header_printed; int algo; gcry_cipher_hd_t hd; int i; int keylen, blklen; char key[128]; char *outbuf, *buf; char *raw_outbuf, *raw_buf; size_t allocated_buflen, buflen; int repetitions; static struct { int mode; const char *name; int blocked; } modes[] = { { GCRY_CIPHER_MODE_ECB, " ECB/Stream", 1 }, { GCRY_CIPHER_MODE_CBC, " CBC", 1 }, { GCRY_CIPHER_MODE_CFB, " CFB", 0 }, { GCRY_CIPHER_MODE_OFB, " OFB", 0 }, { GCRY_CIPHER_MODE_CTR, " CTR", 0 }, { GCRY_CIPHER_MODE_STREAM, "", 0 }, {0} }; int modeidx; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if ( !gcry_cipher_test_algo (i) ) cipher_bench (gcry_cipher_algo_name (i)); return; } if (large_buffers) { allocated_buflen = 1024 * 100; repetitions = 10; } else { allocated_buflen = 1024; repetitions = 1000; } repetitions *= cipher_repetitions; raw_buf = gcry_xmalloc (allocated_buflen+15); buf = (raw_buf + ((16 - ((size_t)raw_buf & 0x0f)) % buffer_alignment)); outbuf = raw_outbuf = gcry_xmalloc (allocated_buflen+15); outbuf = (raw_outbuf + ((16 - ((size_t)raw_outbuf & 0x0f)) % buffer_alignment)); if (!header_printed) { if (cipher_repetitions != 1) printf ("Running each test %d times.\n", cipher_repetitions); printf ("%-12s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) if (*modes[modeidx].name) printf (" %-15s", modes[modeidx].name ); putchar ('\n'); printf ("%-12s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) if (*modes[modeidx].name) printf (" ---------------" ); putchar ('\n'); header_printed = 1; } algo = gcry_cipher_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname); exit (1); } keylen = gcry_cipher_get_algo_keylen (algo); if (!keylen) { fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", algoname); exit (1); } if ( keylen > sizeof key ) { fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n", algo, keylen ); exit (1); } for (i=0; i < keylen; i++) key[i] = i + (clock () & 0xff); blklen = gcry_cipher_get_algo_blklen (algo); if (!blklen) { fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n", algoname); exit (1); } printf ("%-12s", gcry_cipher_algo_name (algo)); fflush (stdout); for (modeidx=0; modes[modeidx].mode; modeidx++) { if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM) | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM)) continue; for (i=0; i < sizeof buf; i++) buf[i] = i; err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname); exit (1); } if (!cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } buflen = allocated_buflen; if (modes[modeidx].blocked) buflen = (buflen / blklen) * blklen; start_timer (); for (i=err=0; !err && i < repetitions; i++) { if (cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_encrypt failed: %s\n", gpg_strerror (err) ); exit (1); } err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname); exit (1); } if (!cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } start_timer (); for (i=err=0; !err && i < repetitions; i++) { if (cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } err = gcry_cipher_decrypt ( hd, outbuf, buflen, buf, buflen); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_decrypt failed: %s\n", gpg_strerror (err) ); exit (1); } } putchar ('\n'); gcry_free (raw_buf); gcry_free (raw_outbuf); }
static void cipher_bench ( const char *algoname ) { static int header_printed; int algo; gcry_cipher_hd_t hd; int i; int keylen, blklen; char key[128]; char outbuf[1000], buf[1000]; size_t buflen; static struct { int mode; const char *name; int blocked; } modes[] = { { GCRY_CIPHER_MODE_ECB, "ECB", 1 }, { GCRY_CIPHER_MODE_CBC, "CBC", 1 }, { GCRY_CIPHER_MODE_CFB, "CFB", 0 }, { GCRY_CIPHER_MODE_CTR, "CTR", 0 }, { GCRY_CIPHER_MODE_STREAM, "STREAM", 0 }, {0} }; int modeidx; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if ( !gcry_cipher_test_algo (i) ) cipher_bench (gcry_cipher_algo_name (i)); return; } if (!header_printed) { printf ("%-10s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) printf (" %-15s", modes[modeidx].name ); putchar ('\n'); printf ("%-10s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) printf (" ---------------" ); putchar ('\n'); header_printed = 1; } algo = gcry_cipher_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname); exit (1); } keylen = gcry_cipher_get_algo_keylen (algo); if (!keylen) { fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", algoname); exit (1); } if ( keylen > sizeof key ) { fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n", algo, keylen ); exit (1); } for (i=0; i < keylen; i++) key[i] = i + (clock () & 0xff); blklen = gcry_cipher_get_algo_blklen (algo); if (!blklen) { fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n", algoname); exit (1); } printf ("%-10s", gcry_cipher_algo_name (algo)); fflush (stdout); for (modeidx=0; modes[modeidx].mode; modeidx++) { if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM) | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM)) { printf (" " ); continue; } for (i=0; i < sizeof buf; i++) buf[i] = i; err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname); exit (1); } err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } buflen = sizeof buf; if (modes[modeidx].blocked) buflen = (buflen / blklen) * blklen; start_timer (); for (i=err=0; !err && i < 1000; i++) err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_encrypt failed: %s\n", gpg_strerror (err) ); exit (1); } err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname); exit (1); } err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } start_timer (); for (i=err=0; !err && i < 1000; i++) err = gcry_cipher_decrypt ( hd, outbuf, buflen, buf, buflen); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_decrypt failed: %s\n", gpg_strerror (err) ); exit (1); } } putchar ('\n'); }