{
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,
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))
}
}
-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,
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;
*/
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 */
};
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);
*/
#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
#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
#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)
{
#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)
{
#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
}
+/*
+ *
+ * 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,
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)