2N/A/* cipher.c - cipher dispatcher
2N/A * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
2N/A * 2005, 2007, 2008 Free Software Foundation, Inc.
2N/A *
2N/A * This file is part of Libgcrypt.
2N/A *
2N/A * Libgcrypt is free software; you can redistribute it and/or modify
2N/A * it under the terms of the GNU Lesser general Public License as
2N/A * published by the Free Software Foundation; either version 2.1 of
2N/A * the License, or (at your option) any later version.
2N/A *
2N/A * Libgcrypt is distributed in the hope that it will be useful,
2N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A * GNU Lesser General Public License for more details.
2N/A *
2N/A * You should have received a copy of the GNU Lesser General Public
2N/A * License along with this program; if not, see <http://www.gnu.org/licenses/>.
2N/A */
2N/A
2N/A#include <config.h>
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <errno.h>
2N/A
2N/A#include "g10lib.h"
2N/A#include "cipher.h"
2N/A#include "ath.h"
2N/A
2N/A#define MAX_BLOCKSIZE 16
2N/A#define TABLE_SIZE 14
2N/A#define CTX_MAGIC_NORMAL 0x24091964
2N/A#define CTX_MAGIC_SECURE 0x46919042
2N/A
2N/A#undef NEED_16BYTE_ALIGNED_CONTEXT
2N/A#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
2N/A#define NEED_16BYTE_ALIGNED_CONTEXT 1
2N/A#endif
2N/A
2N/A/* A dummy extraspec so that we do not need to tests the extraspec
2N/A field from the module specification against NULL and instead
2N/A directly test the respective fields of extraspecs. */
2N/Astatic cipher_extra_spec_t dummy_extra_spec;
2N/A
2N/A/* This is the list of the default ciphers, which are included in
2N/A libgcrypt. */
2N/Astatic struct cipher_table_entry
2N/A{
2N/A gcry_cipher_spec_t *cipher;
2N/A cipher_extra_spec_t *extraspec;
2N/A unsigned int algorithm;
2N/A int fips_allowed;
2N/A} cipher_table[] =
2N/A {
2N/A#if USE_BLOWFISH
2N/A { &_gcry_cipher_spec_blowfish,
2N/A &dummy_extra_spec, GCRY_CIPHER_BLOWFISH },
2N/A#endif
2N/A#if USE_DES
2N/A { &_gcry_cipher_spec_des,
2N/A &dummy_extra_spec, GCRY_CIPHER_DES },
2N/A { &_gcry_cipher_spec_tripledes,
2N/A &_gcry_cipher_extraspec_tripledes, GCRY_CIPHER_3DES, 1 },
2N/A#endif
2N/A#if USE_ARCFOUR
2N/A { &_gcry_cipher_spec_arcfour,
2N/A &dummy_extra_spec, GCRY_CIPHER_ARCFOUR },
2N/A#endif
2N/A#if USE_CAST5
2N/A { &_gcry_cipher_spec_cast5,
2N/A &dummy_extra_spec, GCRY_CIPHER_CAST5 },
2N/A#endif
2N/A#if USE_AES
2N/A { &_gcry_cipher_spec_aes,
2N/A &_gcry_cipher_extraspec_aes, GCRY_CIPHER_AES, 1 },
2N/A { &_gcry_cipher_spec_aes192,
2N/A &_gcry_cipher_extraspec_aes192, GCRY_CIPHER_AES192, 1 },
2N/A { &_gcry_cipher_spec_aes256,
2N/A &_gcry_cipher_extraspec_aes256, GCRY_CIPHER_AES256, 1 },
2N/A#endif
2N/A#if USE_TWOFISH
2N/A { &_gcry_cipher_spec_twofish,
2N/A &dummy_extra_spec, GCRY_CIPHER_TWOFISH },
2N/A { &_gcry_cipher_spec_twofish128,
2N/A &dummy_extra_spec, GCRY_CIPHER_TWOFISH128 },
2N/A#endif
2N/A#if USE_SERPENT
2N/A { &_gcry_cipher_spec_serpent128,
2N/A &dummy_extra_spec, GCRY_CIPHER_SERPENT128 },
2N/A { &_gcry_cipher_spec_serpent192,
2N/A &dummy_extra_spec, GCRY_CIPHER_SERPENT192 },
2N/A { &_gcry_cipher_spec_serpent256,
2N/A &dummy_extra_spec, GCRY_CIPHER_SERPENT256 },
2N/A#endif
2N/A#if USE_RFC2268
2N/A { &_gcry_cipher_spec_rfc2268_40,
2N/A &dummy_extra_spec, GCRY_CIPHER_RFC2268_40 },
2N/A#endif
2N/A#if USE_SEED
2N/A { &_gcry_cipher_spec_seed,
2N/A &dummy_extra_spec, GCRY_CIPHER_SEED },
2N/A#endif
2N/A#if USE_CAMELLIA
2N/A { &_gcry_cipher_spec_camellia128,
2N/A &dummy_extra_spec, GCRY_CIPHER_CAMELLIA128 },
2N/A { &_gcry_cipher_spec_camellia192,
2N/A &dummy_extra_spec, GCRY_CIPHER_CAMELLIA192 },
2N/A { &_gcry_cipher_spec_camellia256,
2N/A &dummy_extra_spec, GCRY_CIPHER_CAMELLIA256 },
2N/A#endif
2N/A { NULL }
2N/A };
2N/A
2N/A/* List of registered ciphers. */
2N/Astatic gcry_module_t ciphers_registered;
2N/A
2N/A/* This is the lock protecting CIPHERS_REGISTERED. */
2N/Astatic ath_mutex_t ciphers_registered_lock = ATH_MUTEX_INITIALIZER;
2N/A
2N/A/* Flag to check wether the default ciphers have already been
2N/A registered. */
2N/Astatic int default_ciphers_registered;
2N/A
2N/A/* Convenient macro for registering the default ciphers. */
2N/A#define REGISTER_DEFAULT_CIPHERS \
2N/A do \
2N/A { \
2N/A ath_mutex_lock (&ciphers_registered_lock); \
2N/A if (! default_ciphers_registered) \
2N/A { \
2N/A cipher_register_default (); \
2N/A default_ciphers_registered = 1; \
2N/A } \
2N/A ath_mutex_unlock (&ciphers_registered_lock); \
2N/A } \
2N/A while (0)
2N/A
2N/A
2N/A/* A VIA processor with the Padlock engine requires an alignment of
2N/A most data on a 16 byte boundary. Because we trick out the compiler
2N/A while allocating the context, the align attribute as used in
2N/A rijndael.c does not work on its own. Thus we need to make sure
2N/A that the entire context structure is a aligned on that boundary.
2N/A We achieve this by defining a new type and use that instead of our
2N/A usual alignment type. */
2N/Atypedef union
2N/A{
2N/A PROPERLY_ALIGNED_TYPE foo;
2N/A#ifdef NEED_16BYTE_ALIGNED_CONTEXT
2N/A char bar[16] __attribute__ ((aligned (16)));
2N/A#endif
2N/A char c[1];
2N/A} cipher_context_alignment_t;
2N/A
2N/A
2N/A/* The handle structure. */
2N/Astruct gcry_cipher_handle
2N/A{
2N/A int magic;
2N/A size_t actual_handle_size; /* Allocated size of this handle. */
2N/A size_t handle_offset; /* Offset to the malloced block. */
2N/A gcry_cipher_spec_t *cipher;
2N/A cipher_extra_spec_t *extraspec;
2N/A gcry_module_t module;
2N/A
2N/A /* The algorithm id. This is a hack required because the module
2N/A interface does not easily allow to retrieve this value. */
2N/A int algo;
2N/A
2N/A /* A structure with function pointers for bulk operations. Due to
2N/A limitations of the module system (we don't want to change the
2N/A API) we need to keep these function pointers here. The cipher
2N/A open function intializes them and the actual encryption routines
2N/A use them if they are not NULL. */
2N/A struct {
2N/A void (*cfb_enc)(void *context, unsigned char *iv,
2N/A void *outbuf_arg, const void *inbuf_arg,
2N/A unsigned int nblocks);
2N/A void (*cfb_dec)(void *context, unsigned char *iv,
2N/A void *outbuf_arg, const void *inbuf_arg,
2N/A unsigned int nblocks);
2N/A void (*cbc_enc)(void *context, unsigned char *iv,
2N/A void *outbuf_arg, const void *inbuf_arg,
2N/A unsigned int nblocks, int cbc_mac);
2N/A void (*cbc_dec)(void *context, unsigned char *iv,
2N/A void *outbuf_arg, const void *inbuf_arg,
2N/A unsigned int nblocks);
2N/A } bulk;
2N/A
2N/A
2N/A int mode;
2N/A unsigned int flags;
2N/A
2N/A /* The initialization vector. To help code optimization we make
2N/A sure that it is aligned on an unsigned long and u32 boundary. */
2N/A union {
2N/A unsigned long dummy_iv;
2N/A u32 dummy_u32_iv;
2N/A unsigned char iv[MAX_BLOCKSIZE];
2N/A } u_iv;
2N/A
2N/A unsigned char lastiv[MAX_BLOCKSIZE];
2N/A int unused; /* Number of unused bytes in the IV. */
2N/A
2N/A unsigned char ctr[MAX_BLOCKSIZE]; /* For Counter (CTR) mode. */
2N/A
2N/A
2N/A /* What follows are two contexts of the cipher in use. The first
2N/A one needs to be aligned well enough for the cipher operation
2N/A whereas the second one is a copy created by cipher_setkey and
2N/A used by cipher_reset. That second copy has no need for proper
2N/A aligment because it is only accessed by memcpy. */
2N/A cipher_context_alignment_t context;
2N/A};
2N/A
2N/A
2N/A
2N/A/* These dummy functions are used in case a cipher implementation
2N/A refuses to provide it's own functions. */
2N/A
2N/Astatic gcry_err_code_t
2N/Adummy_setkey (void *c, const unsigned char *key, unsigned int keylen)
2N/A{
2N/A (void)c;
2N/A (void)key;
2N/A (void)keylen;
2N/A return GPG_ERR_NO_ERROR;
2N/A}
2N/A
2N/Astatic void
2N/Adummy_encrypt_block (void *c,
2N/A unsigned char *outbuf, const unsigned char *inbuf)
2N/A{
2N/A (void)c;
2N/A (void)outbuf;
2N/A (void)inbuf;
2N/A BUG();
2N/A}
2N/A
2N/Astatic void
2N/Adummy_decrypt_block (void *c,
2N/A unsigned char *outbuf, const unsigned char *inbuf)
2N/A{
2N/A (void)c;
2N/A (void)outbuf;
2N/A (void)inbuf;
2N/A BUG();
2N/A}
2N/A
2N/Astatic void
2N/Adummy_encrypt_stream (void *c,
2N/A unsigned char *outbuf, const unsigned char *inbuf,
2N/A unsigned int n)
2N/A{
2N/A (void)c;
2N/A (void)outbuf;
2N/A (void)inbuf;
2N/A (void)n;
2N/A BUG();
2N/A}
2N/A
2N/Astatic void
2N/Adummy_decrypt_stream (void *c,
2N/A unsigned char *outbuf, const unsigned char *inbuf,
2N/A unsigned int n)
2N/A{
2N/A (void)c;
2N/A (void)outbuf;
2N/A (void)inbuf;
2N/A (void)n;
2N/A BUG();
2N/A}
2N/A
2N/A
2N/A/* Internal function. Register all the ciphers included in
2N/A CIPHER_TABLE. Note, that this function gets only used by the macro
2N/A REGISTER_DEFAULT_CIPHERS which protects it using a mutex. */
2N/Astatic void
2N/Acipher_register_default (void)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A int i;
2N/A
2N/A for (i = 0; !err && cipher_table[i].cipher; i++)
2N/A {
2N/A if (! cipher_table[i].cipher->setkey)
2N/A cipher_table[i].cipher->setkey = dummy_setkey;
2N/A if (! cipher_table[i].cipher->encrypt)
2N/A cipher_table[i].cipher->encrypt = dummy_encrypt_block;
2N/A if (! cipher_table[i].cipher->decrypt)
2N/A cipher_table[i].cipher->decrypt = dummy_decrypt_block;
2N/A if (! cipher_table[i].cipher->stencrypt)
2N/A cipher_table[i].cipher->stencrypt = dummy_encrypt_stream;
2N/A if (! cipher_table[i].cipher->stdecrypt)
2N/A cipher_table[i].cipher->stdecrypt = dummy_decrypt_stream;
2N/A
2N/A if ( fips_mode () && !cipher_table[i].fips_allowed )
2N/A continue;
2N/A
2N/A err = _gcry_module_add (&ciphers_registered,
2N/A cipher_table[i].algorithm,
2N/A (void *) cipher_table[i].cipher,
2N/A (void *) cipher_table[i].extraspec,
2N/A NULL);
2N/A }
2N/A
2N/A if (err)
2N/A BUG ();
2N/A}
2N/A
2N/A/* Internal callback function. Used via _gcry_module_lookup. */
2N/Astatic int
2N/Agcry_cipher_lookup_func_name (void *spec, void *data)
2N/A{
2N/A gcry_cipher_spec_t *cipher = (gcry_cipher_spec_t *) spec;
2N/A char *name = (char *) data;
2N/A const char **aliases = cipher->aliases;
2N/A int i, ret = ! stricmp (name, cipher->name);
2N/A
2N/A if (aliases)
2N/A for (i = 0; aliases[i] && (! ret); i++)
2N/A ret = ! stricmp (name, aliases[i]);
2N/A
2N/A return ret;
2N/A}
2N/A
2N/A/* Internal callback function. Used via _gcry_module_lookup. */
2N/Astatic int
2N/Agcry_cipher_lookup_func_oid (void *spec, void *data)
2N/A{
2N/A gcry_cipher_spec_t *cipher = (gcry_cipher_spec_t *) spec;
2N/A char *oid = (char *) data;
2N/A gcry_cipher_oid_spec_t *oid_specs = cipher->oids;
2N/A int ret = 0, i;
2N/A
2N/A if (oid_specs)
2N/A for (i = 0; oid_specs[i].oid && (! ret); i++)
2N/A if (! stricmp (oid, oid_specs[i].oid))
2N/A ret = 1;
2N/A
2N/A return ret;
2N/A}
2N/A
2N/A/* Internal function. Lookup a cipher entry by it's name. */
2N/Astatic gcry_module_t
2N/Agcry_cipher_lookup_name (const char *name)
2N/A{
2N/A gcry_module_t cipher;
2N/A
2N/A cipher = _gcry_module_lookup (ciphers_registered, (void *) name,
2N/A gcry_cipher_lookup_func_name);
2N/A
2N/A return cipher;
2N/A}
2N/A
2N/A/* Internal function. Lookup a cipher entry by it's oid. */
2N/Astatic gcry_module_t
2N/Agcry_cipher_lookup_oid (const char *oid)
2N/A{
2N/A gcry_module_t cipher;
2N/A
2N/A cipher = _gcry_module_lookup (ciphers_registered, (void *) oid,
2N/A gcry_cipher_lookup_func_oid);
2N/A
2N/A return cipher;
2N/A}
2N/A
2N/A/* Register a new cipher module whose specification can be found in
2N/A CIPHER. On success, a new algorithm ID is stored in ALGORITHM_ID
2N/A and a pointer representhing this module is stored in MODULE. */
2N/Agcry_error_t
2N/A_gcry_cipher_register (gcry_cipher_spec_t *cipher,
2N/A cipher_extra_spec_t *extraspec,
2N/A int *algorithm_id,
2N/A gcry_module_t *module)
2N/A{
2N/A gcry_err_code_t err = 0;
2N/A gcry_module_t mod;
2N/A
2N/A /* We do not support module loading in fips mode. */
2N/A if (fips_mode ())
2N/A return gpg_error (GPG_ERR_NOT_SUPPORTED);
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A err = _gcry_module_add (&ciphers_registered, 0,
2N/A (void *)cipher,
2N/A (void *)(extraspec? extraspec : &dummy_extra_spec),
2N/A &mod);
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A if (! err)
2N/A {
2N/A *module = mod;
2N/A *algorithm_id = mod->mod_id;
2N/A }
2N/A
2N/A return gcry_error (err);
2N/A}
2N/A
2N/A/* Unregister the cipher identified by MODULE, which must have been
2N/A registered with gcry_cipher_register. */
2N/Avoid
2N/Agcry_cipher_unregister (gcry_module_t module)
2N/A{
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A _gcry_module_release (module);
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A}
2N/A
2N/A/* Locate the OID in the oid table and return the index or -1 when not
2N/A found. An opitonal "oid." or "OID." prefix in OID is ignored, the
2N/A OID is expected to be in standard IETF dotted notation. The
2N/A internal algorithm number is returned in ALGORITHM unless it
2N/A ispassed as NULL. A pointer to the specification of the module
2N/A implementing this algorithm is return in OID_SPEC unless passed as
2N/A NULL.*/
2N/Astatic int
2N/Asearch_oid (const char *oid, int *algorithm, gcry_cipher_oid_spec_t *oid_spec)
2N/A{
2N/A gcry_module_t module;
2N/A int ret = 0;
2N/A
2N/A if (oid && ((! strncmp (oid, "oid.", 4))
2N/A || (! strncmp (oid, "OID.", 4))))
2N/A oid += 4;
2N/A
2N/A module = gcry_cipher_lookup_oid (oid);
2N/A if (module)
2N/A {
2N/A gcry_cipher_spec_t *cipher = module->spec;
2N/A int i;
2N/A
2N/A for (i = 0; cipher->oids[i].oid && !ret; i++)
2N/A if (! stricmp (oid, cipher->oids[i].oid))
2N/A {
2N/A if (algorithm)
2N/A *algorithm = module->mod_id;
2N/A if (oid_spec)
2N/A *oid_spec = cipher->oids[i];
2N/A ret = 1;
2N/A }
2N/A _gcry_module_release (module);
2N/A }
2N/A
2N/A return ret;
2N/A}
2N/A
2N/A/* Map STRING to the cipher algorithm identifier. Returns the
2N/A algorithm ID of the cipher for the given name or 0 if the name is
2N/A not known. It is valid to pass NULL for STRING which results in a
2N/A return value of 0. */
2N/Aint
2N/Agcry_cipher_map_name (const char *string)
2N/A{
2N/A gcry_module_t cipher;
2N/A int ret, algorithm = 0;
2N/A
2N/A if (! string)
2N/A return 0;
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A /* If the string starts with a digit (optionally prefixed with
2N/A either "OID." or "oid."), we first look into our table of ASN.1
2N/A object identifiers to figure out the algorithm */
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A
2N/A ret = search_oid (string, &algorithm, NULL);
2N/A if (! ret)
2N/A {
2N/A cipher = gcry_cipher_lookup_name (string);
2N/A if (cipher)
2N/A {
2N/A algorithm = cipher->mod_id;
2N/A _gcry_module_release (cipher);
2N/A }
2N/A }
2N/A
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A return algorithm;
2N/A}
2N/A
2N/A
2N/A/* Given a STRING with an OID in dotted decimal notation, this
2N/A function returns the cipher mode (GCRY_CIPHER_MODE_*) associated
2N/A with that OID or 0 if no mode is known. Passing NULL for string
2N/A yields a return value of 0. */
2N/Aint
2N/Agcry_cipher_mode_from_oid (const char *string)
2N/A{
2N/A gcry_cipher_oid_spec_t oid_spec;
2N/A int ret = 0, mode = 0;
2N/A
2N/A if (!string)
2N/A return 0;
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A ret = search_oid (string, NULL, &oid_spec);
2N/A if (ret)
2N/A mode = oid_spec.mode;
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A return mode;
2N/A}
2N/A
2N/A
2N/A/* Map the cipher algorithm whose ID is contained in ALGORITHM to a
2N/A string representation of the algorithm name. For unknown algorithm
2N/A IDs this function returns "?". */
2N/Astatic const char *
2N/Acipher_algo_to_string (int algorithm)
2N/A{
2N/A gcry_module_t cipher;
2N/A const char *name;
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
2N/A if (cipher)
2N/A {
2N/A name = ((gcry_cipher_spec_t *) cipher->spec)->name;
2N/A _gcry_module_release (cipher);
2N/A }
2N/A else
2N/A name = "?";
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A return name;
2N/A}
2N/A
2N/A/* Map the cipher algorithm identifier ALGORITHM to a string
2N/A representing this algorithm. This string is the default name as
2N/A used by Libgcrypt. An pointer to an empty string is returned for
2N/A an unknown algorithm. NULL is never returned. */
2N/Aconst char *
2N/Agcry_cipher_algo_name (int algorithm)
2N/A{
2N/A return cipher_algo_to_string (algorithm);
2N/A}
2N/A
2N/A
2N/A/* Flag the cipher algorithm with the identifier ALGORITHM as
2N/A disabled. There is no error return, the function does nothing for
2N/A unknown algorithms. Disabled algorithms are vitually not available
2N/A in Libgcrypt. */
2N/Astatic void
2N/Adisable_cipher_algo (int algorithm)
2N/A{
2N/A gcry_module_t cipher;
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
2N/A if (cipher)
2N/A {
2N/A if (! (cipher->flags & FLAG_MODULE_DISABLED))
2N/A cipher->flags |= FLAG_MODULE_DISABLED;
2N/A _gcry_module_release (cipher);
2N/A }
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A}
2N/A
2N/A
2N/A/* Return 0 if the cipher algorithm with identifier ALGORITHM is
2N/A available. Returns a basic error code value if it is not
2N/A available. */
2N/Astatic gcry_err_code_t
2N/Acheck_cipher_algo (int algorithm)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A gcry_module_t cipher;
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
2N/A if (cipher)
2N/A {
2N/A if (cipher->flags & FLAG_MODULE_DISABLED)
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A _gcry_module_release (cipher);
2N/A }
2N/A else
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A return err;
2N/A}
2N/A
2N/A
2N/A/* Return the standard length of the key for the cipher algorithm with
2N/A the identifier ALGORITHM. This function expects a valid algorithm
2N/A and will abort if the algorithm is not available or the length of
2N/A the key is not known. */
2N/Astatic unsigned int
2N/Acipher_get_keylen (int algorithm)
2N/A{
2N/A gcry_module_t cipher;
2N/A unsigned len = 0;
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
2N/A if (cipher)
2N/A {
2N/A len = ((gcry_cipher_spec_t *) cipher->spec)->keylen;
2N/A if (!len)
2N/A log_bug ("cipher %d w/o key length\n", algorithm);
2N/A _gcry_module_release (cipher);
2N/A }
2N/A else
2N/A log_bug ("cipher %d not found\n", algorithm);
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A return len;
2N/A}
2N/A
2N/A/* Return the block length of the cipher algorithm with the identifier
2N/A ALGORITHM. This function expects a valid algorithm and will abort
2N/A if the algorithm is not available or the length of the key is not
2N/A known. */
2N/Astatic unsigned int
2N/Acipher_get_blocksize (int algorithm)
2N/A{
2N/A gcry_module_t cipher;
2N/A unsigned len = 0;
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
2N/A if (cipher)
2N/A {
2N/A len = ((gcry_cipher_spec_t *) cipher->spec)->blocksize;
2N/A if (! len)
2N/A log_bug ("cipher %d w/o blocksize\n", algorithm);
2N/A _gcry_module_release (cipher);
2N/A }
2N/A else
2N/A log_bug ("cipher %d not found\n", algorithm);
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A return len;
2N/A}
2N/A
2N/A
2N/A/*
2N/A Open a cipher handle for use with cipher algorithm ALGORITHM, using
2N/A the cipher mode MODE (one of the GCRY_CIPHER_MODE_*) and return a
2N/A handle in HANDLE. Put NULL into HANDLE and return an error code if
2N/A something goes wrong. FLAGS may be used to modify the
2N/A operation. The defined flags are:
2N/A
2N/A GCRY_CIPHER_SECURE: allocate all internal buffers in secure memory.
2N/A GCRY_CIPHER_ENABLE_SYNC: Enable the sync operation as used in OpenPGP.
2N/A GCRY_CIPHER_CBC_CTS: Enable CTS mode.
2N/A GCRY_CIPHER_CBC_MAC: Enable MAC mode.
2N/A
2N/A Values for these flags may be combined using OR.
2N/A */
2N/Agcry_error_t
2N/Agcry_cipher_open (gcry_cipher_hd_t *handle,
2N/A int algo, int mode, unsigned int flags)
2N/A{
2N/A int secure = (flags & GCRY_CIPHER_SECURE);
2N/A gcry_cipher_spec_t *cipher = NULL;
2N/A cipher_extra_spec_t *extraspec = NULL;
2N/A gcry_module_t module = NULL;
2N/A gcry_cipher_hd_t h = NULL;
2N/A gcry_err_code_t err = 0;
2N/A
2N/A /* If the application missed to call the random poll function, we do
2N/A it here to ensure that it is used once in a while. */
2N/A _gcry_fast_random_poll ();
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A /* Fetch the according module and check wether the cipher is marked
2N/A available for use. */
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A module = _gcry_module_lookup_id (ciphers_registered, algo);
2N/A if (module)
2N/A {
2N/A /* Found module. */
2N/A
2N/A if (module->flags & FLAG_MODULE_DISABLED)
2N/A {
2N/A /* Not available for use. */
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A _gcry_module_release (module);
2N/A }
2N/A else
2N/A {
2N/A cipher = (gcry_cipher_spec_t *) module->spec;
2N/A extraspec = module->extraspec;
2N/A }
2N/A }
2N/A else
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A /* check flags */
2N/A if ((! err)
2N/A && ((flags & ~(0
2N/A | GCRY_CIPHER_SECURE
2N/A | GCRY_CIPHER_ENABLE_SYNC
2N/A | GCRY_CIPHER_CBC_CTS
2N/A | GCRY_CIPHER_CBC_MAC))
2N/A || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)))
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A
2N/A /* check that a valid mode has been requested */
2N/A if (! err)
2N/A switch (mode)
2N/A {
2N/A case GCRY_CIPHER_MODE_ECB:
2N/A case GCRY_CIPHER_MODE_CBC:
2N/A case GCRY_CIPHER_MODE_CFB:
2N/A case GCRY_CIPHER_MODE_OFB:
2N/A case GCRY_CIPHER_MODE_CTR:
2N/A if ((cipher->encrypt == dummy_encrypt_block)
2N/A || (cipher->decrypt == dummy_decrypt_block))
2N/A err = GPG_ERR_INV_CIPHER_MODE;
2N/A break;
2N/A
2N/A case GCRY_CIPHER_MODE_STREAM:
2N/A if ((cipher->stencrypt == dummy_encrypt_stream)
2N/A || (cipher->stdecrypt == dummy_decrypt_stream))
2N/A err = GPG_ERR_INV_CIPHER_MODE;
2N/A break;
2N/A
2N/A case GCRY_CIPHER_MODE_NONE:
2N/A /* This mode may be used for debugging. It copies the main
2N/A text verbatim to the ciphertext. We do not allow this in
2N/A fips mode or if no debug flag has been set. */
2N/A if (fips_mode () || !_gcry_get_debug_flag (0))
2N/A err = GPG_ERR_INV_CIPHER_MODE;
2N/A break;
2N/A
2N/A default:
2N/A err = GPG_ERR_INV_CIPHER_MODE;
2N/A }
2N/A
2N/A /* Perform selftest here and mark this with a flag in cipher_table?
2N/A No, we should not do this as it takes too long. Further it does
2N/A not make sense to exclude algorithms with failing selftests at
2N/A runtime: If a selftest fails there is something seriously wrong
2N/A with the system and thus we better die immediately. */
2N/A
2N/A if (! err)
2N/A {
2N/A size_t size = (sizeof (*h)
2N/A + 2 * cipher->contextsize
2N/A - sizeof (cipher_context_alignment_t)
2N/A#ifdef NEED_16BYTE_ALIGNED_CONTEXT
2N/A + 15 /* Space for leading alignment gap. */
2N/A#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
2N/A );
2N/A
2N/A if (secure)
2N/A h = gcry_calloc_secure (1, size);
2N/A else
2N/A h = gcry_calloc (1, size);
2N/A
2N/A if (! h)
2N/A err = gpg_err_code_from_errno (errno);
2N/A else
2N/A {
2N/A size_t off = 0;
2N/A
2N/A#ifdef NEED_16BYTE_ALIGNED_CONTEXT
2N/A if ( ((unsigned long)h & 0x0f) )
2N/A {
2N/A /* The malloced block is not aligned on a 16 byte
2N/A boundary. Correct for this. */
2N/A off = 16 - ((unsigned long)h & 0x0f);
2N/A h = (void*)((char*)h + off);
2N/A }
2N/A#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
2N/A
2N/A h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
2N/A h->actual_handle_size = size - off;
2N/A h->handle_offset = off;
2N/A h->cipher = cipher;
2N/A h->extraspec = extraspec;
2N/A h->module = module;
2N/A h->algo = algo;
2N/A h->mode = mode;
2N/A h->flags = flags;
2N/A
2N/A /* Setup bulk encryption routines. */
2N/A switch (algo)
2N/A {
2N/A#ifdef USE_AES
2N/A case GCRY_CIPHER_AES128:
2N/A case GCRY_CIPHER_AES192:
2N/A case GCRY_CIPHER_AES256:
2N/A h->bulk.cfb_enc = _gcry_aes_cfb_enc;
2N/A h->bulk.cfb_dec = _gcry_aes_cfb_dec;
2N/A h->bulk.cbc_enc = _gcry_aes_cbc_enc;
2N/A h->bulk.cbc_dec = _gcry_aes_cbc_dec;
2N/A break;
2N/A#endif /*USE_AES*/
2N/A
2N/A default:
2N/A break;
2N/A }
2N/A }
2N/A }
2N/A
2N/A /* Done. */
2N/A
2N/A if (err)
2N/A {
2N/A if (module)
2N/A {
2N/A /* Release module. */
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A _gcry_module_release (module);
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A }
2N/A }
2N/A
2N/A *handle = err ? NULL : h;
2N/A
2N/A return gcry_error (err);
2N/A}
2N/A
2N/A
2N/A/* Release all resources associated with the cipher handle H. H may be
2N/A NULL in which case this is a no-operation. */
2N/Avoid
2N/Agcry_cipher_close (gcry_cipher_hd_t h)
2N/A{
2N/A size_t off;
2N/A
2N/A if (!h)
2N/A return;
2N/A
2N/A if ((h->magic != CTX_MAGIC_SECURE)
2N/A && (h->magic != CTX_MAGIC_NORMAL))
2N/A _gcry_fatal_error(GPG_ERR_INTERNAL,
2N/A "gcry_cipher_close: already closed/invalid handle");
2N/A else
2N/A h->magic = 0;
2N/A
2N/A /* Release module. */
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A _gcry_module_release (h->module);
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A /* We always want to wipe out the memory even when the context has
2N/A been allocated in secure memory. The user might have disabled
2N/A secure memory or is using his own implementation which does not
2N/A do the wiping. To accomplish this we need to keep track of the
2N/A actual size of this structure because we have no way to known
2N/A how large the allocated area was when using a standard malloc. */
2N/A off = h->handle_offset;
2N/A wipememory (h, h->actual_handle_size);
2N/A
2N/A gcry_free ((char*)h - off);
2N/A}
2N/A
2N/A
2N/A/* Set the key to be used for the encryption context C to KEY with
2N/A length KEYLEN. The length should match the required length. */
2N/Astatic gcry_error_t
2N/Acipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen)
2N/A{
2N/A gcry_err_code_t ret;
2N/A
2N/A ret = (*c->cipher->setkey) (&c->context.c, key, keylen);
2N/A if (!ret)
2N/A {
2N/A /* Duplicate initial context. */
2N/A memcpy ((void *) ((char *) &c->context.c + c->cipher->contextsize),
2N/A (void *) &c->context.c,
2N/A c->cipher->contextsize);
2N/A }
2N/A
2N/A return gcry_error (ret);
2N/A}
2N/A
2N/A
2N/A/* Set the IV to be used for the encryption context C to IV with
2N/A length IVLEN. The length should match the required length. */
2N/Astatic void
2N/Acipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen )
2N/A{
2N/A memset (c->u_iv.iv, 0, c->cipher->blocksize);
2N/A if (iv)
2N/A {
2N/A if (ivlen != c->cipher->blocksize)
2N/A {
2N/A log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
2N/A ivlen, (unsigned int)c->cipher->blocksize);
2N/A fips_signal_error ("IV length does not match blocklength");
2N/A }
2N/A if (ivlen > c->cipher->blocksize)
2N/A ivlen = c->cipher->blocksize;
2N/A memcpy (c->u_iv.iv, iv, ivlen);
2N/A }
2N/A c->unused = 0;
2N/A}
2N/A
2N/A
2N/A/* Reset the cipher context to the initial context. This is basically
2N/A the same as an release followed by a new. */
2N/Astatic void
2N/Acipher_reset (gcry_cipher_hd_t c)
2N/A{
2N/A memcpy (&c->context.c,
2N/A (char *) &c->context.c + c->cipher->contextsize,
2N/A c->cipher->contextsize);
2N/A memset (c->u_iv.iv, 0, c->cipher->blocksize);
2N/A memset (c->lastiv, 0, c->cipher->blocksize);
2N/A memset (c->ctr, 0, c->cipher->blocksize);
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Ado_ecb_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
2N/A unsigned int nblocks )
2N/A{
2N/A unsigned int n;
2N/A
2N/A for (n=0; n < nblocks; n++ )
2N/A {
2N/A c->cipher->encrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
2N/A inbuf += c->cipher->blocksize;
2N/A outbuf += c->cipher->blocksize;
2N/A }
2N/A}
2N/A
2N/Astatic void
2N/Ado_ecb_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
2N/A unsigned int nblocks )
2N/A{
2N/A unsigned int n;
2N/A
2N/A for (n=0; n < nblocks; n++ )
2N/A {
2N/A c->cipher->decrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
2N/A inbuf += c->cipher->blocksize;
2N/A outbuf += c->cipher->blocksize;
2N/A }
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Ado_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
2N/A const unsigned char *inbuf, unsigned int nbytes )
2N/A{
2N/A unsigned int n;
2N/A unsigned char *ivp;
2N/A int i;
2N/A size_t blocksize = c->cipher->blocksize;
2N/A unsigned nblocks = nbytes / blocksize;
2N/A
2N/A if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
2N/A {
2N/A if ((nbytes % blocksize) == 0)
2N/A nblocks--;
2N/A }
2N/A
2N/A if (c->bulk.cbc_enc)
2N/A {
2N/A c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks,
2N/A (c->flags & GCRY_CIPHER_CBC_MAC));
2N/A inbuf += nblocks * blocksize;
2N/A if (!(c->flags & GCRY_CIPHER_CBC_MAC))
2N/A outbuf += nblocks * blocksize;
2N/A }
2N/A else
2N/A {
2N/A for (n=0; n < nblocks; n++ )
2N/A {
2N/A for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
2N/A outbuf[i] = inbuf[i] ^ *ivp++;
2N/A c->cipher->encrypt ( &c->context.c, outbuf, outbuf );
2N/A memcpy (c->u_iv.iv, outbuf, blocksize );
2N/A inbuf += blocksize;
2N/A if (!(c->flags & GCRY_CIPHER_CBC_MAC))
2N/A outbuf += blocksize;
2N/A }
2N/A }
2N/A
2N/A if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
2N/A {
2N/A /* We have to be careful here, since outbuf might be equal to
2N/A inbuf. */
2N/A int restbytes;
2N/A unsigned char b;
2N/A
2N/A if ((nbytes % blocksize) == 0)
2N/A restbytes = blocksize;
2N/A else
2N/A restbytes = nbytes % blocksize;
2N/A
2N/A outbuf -= blocksize;
2N/A for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++)
2N/A {
2N/A b = inbuf[i];
2N/A outbuf[blocksize + i] = outbuf[i];
2N/A outbuf[i] = b ^ *ivp++;
2N/A }
2N/A for (; i < blocksize; i++)
2N/A outbuf[i] = 0 ^ *ivp++;
2N/A
2N/A c->cipher->encrypt (&c->context.c, outbuf, outbuf);
2N/A memcpy (c->u_iv.iv, outbuf, blocksize);
2N/A }
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Ado_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
2N/A const unsigned char *inbuf, unsigned int nbytes)
2N/A{
2N/A unsigned int n;
2N/A unsigned char *ivp;
2N/A int i;
2N/A size_t blocksize = c->cipher->blocksize;
2N/A unsigned int nblocks = nbytes / blocksize;
2N/A
2N/A if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
2N/A {
2N/A nblocks--;
2N/A if ((nbytes % blocksize) == 0)
2N/A nblocks--;
2N/A memcpy (c->lastiv, c->u_iv.iv, blocksize);
2N/A }
2N/A
2N/A if (c->bulk.cbc_dec)
2N/A {
2N/A c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
2N/A inbuf += nblocks * blocksize;
2N/A outbuf += nblocks * blocksize;
2N/A }
2N/A else
2N/A {
2N/A for (n=0; n < nblocks; n++ )
2N/A {
2N/A /* Because outbuf and inbuf might be the same, we have to
2N/A * save the original ciphertext block. We use LASTIV for
2N/A * this here because it is not used otherwise. */
2N/A memcpy (c->lastiv, inbuf, blocksize);
2N/A c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
2N/A for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
2N/A outbuf[i] ^= *ivp++;
2N/A memcpy(c->u_iv.iv, c->lastiv, blocksize );
2N/A inbuf += c->cipher->blocksize;
2N/A outbuf += c->cipher->blocksize;
2N/A }
2N/A }
2N/A
2N/A if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
2N/A {
2N/A int restbytes;
2N/A
2N/A if ((nbytes % blocksize) == 0)
2N/A restbytes = blocksize;
2N/A else
2N/A restbytes = nbytes % blocksize;
2N/A
2N/A memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */
2N/A memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
2N/A
2N/A c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
2N/A for (ivp=c->u_iv.iv,i=0; i < restbytes; i++ )
2N/A outbuf[i] ^= *ivp++;
2N/A
2N/A memcpy(outbuf + blocksize, outbuf, restbytes);
2N/A for(i=restbytes; i < blocksize; i++)
2N/A c->u_iv.iv[i] = outbuf[i];
2N/A c->cipher->decrypt (&c->context.c, outbuf, c->u_iv.iv);
2N/A for(ivp=c->lastiv,i=0; i < blocksize; i++ )
2N/A outbuf[i] ^= *ivp++;
2N/A /* c->lastiv is now really lastlastiv, does this matter? */
2N/A }
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Ado_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
2N/A const unsigned char *inbuf, unsigned int nbytes )
2N/A{
2N/A unsigned char *ivp;
2N/A size_t blocksize = c->cipher->blocksize;
2N/A size_t blocksize_x_2 = blocksize + blocksize;
2N/A
2N/A if ( nbytes <= c->unused )
2N/A {
2N/A /* Short enough to be encoded by the remaining XOR mask. */
2N/A /* XOR the input with the IV and store input into IV. */
2N/A for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused;
2N/A nbytes;
2N/A nbytes--, c->unused-- )
2N/A *outbuf++ = (*ivp++ ^= *inbuf++);
2N/A return;
2N/A }
2N/A
2N/A if ( c->unused )
2N/A {
2N/A /* XOR the input with the IV and store input into IV */
2N/A nbytes -= c->unused;
2N/A for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
2N/A *outbuf++ = (*ivp++ ^= *inbuf++);
2N/A }
2N/A
2N/A /* Now we can process complete blocks. We use a loop as long as we
2N/A have at least 2 blocks and use conditions for the rest. This
2N/A also allows to use a bulk encryption function if available. */
2N/A if (nbytes >= blocksize_x_2 && c->bulk.cfb_enc)
2N/A {
2N/A unsigned int nblocks = nbytes / blocksize;
2N/A c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
2N/A outbuf += nblocks * blocksize;
2N/A inbuf += nblocks * blocksize;
2N/A nbytes -= nblocks * blocksize;
2N/A }
2N/A else
2N/A {
2N/A while ( nbytes >= blocksize_x_2 )
2N/A {
2N/A int i;
2N/A /* Encrypt the IV. */
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A /* XOR the input with the IV and store input into IV. */
2N/A for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
2N/A *outbuf++ = (*ivp++ ^= *inbuf++);
2N/A nbytes -= blocksize;
2N/A }
2N/A }
2N/A
2N/A if ( nbytes >= blocksize )
2N/A {
2N/A int i;
2N/A /* Save the current IV and then encrypt the IV. */
2N/A memcpy( c->lastiv, c->u_iv.iv, blocksize );
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A /* XOR the input with the IV and store input into IV */
2N/A for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
2N/A *outbuf++ = (*ivp++ ^= *inbuf++);
2N/A nbytes -= blocksize;
2N/A }
2N/A if ( nbytes )
2N/A {
2N/A /* Save the current IV and then encrypt the IV. */
2N/A memcpy( c->lastiv, c->u_iv.iv, blocksize );
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A c->unused = blocksize;
2N/A /* Apply the XOR. */
2N/A c->unused -= nbytes;
2N/A for(ivp=c->u_iv.iv; nbytes; nbytes-- )
2N/A *outbuf++ = (*ivp++ ^= *inbuf++);
2N/A }
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Ado_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
2N/A const unsigned char *inbuf, unsigned int nbytes )
2N/A{
2N/A unsigned char *ivp;
2N/A unsigned long temp;
2N/A int i;
2N/A size_t blocksize = c->cipher->blocksize;
2N/A size_t blocksize_x_2 = blocksize + blocksize;
2N/A
2N/A if (nbytes <= c->unused)
2N/A {
2N/A /* Short enough to be encoded by the remaining XOR mask. */
2N/A /* XOR the input with the IV and store input into IV. */
2N/A for (ivp=c->u_iv.iv+blocksize - c->unused;
2N/A nbytes;
2N/A nbytes--, c->unused--)
2N/A {
2N/A temp = *inbuf++;
2N/A *outbuf++ = *ivp ^ temp;
2N/A *ivp++ = temp;
2N/A }
2N/A return;
2N/A }
2N/A
2N/A if (c->unused)
2N/A {
2N/A /* XOR the input with the IV and store input into IV. */
2N/A nbytes -= c->unused;
2N/A for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
2N/A {
2N/A temp = *inbuf++;
2N/A *outbuf++ = *ivp ^ temp;
2N/A *ivp++ = temp;
2N/A }
2N/A }
2N/A
2N/A /* Now we can process complete blocks. We use a loop as long as we
2N/A have at least 2 blocks and use conditions for the rest. This
2N/A also allows to use a bulk encryption function if available. */
2N/A if (nbytes >= blocksize_x_2 && c->bulk.cfb_dec)
2N/A {
2N/A unsigned int nblocks = nbytes / blocksize;
2N/A c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
2N/A outbuf += nblocks * blocksize;
2N/A inbuf += nblocks * blocksize;
2N/A nbytes -= nblocks * blocksize;
2N/A }
2N/A else
2N/A {
2N/A while (nbytes >= blocksize_x_2 )
2N/A {
2N/A /* Encrypt the IV. */
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A /* XOR the input with the IV and store input into IV. */
2N/A for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
2N/A {
2N/A temp = *inbuf++;
2N/A *outbuf++ = *ivp ^ temp;
2N/A *ivp++ = temp;
2N/A }
2N/A nbytes -= blocksize;
2N/A }
2N/A }
2N/A
2N/A if (nbytes >= blocksize )
2N/A {
2N/A /* Save the current IV and then encrypt the IV. */
2N/A memcpy ( c->lastiv, c->u_iv.iv, blocksize);
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A /* XOR the input with the IV and store input into IV */
2N/A for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
2N/A {
2N/A temp = *inbuf++;
2N/A *outbuf++ = *ivp ^ temp;
2N/A *ivp++ = temp;
2N/A }
2N/A nbytes -= blocksize;
2N/A }
2N/A
2N/A if (nbytes)
2N/A {
2N/A /* Save the current IV and then encrypt the IV. */
2N/A memcpy ( c->lastiv, c->u_iv.iv, blocksize );
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A c->unused = blocksize;
2N/A /* Apply the XOR. */
2N/A c->unused -= nbytes;
2N/A for (ivp=c->u_iv.iv; nbytes; nbytes-- )
2N/A {
2N/A temp = *inbuf++;
2N/A *outbuf++ = *ivp ^ temp;
2N/A *ivp++ = temp;
2N/A }
2N/A }
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Ado_ofb_encrypt( gcry_cipher_hd_t c,
2N/A byte *outbuf, const byte *inbuf, unsigned nbytes )
2N/A{
2N/A byte *ivp;
2N/A size_t blocksize = c->cipher->blocksize;
2N/A
2N/A if ( nbytes <= c->unused )
2N/A {
2N/A /* Short enough to be encoded by the remaining XOR mask. */
2N/A /* XOR the input with the IV */
2N/A for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused;
2N/A nbytes;
2N/A nbytes--, c->unused-- )
2N/A *outbuf++ = (*ivp++ ^ *inbuf++);
2N/A return;
2N/A }
2N/A
2N/A if( c->unused )
2N/A {
2N/A nbytes -= c->unused;
2N/A for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
2N/A *outbuf++ = (*ivp++ ^ *inbuf++);
2N/A }
2N/A
2N/A /* Now we can process complete blocks. */
2N/A while ( nbytes >= blocksize )
2N/A {
2N/A int i;
2N/A /* Encrypt the IV (and save the current one). */
2N/A memcpy( c->lastiv, c->u_iv.iv, blocksize );
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A
2N/A for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
2N/A *outbuf++ = (*ivp++ ^ *inbuf++);
2N/A nbytes -= blocksize;
2N/A }
2N/A if ( nbytes )
2N/A { /* process the remaining bytes */
2N/A memcpy( c->lastiv, c->u_iv.iv, blocksize );
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A c->unused = blocksize;
2N/A c->unused -= nbytes;
2N/A for(ivp=c->u_iv.iv; nbytes; nbytes-- )
2N/A *outbuf++ = (*ivp++ ^ *inbuf++);
2N/A }
2N/A}
2N/A
2N/Astatic void
2N/Ado_ofb_decrypt( gcry_cipher_hd_t c,
2N/A byte *outbuf, const byte *inbuf, unsigned int nbytes )
2N/A{
2N/A byte *ivp;
2N/A size_t blocksize = c->cipher->blocksize;
2N/A
2N/A if( nbytes <= c->unused )
2N/A {
2N/A /* Short enough to be encoded by the remaining XOR mask. */
2N/A for (ivp=c->u_iv.iv+blocksize - c->unused; nbytes; nbytes--,c->unused--)
2N/A *outbuf++ = *ivp++ ^ *inbuf++;
2N/A return;
2N/A }
2N/A
2N/A if ( c->unused )
2N/A {
2N/A nbytes -= c->unused;
2N/A for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
2N/A *outbuf++ = *ivp++ ^ *inbuf++;
2N/A }
2N/A
2N/A /* Now we can process complete blocks. */
2N/A while ( nbytes >= blocksize )
2N/A {
2N/A int i;
2N/A /* Encrypt the IV (and save the current one). */
2N/A memcpy( c->lastiv, c->u_iv.iv, blocksize );
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
2N/A *outbuf++ = *ivp++ ^ *inbuf++;
2N/A nbytes -= blocksize;
2N/A }
2N/A if ( nbytes )
2N/A { /* Process the remaining bytes. */
2N/A /* Encrypt the IV (and save the current one). */
2N/A memcpy( c->lastiv, c->u_iv.iv, blocksize );
2N/A c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
2N/A c->unused = blocksize;
2N/A c->unused -= nbytes;
2N/A for (ivp=c->u_iv.iv; nbytes; nbytes-- )
2N/A *outbuf++ = *ivp++ ^ *inbuf++;
2N/A }
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Ado_ctr_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
2N/A unsigned int nbytes )
2N/A{
2N/A unsigned int n;
2N/A byte tmp[MAX_BLOCKSIZE];
2N/A int i;
2N/A
2N/A for(n=0; n < nbytes; n++)
2N/A {
2N/A if ((n % c->cipher->blocksize) == 0)
2N/A {
2N/A c->cipher->encrypt (&c->context.c, tmp, c->ctr);
2N/A
2N/A for (i = c->cipher->blocksize; i > 0; i--)
2N/A {
2N/A c->ctr[i-1]++;
2N/A if (c->ctr[i-1] != 0)
2N/A break;
2N/A }
2N/A }
2N/A
2N/A /* XOR input with encrypted counter and store in output. */
2N/A outbuf[n] = inbuf[n] ^ tmp[n % c->cipher->blocksize];
2N/A }
2N/A}
2N/A
2N/Astatic void
2N/Ado_ctr_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
2N/A unsigned int nbytes )
2N/A{
2N/A do_ctr_encrypt (c, outbuf, inbuf, nbytes);
2N/A}
2N/A
2N/A
2N/A/****************
2N/A * Encrypt INBUF to OUTBUF with the mode selected at open.
2N/A * inbuf and outbuf may overlap or be the same.
2N/A * Depending on the mode some contraints apply to NBYTES.
2N/A */
2N/Astatic gcry_err_code_t
2N/Acipher_encrypt (gcry_cipher_hd_t c, byte *outbuf,
2N/A const byte *inbuf, unsigned int nbytes)
2N/A{
2N/A gcry_err_code_t rc = GPG_ERR_NO_ERROR;
2N/A
2N/A switch( c->mode ) {
2N/A case GCRY_CIPHER_MODE_ECB:
2N/A if (!(nbytes%c->cipher->blocksize))
2N/A do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->cipher->blocksize );
2N/A else
2N/A rc = GPG_ERR_INV_ARG;
2N/A break;
2N/A case GCRY_CIPHER_MODE_CBC:
2N/A if (!(nbytes%c->cipher->blocksize)
2N/A || (nbytes > c->cipher->blocksize
2N/A && (c->flags & GCRY_CIPHER_CBC_CTS)))
2N/A do_cbc_encrypt(c, outbuf, inbuf, nbytes );
2N/A else
2N/A rc = GPG_ERR_INV_ARG;
2N/A break;
2N/A case GCRY_CIPHER_MODE_CFB:
2N/A do_cfb_encrypt(c, outbuf, inbuf, nbytes );
2N/A break;
2N/A case GCRY_CIPHER_MODE_OFB:
2N/A do_ofb_encrypt(c, outbuf, inbuf, nbytes );
2N/A break;
2N/A case GCRY_CIPHER_MODE_CTR:
2N/A do_ctr_encrypt(c, outbuf, inbuf, nbytes );
2N/A break;
2N/A case GCRY_CIPHER_MODE_STREAM:
2N/A c->cipher->stencrypt ( &c->context.c,
2N/A outbuf, (byte*)/*arggg*/inbuf, nbytes );
2N/A break;
2N/A case GCRY_CIPHER_MODE_NONE:
2N/A if (fips_mode () || !_gcry_get_debug_flag (0))
2N/A {
2N/A fips_signal_error ("cipher mode NONE used");
2N/A rc = GPG_ERR_INV_CIPHER_MODE;
2N/A }
2N/A else
2N/A {
2N/A if ( inbuf != outbuf )
2N/A memmove (outbuf, inbuf, nbytes);
2N/A }
2N/A break;
2N/A default:
2N/A log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
2N/A rc = GPG_ERR_INV_CIPHER_MODE;
2N/A break;
2N/A }
2N/A return rc;
2N/A}
2N/A
2N/A
2N/A/****************
2N/A * Encrypt IN and write it to OUT. If IN is NULL, in-place encryption has
2N/A * been requested.
2N/A */
2N/Agcry_error_t
2N/Agcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
2N/A const void *in, size_t inlen)
2N/A{
2N/A gcry_err_code_t err;
2N/A
2N/A if (!in)
2N/A {
2N/A /* Caller requested in-place encryption. */
2N/A /* Actually cipher_encrypt() does not need to know about it, but
2N/A * we may change it in the future to get better performance. */
2N/A err = cipher_encrypt (h, out, out, outsize);
2N/A }
2N/A else if (outsize < ((h->flags & GCRY_CIPHER_CBC_MAC) ?
2N/A h->cipher->blocksize : inlen))
2N/A err = GPG_ERR_TOO_SHORT;
2N/A else if ((h->mode == GCRY_CIPHER_MODE_ECB
2N/A || (h->mode == GCRY_CIPHER_MODE_CBC
2N/A && (! ((h->flags & GCRY_CIPHER_CBC_CTS)
2N/A && (inlen > h->cipher->blocksize)))))
2N/A && (inlen % h->cipher->blocksize))
2N/A err = GPG_ERR_INV_ARG;
2N/A else
2N/A err = cipher_encrypt (h, out, in, inlen);
2N/A
2N/A if (err && out)
2N/A memset (out, 0x42, outsize); /* Failsafe: Make sure that the
2N/A plaintext will never make it into
2N/A OUT. */
2N/A
2N/A return gcry_error (err);
2N/A}
2N/A
2N/A
2N/A
2N/A/****************
2N/A * Decrypt INBUF to OUTBUF with the mode selected at open.
2N/A * inbuf and outbuf may overlap or be the same.
2N/A * Depending on the mode some some contraints apply to NBYTES.
2N/A */
2N/Astatic gcry_err_code_t
2N/Acipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
2N/A unsigned int nbytes)
2N/A{
2N/A gcry_err_code_t rc = GPG_ERR_NO_ERROR;
2N/A
2N/A switch( c->mode ) {
2N/A case GCRY_CIPHER_MODE_ECB:
2N/A if (!(nbytes%c->cipher->blocksize))
2N/A do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->cipher->blocksize );
2N/A else
2N/A rc = GPG_ERR_INV_ARG;
2N/A break;
2N/A case GCRY_CIPHER_MODE_CBC:
2N/A if (!(nbytes%c->cipher->blocksize)
2N/A || (nbytes > c->cipher->blocksize
2N/A && (c->flags & GCRY_CIPHER_CBC_CTS)))
2N/A do_cbc_decrypt(c, outbuf, inbuf, nbytes );
2N/A else
2N/A rc = GPG_ERR_INV_ARG;
2N/A break;
2N/A case GCRY_CIPHER_MODE_CFB:
2N/A do_cfb_decrypt(c, outbuf, inbuf, nbytes );
2N/A break;
2N/A case GCRY_CIPHER_MODE_OFB:
2N/A do_ofb_decrypt(c, outbuf, inbuf, nbytes );
2N/A break;
2N/A case GCRY_CIPHER_MODE_CTR:
2N/A do_ctr_decrypt(c, outbuf, inbuf, nbytes );
2N/A break;
2N/A case GCRY_CIPHER_MODE_STREAM:
2N/A c->cipher->stdecrypt ( &c->context.c,
2N/A outbuf, (byte*)/*arggg*/inbuf, nbytes );
2N/A break;
2N/A case GCRY_CIPHER_MODE_NONE:
2N/A if (fips_mode () || !_gcry_get_debug_flag (0))
2N/A {
2N/A fips_signal_error ("cipher mode NONE used");
2N/A rc = GPG_ERR_INV_CIPHER_MODE;
2N/A }
2N/A else
2N/A {
2N/A if (inbuf != outbuf)
2N/A memmove (outbuf, inbuf, nbytes);
2N/A }
2N/A break;
2N/A default:
2N/A log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode );
2N/A rc = GPG_ERR_INV_CIPHER_MODE;
2N/A break;
2N/A }
2N/A return rc;
2N/A}
2N/A
2N/A
2N/Agcry_error_t
2N/Agcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
2N/A const void *in, size_t inlen)
2N/A{
2N/A gcry_err_code_t err = 0;
2N/A
2N/A if (!in)
2N/A {
2N/A /* Caller requested in-place encryption. */
2N/A /* Actually cipher_encrypt() does not need to know about it, but
2N/A * we may change it in the future to get better performance. */
2N/A err = cipher_decrypt (h, out, out, outsize);
2N/A }
2N/A else if (outsize < inlen)
2N/A err = GPG_ERR_TOO_SHORT;
2N/A else if (((h->mode == GCRY_CIPHER_MODE_ECB)
2N/A || ((h->mode == GCRY_CIPHER_MODE_CBC)
2N/A && (! ((h->flags & GCRY_CIPHER_CBC_CTS)
2N/A && (inlen > h->cipher->blocksize)))))
2N/A && (inlen % h->cipher->blocksize) != 0)
2N/A err = GPG_ERR_INV_ARG;
2N/A else
2N/A err = cipher_decrypt (h, out, in, inlen);
2N/A
2N/A return gcry_error (err);
2N/A}
2N/A
2N/A
2N/A
2N/A/****************
2N/A * Used for PGP's somewhat strange CFB mode. Only works if
2N/A * the corresponding flag is set.
2N/A */
2N/Astatic void
2N/Acipher_sync (gcry_cipher_hd_t c)
2N/A{
2N/A if ((c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused)
2N/A {
2N/A memmove (c->u_iv.iv + c->unused,
2N/A c->u_iv.iv, c->cipher->blocksize - c->unused);
2N/A memcpy (c->u_iv.iv,
2N/A c->lastiv + c->cipher->blocksize - c->unused, c->unused);
2N/A c->unused = 0;
2N/A }
2N/A}
2N/A
2N/A
2N/Agcry_error_t
2N/A_gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen)
2N/A{
2N/A return cipher_setkey (hd, (void*)key, keylen);
2N/A}
2N/A
2N/A
2N/Agcry_error_t
2N/A_gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
2N/A{
2N/A cipher_setiv (hd, iv, ivlen);
2N/A return 0;
2N/A}
2N/A
2N/A/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of
2N/A block size length, or (NULL,0) to set the CTR to the all-zero
2N/A block. */
2N/Agpg_error_t
2N/A_gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen)
2N/A{
2N/A if (ctr && ctrlen == hd->cipher->blocksize)
2N/A memcpy (hd->ctr, ctr, hd->cipher->blocksize);
2N/A else if (!ctr || !ctrlen)
2N/A memset (hd->ctr, 0, hd->cipher->blocksize);
2N/A else
2N/A return gpg_error (GPG_ERR_INV_ARG);
2N/A return 0;
2N/A}
2N/A
2N/A
2N/Agcry_error_t
2N/Agcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
2N/A{
2N/A gcry_err_code_t rc = GPG_ERR_NO_ERROR;
2N/A
2N/A switch (cmd)
2N/A {
2N/A case GCRYCTL_SET_KEY: /* Deprecated; use gcry_cipher_setkey. */
2N/A rc = cipher_setkey( h, buffer, buflen );
2N/A break;
2N/A
2N/A case GCRYCTL_SET_IV: /* Deprecated; use gcry_cipher_setiv. */
2N/A cipher_setiv( h, buffer, buflen );
2N/A break;
2N/A
2N/A case GCRYCTL_RESET:
2N/A cipher_reset (h);
2N/A break;
2N/A
2N/A case GCRYCTL_CFB_SYNC:
2N/A cipher_sync( h );
2N/A break;
2N/A
2N/A case GCRYCTL_SET_CBC_CTS:
2N/A if (buflen)
2N/A if (h->flags & GCRY_CIPHER_CBC_MAC)
2N/A rc = GPG_ERR_INV_FLAG;
2N/A else
2N/A h->flags |= GCRY_CIPHER_CBC_CTS;
2N/A else
2N/A h->flags &= ~GCRY_CIPHER_CBC_CTS;
2N/A break;
2N/A
2N/A case GCRYCTL_SET_CBC_MAC:
2N/A if (buflen)
2N/A if (h->flags & GCRY_CIPHER_CBC_CTS)
2N/A rc = GPG_ERR_INV_FLAG;
2N/A else
2N/A h->flags |= GCRY_CIPHER_CBC_MAC;
2N/A else
2N/A h->flags &= ~GCRY_CIPHER_CBC_MAC;
2N/A break;
2N/A
2N/A case GCRYCTL_DISABLE_ALGO:
2N/A /* This command expects NULL for H and BUFFER to point to an
2N/A integer with the algo number. */
2N/A if( h || !buffer || buflen != sizeof(int) )
2N/A return gcry_error (GPG_ERR_CIPHER_ALGO);
2N/A disable_cipher_algo( *(int*)buffer );
2N/A break;
2N/A
2N/A case GCRYCTL_SET_CTR: /* Deprecated; use gcry_cipher_setctr. */
2N/A if (buffer && buflen == h->cipher->blocksize)
2N/A memcpy (h->ctr, buffer, h->cipher->blocksize);
2N/A else if (buffer == NULL || buflen == 0)
2N/A memset (h->ctr, 0, h->cipher->blocksize);
2N/A else
2N/A rc = GPG_ERR_INV_ARG;
2N/A break;
2N/A
2N/A case 61: /* Disable weak key detection (private). */
2N/A if (h->extraspec->set_extra_info)
2N/A rc = h->extraspec->set_extra_info
2N/A (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0);
2N/A else
2N/A rc = GPG_ERR_NOT_SUPPORTED;
2N/A break;
2N/A
2N/A case 62: /* Return current input vector (private). */
2N/A /* This is the input block as used in CFB and OFB mode which has
2N/A initially been set as IV. The returned format is:
2N/A 1 byte Actual length of the block in bytes.
2N/A n byte The block.
2N/A If the provided buffer is too short, an error is returned. */
2N/A if (buflen < (1 + h->cipher->blocksize))
2N/A rc = GPG_ERR_TOO_SHORT;
2N/A else
2N/A {
2N/A unsigned char *ivp;
2N/A unsigned char *dst = buffer;
2N/A int n = h->unused;
2N/A
2N/A if (!n)
2N/A n = h->cipher->blocksize;
2N/A gcry_assert (n <= h->cipher->blocksize);
2N/A *dst++ = n;
2N/A ivp = h->u_iv.iv + h->cipher->blocksize - n;
2N/A while (n--)
2N/A *dst++ = *ivp++;
2N/A }
2N/A break;
2N/A
2N/A default:
2N/A rc = GPG_ERR_INV_OP;
2N/A }
2N/A
2N/A return gcry_error (rc);
2N/A}
2N/A
2N/A
2N/A/* Return information about the cipher handle H. CMD is the kind of
2N/A information requested. BUFFER and NBYTES are reserved for now.
2N/A
2N/A There are no values for CMD yet defined.
2N/A
2N/A The fucntion always returns GPG_ERR_INV_OP.
2N/A
2N/A */
2N/Agcry_error_t
2N/Agcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A
2N/A (void)h;
2N/A (void)buffer;
2N/A (void)nbytes;
2N/A
2N/A switch (cmd)
2N/A {
2N/A default:
2N/A err = GPG_ERR_INV_OP;
2N/A }
2N/A
2N/A return gcry_error (err);
2N/A}
2N/A
2N/A/* Return information about the given cipher algorithm ALGO.
2N/A
2N/A WHAT select the kind of information returned:
2N/A
2N/A GCRYCTL_GET_KEYLEN:
2N/A Return the length of the key. If the algorithm ALGO
2N/A supports multiple key lengths, the maximum supported key length
2N/A is returned. The key length is returned as number of octets.
2N/A BUFFER and NBYTES must be zero.
2N/A
2N/A GCRYCTL_GET_BLKLEN:
2N/A Return the blocklength of the algorithm ALGO counted in octets.
2N/A BUFFER and NBYTES must be zero.
2N/A
2N/A GCRYCTL_TEST_ALGO:
2N/A Returns 0 if the specified algorithm ALGO is available for use.
2N/A BUFFER and NBYTES must be zero.
2N/A
2N/A Note: Because this function is in most cases used to return an
2N/A integer value, we can make it easier for the caller to just look at
2N/A the return value. The caller will in all cases consult the value
2N/A and thereby detecting whether a error occured or not (i.e. while
2N/A checking the block size)
2N/A */
2N/Agcry_error_t
2N/Agcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A unsigned int ui;
2N/A
2N/A switch (what)
2N/A {
2N/A case GCRYCTL_GET_KEYLEN:
2N/A if (buffer || (! nbytes))
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A else
2N/A {
2N/A ui = cipher_get_keylen (algo);
2N/A if ((ui > 0) && (ui <= 512))
2N/A *nbytes = (size_t) ui / 8;
2N/A else
2N/A /* The only reason is an invalid algo or a strange
2N/A blocksize. */
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A }
2N/A break;
2N/A
2N/A case GCRYCTL_GET_BLKLEN:
2N/A if (buffer || (! nbytes))
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A else
2N/A {
2N/A ui = cipher_get_blocksize (algo);
2N/A if ((ui > 0) && (ui < 10000))
2N/A *nbytes = ui;
2N/A else
2N/A /* The only reason is an invalid algo or a strange
2N/A blocksize. */
2N/A err = GPG_ERR_CIPHER_ALGO;
2N/A }
2N/A break;
2N/A
2N/A case GCRYCTL_TEST_ALGO:
2N/A if (buffer || nbytes)
2N/A err = GPG_ERR_INV_ARG;
2N/A else
2N/A err = check_cipher_algo (algo);
2N/A break;
2N/A
2N/A default:
2N/A err = GPG_ERR_INV_OP;
2N/A }
2N/A
2N/A return gcry_error (err);
2N/A}
2N/A
2N/A
2N/A/* This function returns length of the key for algorithm ALGO. If the
2N/A algorithm supports multiple key lengths, the maximum supported key
2N/A length is returned. On error 0 is returned. The key length is
2N/A returned as number of octets.
2N/A
2N/A This is a convenience functions which should be preferred over
2N/A gcry_cipher_algo_info because it allows for proper type
2N/A checking. */
2N/Asize_t
2N/Agcry_cipher_get_algo_keylen (int algo)
2N/A{
2N/A size_t n;
2N/A
2N/A if (gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &n))
2N/A n = 0;
2N/A return n;
2N/A}
2N/A
2N/A/* This functions returns the blocklength of the algorithm ALGO
2N/A counted in octets. On error 0 is returned.
2N/A
2N/A This is a convenience functions which should be preferred over
2N/A gcry_cipher_algo_info because it allows for proper type
2N/A checking. */
2N/Asize_t
2N/Agcry_cipher_get_algo_blklen (int algo)
2N/A{
2N/A size_t n;
2N/A
2N/A if (gcry_cipher_algo_info( algo, GCRYCTL_GET_BLKLEN, NULL, &n))
2N/A n = 0;
2N/A return n;
2N/A}
2N/A
2N/A/* Explicitly initialize this module. */
2N/Agcry_err_code_t
2N/A_gcry_cipher_init (void)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A return err;
2N/A}
2N/A
2N/A/* Get a list consisting of the IDs of the loaded cipher modules. If
2N/A LIST is zero, write the number of loaded cipher modules to
2N/A LIST_LENGTH and return. If LIST is non-zero, the first
2N/A *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
2N/A according size. In case there are less cipher modules than
2N/A *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
2N/Agcry_error_t
2N/Agcry_cipher_list (int *list, int *list_length)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A err = _gcry_module_list (ciphers_registered, list, list_length);
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A
2N/A return err;
2N/A}
2N/A
2N/A
2N/A/* Run the selftests for cipher algorithm ALGO with optional reporting
2N/A function REPORT. */
2N/Agpg_error_t
2N/A_gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report)
2N/A{
2N/A gcry_module_t module = NULL;
2N/A cipher_extra_spec_t *extraspec = NULL;
2N/A gcry_err_code_t ec = 0;
2N/A
2N/A REGISTER_DEFAULT_CIPHERS;
2N/A
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A module = _gcry_module_lookup_id (ciphers_registered, algo);
2N/A if (module && !(module->flags & FLAG_MODULE_DISABLED))
2N/A extraspec = module->extraspec;
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A if (extraspec && extraspec->selftest)
2N/A ec = extraspec->selftest (algo, extended, report);
2N/A else
2N/A {
2N/A ec = GPG_ERR_CIPHER_ALGO;
2N/A if (report)
2N/A report ("cipher", algo, "module",
2N/A module && !(module->flags & FLAG_MODULE_DISABLED)?
2N/A "no selftest available" :
2N/A module? "algorithm disabled" : "algorithm not found");
2N/A }
2N/A
2N/A if (module)
2N/A {
2N/A ath_mutex_lock (&ciphers_registered_lock);
2N/A _gcry_module_release (module);
2N/A ath_mutex_unlock (&ciphers_registered_lock);
2N/A }
2N/A return gpg_error (ec);
2N/A}