mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-20 12:02:28 +02:00
Refactored cipher key types
Signed-off-by: Adriaan de Jong <dejong@fox-it.com> Acked-by: David Sommerseth <davids@redhat.com> Acked-by: James Yonan <james@openvpn.net> Signed-off-by: David Sommerseth <davids@redhat.com>
This commit is contained in:
parent
e8c950f12d
commit
670f9dd91a
48
crypto.c
48
crypto.c
@ -378,27 +378,11 @@ crypto_adjust_frame_parameters(struct frame *frame,
|
||||
{
|
||||
frame_add_to_extra_frame (frame,
|
||||
(packet_id ? packet_id_size (packet_id_long_form) : 0) +
|
||||
((cipher_defined && use_iv) ? EVP_CIPHER_iv_length (kt->cipher) : 0) +
|
||||
(cipher_defined ? EVP_CIPHER_block_size (kt->cipher) : 0) + /* worst case padding expansion */
|
||||
((cipher_defined && use_iv) ? cipher_kt_iv_size (kt->cipher) : 0) +
|
||||
(cipher_defined ? cipher_kt_block_size (kt->cipher) : 0) + /* worst case padding expansion */
|
||||
kt->hmac_length);
|
||||
}
|
||||
|
||||
static const EVP_CIPHER *
|
||||
get_cipher (const char *ciphername)
|
||||
{
|
||||
const EVP_CIPHER *cipher = NULL;
|
||||
ASSERT (ciphername);
|
||||
cipher = EVP_get_cipherbyname (ciphername);
|
||||
if ( !(cipher && cipher_ok (OBJ_nid2sn (EVP_CIPHER_nid (cipher)))))
|
||||
msg (M_SSLERR, "Cipher algorithm '%s' not found", ciphername);
|
||||
if (EVP_CIPHER_key_length (cipher) > MAX_CIPHER_KEY_LENGTH)
|
||||
msg (M_FATAL, "Cipher algorithm '%s' uses a default key size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum key size (%d bytes)",
|
||||
ciphername,
|
||||
EVP_CIPHER_key_length (cipher),
|
||||
MAX_CIPHER_KEY_LENGTH);
|
||||
return cipher;
|
||||
}
|
||||
|
||||
static void
|
||||
init_cipher (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
struct key *key, const struct key_type *kt, int enc,
|
||||
@ -446,14 +430,14 @@ init_key_type (struct key_type *kt, const char *ciphername,
|
||||
CLEAR (*kt);
|
||||
if (ciphername && ciphername_defined)
|
||||
{
|
||||
kt->cipher = get_cipher (ciphername);
|
||||
kt->cipher_length = EVP_CIPHER_key_length (kt->cipher);
|
||||
kt->cipher = cipher_kt_get (ciphername);
|
||||
kt->cipher_length = cipher_kt_key_size (kt->cipher);
|
||||
if (keysize > 0 && keysize <= MAX_CIPHER_KEY_LENGTH)
|
||||
kt->cipher_length = keysize;
|
||||
|
||||
/* check legal cipher mode */
|
||||
{
|
||||
const unsigned int mode = EVP_CIPHER_mode (kt->cipher);
|
||||
const unsigned int mode = cipher_kt_mode (kt->cipher);
|
||||
if (!(mode == OPENVPN_MODE_CBC
|
||||
#ifdef ALLOW_NON_CBC_CIPHERS
|
||||
|| (cfb_ofb_allowed && (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB))
|
||||
@ -483,26 +467,6 @@ init_key_type (struct key_type *kt, const char *ciphername,
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
kt_cipher_name (const struct key_type *kt)
|
||||
{
|
||||
if (kt->cipher)
|
||||
return EVP_CIPHER_name (kt->cipher);
|
||||
else
|
||||
return "[null-cipher]";
|
||||
}
|
||||
|
||||
int
|
||||
kt_key_size (const struct key_type *kt)
|
||||
{
|
||||
if (kt->cipher_length)
|
||||
return kt->cipher_length * 8;
|
||||
else if (kt->cipher)
|
||||
return EVP_CIPHER_key_length (kt->cipher) * 8;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* given a key and key_type, build a key_ctx */
|
||||
void
|
||||
init_key_ctx (struct key_ctx *ctx, struct key *key,
|
||||
@ -632,8 +596,8 @@ check_replay_iv_consistency (const struct key_type *kt, bool packet_id, bool use
|
||||
bool
|
||||
cfb_ofb_mode (const struct key_type* kt)
|
||||
{
|
||||
const unsigned int mode = EVP_CIPHER_mode (kt->cipher);
|
||||
if (kt && kt->cipher) {
|
||||
const unsigned int mode = cipher_kt_mode (kt->cipher);
|
||||
return mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB;
|
||||
}
|
||||
return false;
|
||||
|
6
crypto.h
6
crypto.h
@ -164,9 +164,9 @@ cipher_ok (const char* name)
|
||||
*/
|
||||
struct key_type
|
||||
{
|
||||
uint8_t cipher_length;
|
||||
uint8_t cipher_length; /**< Cipher length, in bytes */
|
||||
uint8_t hmac_length; /**< HMAC length, in bytes */
|
||||
const EVP_CIPHER *cipher;
|
||||
const cipher_kt_t *cipher; /**< Cipher static parameters */
|
||||
const md_kt_t *digest; /**< Message digest static parameters */
|
||||
};
|
||||
|
||||
@ -309,8 +309,6 @@ int read_key (struct key *key, const struct key_type *kt, struct buffer *buf);
|
||||
|
||||
bool cfb_ofb_mode (const struct key_type* kt);
|
||||
|
||||
const char *kt_cipher_name (const struct key_type *kt);
|
||||
int kt_key_size (const struct key_type *kt);
|
||||
void init_key_type (struct key_type *kt, const char *ciphername,
|
||||
bool ciphername_defined, const char *authname, bool authname_defined,
|
||||
int keysize, bool cfb_ofb_allowed, bool warn);
|
||||
|
@ -156,6 +156,69 @@ void cipher_des_encrypt_ecb (const unsigned char key[8],
|
||||
*/
|
||||
#define MAX_CIPHER_KEY_LENGTH 64
|
||||
|
||||
/**
|
||||
* Return cipher parameters, based on the given cipher name. The
|
||||
* contents of these parameters are library-specific, and can be used to
|
||||
* initialise encryption/decryption.
|
||||
*
|
||||
* @param ciphername Name of the cipher to retrieve parameters for (e.g.
|
||||
* \c AES-128-CBC).
|
||||
*
|
||||
* @return A statically allocated structure containing parameters
|
||||
* for the given cipher.
|
||||
*/
|
||||
const cipher_kt_t * cipher_kt_get (const char *ciphername);
|
||||
|
||||
/**
|
||||
* Retrieve a string describing the cipher (e.g. \c AES-128-CBC).
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return a statically allocated string describing the cipher.
|
||||
*/
|
||||
const char * cipher_kt_name (const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the size of keys used by the cipher, in bytes. If the cipher has a
|
||||
* variable key size, return the default key size.
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return (Default) size of keys used by the cipher, in bytes.
|
||||
*/
|
||||
int cipher_kt_key_size (const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the size of the IV used by the cipher, in bytes, or 0 if no IV is
|
||||
* used.
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return Size of the IV, in bytes, or 0 if the cipher does not
|
||||
* use an IV.
|
||||
*/
|
||||
int cipher_kt_iv_size (const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the block size of the cipher, in bytes.
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return Block size, in bytes.
|
||||
*/
|
||||
int cipher_kt_block_size (const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the mode that the cipher runs in.
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return Cipher mode, either \c OPENVPN_MODE_CBC, \c
|
||||
* OPENVPN_MODE_OFB or \c OPENVPN_MODE_CFB
|
||||
*/
|
||||
bool cipher_kt_mode (const cipher_kt_t *cipher_kt);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Generic message digest information functions
|
||||
|
108
crypto_openssl.c
108
crypto_openssl.c
@ -58,6 +58,10 @@
|
||||
|
||||
#if SSLEAY_VERSION_NUMBER < 0x00907000L
|
||||
|
||||
/* Workaround: EVP_CIPHER_mode is defined wrong in OpenSSL 0.9.6 but is fixed in 0.9.7 */
|
||||
#undef EVP_CIPHER_mode
|
||||
#define EVP_CIPHER_mode(e) (((e)->flags) & EVP_CIPH_MODE)
|
||||
|
||||
#define DES_cblock des_cblock
|
||||
#define DES_is_weak_key des_is_weak_key
|
||||
#define DES_check_key_parity des_check_key_parity
|
||||
@ -74,6 +78,33 @@
|
||||
|
||||
#if SSLEAY_VERSION_NUMBER < 0x00906000
|
||||
|
||||
#undef EVP_CIPHER_mode
|
||||
#define EVP_CIPHER_mode(x) 1
|
||||
#define EVP_CIPHER_CTX_mode(x) 1
|
||||
#define EVP_CIPHER_flags(x) 0
|
||||
|
||||
#define EVP_CIPH_CBC_MODE 1
|
||||
#define EVP_CIPH_CFB_MODE 0
|
||||
#define EVP_CIPH_OFB_MODE 0
|
||||
#define EVP_CIPH_VARIABLE_LENGTH 0
|
||||
|
||||
#define OPENSSL_malloc(x) malloc(x)
|
||||
#define OPENSSL_free(x) free(x)
|
||||
|
||||
static inline int
|
||||
EVP_CipherInit_ov (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, uint8_t *key, uint8_t *iv, int enc)
|
||||
{
|
||||
EVP_CipherInit (ctx, type, key, iv, enc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
EVP_CipherUpdate_ov (EVP_CIPHER_CTX *ctx, uint8_t *out, int *outl, uint8_t *in, int inl)
|
||||
{
|
||||
EVP_CipherUpdate (ctx, out, outl, in, inl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
cipher_ok (const char* name)
|
||||
{
|
||||
@ -86,6 +117,18 @@ cipher_ok (const char* name)
|
||||
|
||||
#else
|
||||
|
||||
static inline int
|
||||
EVP_CipherInit_ov (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, uint8_t *key, uint8_t *iv, int enc)
|
||||
{
|
||||
return EVP_CipherInit (ctx, type, key, iv, enc);
|
||||
}
|
||||
|
||||
static inline int
|
||||
EVP_CipherUpdate_ov (EVP_CIPHER_CTX *ctx, uint8_t *out, int *outl, uint8_t *in, int inl)
|
||||
{
|
||||
return EVP_CipherUpdate (ctx, out, outl, in, inl);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
cipher_ok (const char* name)
|
||||
{
|
||||
@ -98,6 +141,10 @@ cipher_ok (const char* name)
|
||||
|
||||
#endif /* SSLEAY_VERSION_NUMBER < 0x0090581f */
|
||||
|
||||
#ifndef EVP_CIPHER_name
|
||||
#define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
|
||||
#endif
|
||||
|
||||
#ifndef EVP_MD_name
|
||||
#define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e))
|
||||
#endif
|
||||
@ -452,6 +499,67 @@ key_des_fixup (uint8_t *key, int key_len, int ndc)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Generic cipher key type functions
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const EVP_CIPHER *
|
||||
cipher_kt_get (const char *ciphername)
|
||||
{
|
||||
const EVP_CIPHER *cipher = NULL;
|
||||
|
||||
ASSERT (ciphername);
|
||||
|
||||
cipher = EVP_get_cipherbyname (ciphername);
|
||||
|
||||
if ((NULL == cipher) || !cipher_ok (OBJ_nid2sn (EVP_CIPHER_nid (cipher))))
|
||||
msg (M_SSLERR, "Cipher algorithm '%s' not found", ciphername);
|
||||
|
||||
if (EVP_CIPHER_key_length (cipher) > MAX_CIPHER_KEY_LENGTH)
|
||||
msg (M_FATAL, "Cipher algorithm '%s' uses a default key size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum key size (%d bytes)",
|
||||
ciphername,
|
||||
EVP_CIPHER_key_length (cipher),
|
||||
MAX_CIPHER_KEY_LENGTH);
|
||||
|
||||
return cipher;
|
||||
}
|
||||
|
||||
const char *
|
||||
cipher_kt_name (const EVP_CIPHER *cipher_kt)
|
||||
{
|
||||
if (NULL == cipher_kt)
|
||||
return "[null-cipher]";
|
||||
return EVP_CIPHER_name (cipher_kt);
|
||||
}
|
||||
|
||||
int
|
||||
cipher_kt_key_size (const EVP_CIPHER *cipher_kt)
|
||||
{
|
||||
return EVP_CIPHER_key_length (cipher_kt);
|
||||
}
|
||||
|
||||
int
|
||||
cipher_kt_iv_size (const EVP_CIPHER *cipher_kt)
|
||||
{
|
||||
return EVP_CIPHER_iv_length (cipher_kt);
|
||||
}
|
||||
|
||||
int
|
||||
cipher_kt_block_size (const EVP_CIPHER *cipher_kt)
|
||||
{
|
||||
return EVP_CIPHER_block_size (cipher_kt);
|
||||
}
|
||||
|
||||
bool
|
||||
cipher_kt_mode (const EVP_CIPHER *cipher_kt)
|
||||
{
|
||||
ASSERT(NULL != cipher_kt);
|
||||
return EVP_CIPHER_mode (cipher_kt);
|
||||
}
|
||||
|
||||
void
|
||||
cipher_des_encrypt_ecb (const unsigned char key[8],
|
||||
unsigned char *src,
|
||||
|
@ -2779,9 +2779,9 @@ options_string (const struct options *o,
|
||||
o->authname, o->authname_defined,
|
||||
o->keysize, true, false);
|
||||
|
||||
buf_printf (&out, ",cipher %s", kt_cipher_name (&kt));
|
||||
buf_printf (&out, ",cipher %s", cipher_kt_name (kt.cipher));
|
||||
buf_printf (&out, ",auth %s", md_kt_name (kt.digest));
|
||||
buf_printf (&out, ",keysize %d", kt_key_size (&kt));
|
||||
buf_printf (&out, ",keysize %d", kt.cipher_length);
|
||||
if (o->shared_secret_file)
|
||||
buf_printf (&out, ",secret");
|
||||
if (!o->replay)
|
||||
|
Loading…
Reference in New Issue
Block a user