aboutsummaryrefslogtreecommitdiffstats
path: root/wsutil
diff options
context:
space:
mode:
authorCedric Izoard <cedric.izoard@ceva-dsp.com>2016-02-01 17:11:00 +0100
committerAnders Broman <a.broman58@gmail.com>2016-02-03 20:54:35 +0000
commit393b1838ad08a1e088f4e11a9adb0681d3ec5fb2 (patch)
tree23fe809ede183e611a14f3d0c0db8daa2b3eee10 /wsutil
parent16bee215c1e65cf5f7f22b35738414c45b912aba (diff)
Add AES-CMAC encryption support
-Add AES-CMAC encryption need to check MIC when deriving TDLS keys (802.11) -Tested against NIST test vector for AES128-CMAC Bug: 11312 Change-Id: Id4fd839bdedd3aa135823334e59d98271aea7c2b Reviewed-on: https://code.wireshark.org/review/13663 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'wsutil')
-rw-r--r--wsutil/aes.c97
-rw-r--r--wsutil/aes.h41
2 files changed, 138 insertions, 0 deletions
diff --git a/wsutil/aes.c b/wsutil/aes.c
index 11543b7ff2..ee910c2b64 100644
--- a/wsutil/aes.c
+++ b/wsutil/aes.c
@@ -26,6 +26,7 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <string.h>
#include <glib.h>
#include "aes.h"
@@ -1251,6 +1252,102 @@ void rijndael_decrypt(
rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst);
}
+
+/*
+ * CMAC
+ */
+void aes_cmac_encrypt_starts(aes_cmac_ctx *ctx, const guint8 *key, guint key_len)
+{
+ if (ctx == NULL || key == NULL) {
+ ctx->key_len = 0;
+ return;
+ }
+
+ ctx->key_len = key_len;
+ memset(ctx->state, 0, key_len);
+ ctx->input_used = 0;
+ ctx->aes.Nr = rijndaelKeySetupEnc(ctx->aes.ek, key, key_len * 8);
+}
+
+#define XOR_BLOCK(b, a, len) \
+ { \
+ guint __i__; \
+ for (__i__ = 0; __i__ < (guint)(len); __i__++) \
+ (b)[__i__] ^= (a)[__i__]; \
+ }
+
+void aes_cmac_encrypt_update(aes_cmac_ctx *ctx, const guint8 *input, guint length)
+{
+ guint left ;
+
+ if (ctx == NULL || input == NULL || ctx->key_len == 0) {
+ return;
+ }
+
+ left = ctx->key_len - ctx->input_used;
+
+ if (length <= left) {
+ memcpy(&ctx->input[ctx->input_used], input, length);
+ ctx->input_used += length;
+ return;
+ }
+
+ if (ctx->input_used > 0) {
+ memcpy(&ctx->input[ctx->input_used], input, left);
+ input += left;
+ length -= left;
+ XOR_BLOCK(ctx->state, ctx->input, ctx->key_len);
+ rijndael_encrypt(&(ctx->aes), ctx->state, ctx->state);
+ }
+
+ while (length > ctx->key_len) {
+ XOR_BLOCK(ctx->state, input, ctx->key_len);
+ rijndael_encrypt(&(ctx->aes), ctx->state, ctx->state);
+ input += ctx->key_len;
+ length -= ctx->key_len;
+ }
+
+ if (length > 0) {
+ memcpy(ctx->input, input, length);
+ ctx->input_used = length;
+ }
+}
+
+static void sub_key_shift(guint8* sub_key, guint key_len)
+{
+ guint8 carry = (sub_key[0] & 0x80);
+ guint i;
+
+ for (i = 0; i < key_len - 1; i++)
+ sub_key[i] = (sub_key[i] << 1) | (sub_key[i + 1] >> 7);
+ sub_key[key_len - 1] <<= 1;
+
+ if (carry)
+ sub_key[key_len - 1] ^= 0x87;
+}
+
+void aes_cmac_encrypt_finish(aes_cmac_ctx *ctx, guint8 *output)
+{
+ guint8 sub_key[RIJNDAEL_MAXKB];
+ memset(sub_key, 0, ctx->key_len);
+ rijndael_encrypt(&(ctx->aes), sub_key, sub_key);
+ sub_key_shift(sub_key, ctx->key_len);
+
+ if (ctx->input_used == ctx->key_len) {
+ XOR_BLOCK(sub_key, ctx->input, ctx->key_len);
+ } else {
+ sub_key_shift(sub_key, ctx->key_len);
+ XOR_BLOCK(sub_key, ctx->input, ctx->input_used);
+ sub_key[ctx->input_used] ^= 0x80;
+ }
+
+ XOR_BLOCK(ctx->state, sub_key, ctx->key_len);
+ rijndael_encrypt(&(ctx->aes), ctx->state, output);
+}
+
+#undef XOR_BLOCK
+
+
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
diff --git a/wsutil/aes.h b/wsutil/aes.h
index e384667900..df319c69af 100644
--- a/wsutil/aes.h
+++ b/wsutil/aes.h
@@ -62,5 +62,46 @@ void rijndael_decrypt(
const guchar *src,
guchar *dst);
+typedef struct s_aes_cmac_ctx {
+ rijndael_ctx aes;
+ guint key_len;
+ guint input_used;
+ guint8 state[RIJNDAEL_MAXKB];
+ guint8 input[RIJNDAEL_MAXKB];
+} aes_cmac_ctx;
+
+/**
+ * Initialize AES-CMAC calculation with the provided key.
+ * @param [OUT] ctx Context to initialize
+ * @param [IN] key Key to used
+ * @param [IN] key_len Key length in bytes
+ */
+WS_DLL_PUBLIC
+void aes_cmac_encrypt_starts(
+ aes_cmac_ctx *ctx,
+ const guint8 *key,
+ guint key_len);
+
+/**
+ * Add a new buffer for AES-CMAC calculation
+ * @param [IN] ctx Context (initialize with @ref AES_CMAC_encrypt_starts)
+ * @param [IN] input Buffer to add in AES-CMAC calculation
+ * @param [IN] length Length of input buffer (in bytes)
+ */
+WS_DLL_PUBLIC
+void aes_cmac_encrypt_update(
+ aes_cmac_ctx *ctx,
+ const guint8 *input,
+ guint length);
+
+/**
+ * Ends AES-CMAC calculation
+ * @param [IN] ctx Context (initialize with @ref AES_CMAC_encrypt_starts)
+ * @param [OUT] output Buffer to store MAC (must be at least key_len long)
+ */
+WS_DLL_PUBLIC
+void aes_cmac_encrypt_finish(
+ aes_cmac_ctx *ctx,
+ guint8 *output);
#endif