From 20c8675ba46bda97330a4117c459a59a9f1c465e Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Iniesta Date: Mon, 21 Nov 2016 09:37:33 +0100 Subject: New upstream version 2.4~beta1 --- src/openvpn/crypto.h | 162 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 109 insertions(+), 53 deletions(-) (limited to 'src/openvpn/crypto.h') diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index e489827..ff90745 100644 --- a/src/openvpn/crypto.h +++ b/src/openvpn/crypto.h @@ -86,6 +86,30 @@ * [ HMAC ] [ - IV - ] [ * packet payload * ] * * @par + * GCM data channel crypto format \n + * GCM modes are only supported in TLS mode. In these modes, the IV consists of + * the 32-bit packet counter followed by data from the HMAC key. The HMAC key + * can be used as IV, since in GCM and CCM modes the HMAC key is not used for + * the HMAC. The packet counter may not roll over within a single TLS sessions. + * This results in a unique IV for each packet, as required by GCM. + * + * @par + * The HMAC key data is pre-shared during the connection setup, and thus can be + * omitted in on-the-wire packets, saving 8 bytes per packet (for GCM and CCM). + * + * @par + * In GCM mode, P_DATA_V2 headers (the opcode and peer-id) are also + * authenticated as Additional Data. + * + * @par + * GCM IV format: \n + * [ - packet ID - ] [ - HMAC key data - ] \n + * P_DATA_V1 GCM data channel crypto format: \n + * [ opcode ] [ - packet ID - ] [ TAG ] [ * packet payload * ] + * P_DATA_V2 GCM data channel crypto format: \n + * [ - opcode/peer-id - ] [ - packet ID - ] [ TAG ] [ * packet payload * ] + * + * @par * No-crypto data channel format \n * In no-crypto mode (\c \-\-cipher \c none is specified), both TLS-mode and * static key mode are supported. No encryption will be performed on the packet, @@ -108,6 +132,11 @@ #include "packet_id.h" #include "mtu.h" +/** Wrapper struct to pass around MD5 digests */ +struct md5_digest { + uint8_t digest[MD5_DIGEST_LENGTH]; +}; + /* * Defines a key type and key length for both cipher and HMAC. */ @@ -133,13 +162,16 @@ struct key /** - * Container for one set of OpenSSL cipher and/or HMAC contexts. + * Container for one set of cipher and/or HMAC contexts. * @ingroup control_processor */ struct key_ctx { cipher_ctx_t *cipher; /**< Generic cipher %context. */ - hmac_ctx_t *hmac; /**< Generic HMAC %context. */ + hmac_ctx_t *hmac; /**< Generic HMAC %context. */ + uint8_t implicit_iv[OPENVPN_MAX_IV_LENGTH]; + /**< The implicit part of the IV */ + size_t implicit_iv_len; /**< The length of implicit_iv */ }; #define KEY_DIRECTION_BIDIRECTIONAL 0 /* same keys for both directions */ @@ -190,10 +222,11 @@ struct key_direction_state */ struct key_ctx_bi { - struct key_ctx encrypt; /**< OpenSSL cipher and/or HMAC contexts - * for sending direction. */ - struct key_ctx decrypt; /**< OpenSSL cipher and/or HMAC contexts - * for receiving direction. */ + struct key_ctx encrypt; /**< Cipher and/or HMAC contexts for sending + * direction. */ + struct key_ctx decrypt; /**< cipher and/or HMAC contexts for + * receiving direction. */ + bool initialized; }; /** @@ -202,11 +235,11 @@ struct key_ctx_bi */ struct crypto_options { - struct key_ctx_bi *key_ctx_bi; + struct key_ctx_bi key_ctx_bi; /**< OpenSSL cipher and HMAC contexts for * both sending and receiving * directions. */ - struct packet_id *packet_id; /**< Current packet ID state for both + struct packet_id packet_id; /**< Current packet ID state for both * sending and receiving directions. */ struct packet_id_persist *pid_persist; /**< Persistent packet ID state for @@ -233,6 +266,15 @@ struct crypto_options * security operation functions. */ }; +#define CRYPT_ERROR(format) \ + do { msg (D_CRYPT_ERRORS, "%s: " format, error_prefix); goto error_exit; } while (false) + +/** + * Minimal IV length for AEAD mode ciphers (in bytes): + * 4-byte packet id + 8 bytes implicit IV. + */ +#define OPENVPN_AEAD_MIN_IV_LEN (sizeof (packet_id_type) + 8) + #define RKF_MUST_SUCCEED (1<<0) #define RKF_INLINE (1<<1) void read_key_file (struct key2 *key2, const char *file, const unsigned int flags); @@ -257,9 +299,20 @@ bool write_key (const struct key *key, const struct key_type *kt, int read_key (struct key *key, const struct key_type *kt, struct buffer *buf); +/** + * Initialize a key_type structure with. + * + * @param kt The struct key_type to initialize + * @param ciphername The name of the cipher to use + * @param authname The name of the HMAC digest to use + * @param keysize The length of the cipher key to use, in bytes. Only valid + * for ciphers that support variable length keys. + * @param tls_mode Specifies wether we are running in TLS mode, which allows + * more ciphers than static key mode. + * @param warn Print warnings when null cipher / auth is used. + */ 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); + const char *authname, int keysize, bool tls_mode, bool warn); /* * Key context functions @@ -296,18 +349,16 @@ void free_key_ctx_bi (struct key_ctx_bi *ctx); * * @param buf - The %buffer containing the packet on which to * perform security operations. - * @param work - A working %buffer. + * @param work - An initialized working %buffer. * @param opt - The security parameter state for this VPN tunnel. - * @param frame - The packet geometry parameters for this VPN - * tunnel. + * * @return This function returns void.\n On return, the \a buf argument * will point to the resulting %buffer. This %buffer will either * contain the processed packet ready for sending, or be empty if an * error occurred. */ void openvpn_encrypt (struct buffer *buf, struct buffer work, - const struct crypto_options *opt, - const struct frame* frame); + struct crypto_options *opt); /** @@ -333,6 +384,8 @@ void openvpn_encrypt (struct buffer *buf, struct buffer work, * @param opt - The security parameter state for this VPN tunnel. * @param frame - The packet geometry parameters for this VPN * tunnel. + * @param ad_start - A pointer into buf, indicating from where to start + * authenticating additional data (AEAD mode only). * * @return * @li True, if the packet was authenticated and decrypted successfully. @@ -342,18 +395,35 @@ void openvpn_encrypt (struct buffer *buf, struct buffer work, * an error occurred. */ bool openvpn_decrypt (struct buffer *buf, struct buffer work, - const struct crypto_options *opt, - const struct frame* frame); + struct crypto_options *opt, const struct frame* frame, + const uint8_t *ad_start); /** @} name Functions for performing security operations on data channel packets */ +/** + * Check packet ID for replay, and perform replay administration. + * + * @param opt Crypto options for this packet, contains replay state. + * @param pin Packet ID read from packet. + * @param error_prefix Prefix to use when printing error messages. + * @param gc Garbage collector to use. + * + * @return true if packet ID is validated to be not a replay, false otherwise. + */ +bool crypto_check_replay(struct crypto_options *opt, + const struct packet_id_net *pin, const char *error_prefix, + struct gc_arena *gc); + + +/** Calculate crypto overhead and adjust frame to account for that */ void crypto_adjust_frame_parameters(struct frame *frame, const struct key_type* kt, - bool cipher_defined, bool use_iv, bool packet_id, bool packet_id_long_form); +/** Return the worst-case OpenVPN crypto overhead (in bytes) */ +size_t crypto_max_overhead(void); /* Minimum length of the nonce used by the PRNG */ #define NONCE_SECRET_LEN_MIN 16 @@ -392,7 +462,7 @@ void prng_bytes (uint8_t *output, int len); void prng_uninit (); -void test_crypto (const struct crypto_options *co, struct frame* f); +void test_crypto (struct crypto_options *co, struct frame* f); /* key direction functions */ @@ -413,45 +483,31 @@ void key2_print (const struct key2* k, const char* prefix0, const char* prefix1); -#ifdef ENABLE_SSL - -#define GHK_INLINE (1<<0) -void get_tls_handshake_key (const struct key_type *key_type, - struct key_ctx_bi *ctx, - const char *passphrase_file, - const int key_direction, - const unsigned int flags); - -#else - -void init_ssl_lib (void); -void free_ssl_lib (void); - -#endif /* ENABLE_SSL */ +void crypto_read_openvpn_key (const struct key_type *key_type, + struct key_ctx_bi *ctx, const char *key_file, const char *key_inline, + const int key_direction, const char *key_name, const char *opt_name); /* - * md5 functions + * Inline functions */ -struct md5_state { - md_ctx_t ctx; -}; - -struct md5_digest { - uint8_t digest [MD5_DIGEST_LENGTH]; -}; - -const char *md5sum(uint8_t *buf, int len, int n_print_chars, struct gc_arena *gc); -void md5_state_init (struct md5_state *s); -void md5_state_update (struct md5_state *s, void *data, size_t len); -void md5_state_final (struct md5_state *s, struct md5_digest *out); -void md5_digest_clear (struct md5_digest *digest); -bool md5_digest_defined (const struct md5_digest *digest); -bool md5_digest_equal (const struct md5_digest *d1, const struct md5_digest *d2); - -/* - * Inline functions +/** + * As memcmp(), but constant-time. + * Returns 0 when data is equal, non-zero otherwise. */ +static inline int +memcmp_constant_time (const void *a, const void *b, size_t size) { + const uint8_t * a1 = a; + const uint8_t * b1 = b; + int ret = 0; + size_t i; + + for (i = 0; i < size; i++) { + ret |= *a1++ ^ *b1++; + } + + return ret; +} static inline bool key_ctx_bi_defined(const struct key_ctx_bi* key) -- cgit v1.2.3