aboutsummaryrefslogtreecommitdiffstats
path: root/epan/crypt/dot11decrypt_rijndael.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/crypt/dot11decrypt_rijndael.c')
-rw-r--r--epan/crypt/dot11decrypt_rijndael.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/epan/crypt/dot11decrypt_rijndael.c b/epan/crypt/dot11decrypt_rijndael.c
new file mode 100644
index 0000000000..7eb3d530ec
--- /dev/null
+++ b/epan/crypt/dot11decrypt_rijndael.c
@@ -0,0 +1,98 @@
+/**
+ * dot11decrypt_rijndael.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#include "dot11decrypt_rijndael.h"
+
+#include "dot11decrypt_debug.h"
+#include <glib.h>
+#include <wsutil/wsgcrypt.h>
+
+/* Based on RFC 3394 and NIST AES Key Wrap Specification pseudo-code.
+
+This function is used to unwrap an encrypted AES key. One example of its use is
+in the WPA-2 protocol to get the group key.
+*/
+UCHAR *
+AES_unwrap(UCHAR *kek, UINT16 key_len, UCHAR *cipher_text, UINT16 cipher_len)
+{
+ UCHAR *output;
+ UCHAR a[8], b[16];
+ UCHAR *r;
+ gint16 i, j, n;
+ gcry_cipher_hd_t rijndael_handle;
+
+ if (kek == NULL || cipher_len < 16 || cipher_text == NULL) {
+ return NULL; /* "should not happen" */
+ }
+
+ /* Allocate buffer for the unwrapped key */
+
+ output = (guint8 *) g_malloc0(cipher_len);
+
+ /* Initialize variables */
+
+ n = (cipher_len/8)-1; /* the algorithm works on 64-bits at a time */
+ memcpy(a, cipher_text, 8);
+ r = output;
+ memcpy(r, cipher_text+8, cipher_len - 8);
+
+ /* Compute intermediate values */
+
+ if (gcry_cipher_open(&rijndael_handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0)) {
+ return output;
+ }
+ if (gcry_cipher_setkey(rijndael_handle, kek, key_len)) {
+ gcry_cipher_close(rijndael_handle);
+ return output;
+ }
+ for (j=5; j >= 0; --j){
+ r = output + (n - 1) * 8;
+ /* DEBUG_DUMP("r1", (r-8), 8); */
+ /* DEBUG_DUMP("r2", r, 8); */
+ for (i = n; i >= 1; --i){
+ UINT16 t = (n*j) + i;
+ /* DEBUG_DUMP("a", a, 8); */
+ memcpy(b, a, 8);
+ b[7] ^= t;
+ /* DEBUG_DUMP("a plus t", b, 8); */
+ memcpy(b+8, r, 8);
+ gcry_cipher_decrypt(rijndael_handle, b, 16, NULL, 0);
+ /* DEBUG_DUMP("aes decrypt", b, 16) */
+ memcpy(a,b,8);
+ memcpy(r, b+8, 8);
+ r -= 8;
+ }
+ }
+ gcry_cipher_close(rijndael_handle);
+
+ /* DEBUG_DUMP("a", a, 8); */
+ /* DEBUG_DUMP("output", output, cipher_len - 8); */
+
+ return output;
+}
+
+/* */
+/******************************************************************************/