diff options
Diffstat (limited to 'epan/crypt/dot11decrypt_rijndael.c')
-rw-r--r-- | epan/crypt/dot11decrypt_rijndael.c | 98 |
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; +} + +/* */ +/******************************************************************************/ |