diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c
index eefdd1a95923a2bf2d72f521e877fa5c0ff5a2ad..c0861a503f68eed8533a63600023de15e899aab3 100644
--- a/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c
+++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c
@@ -58,9 +58,11 @@
 #include <asm/byteorder.h>
 #include <crypto/algapi.h>
 #include <crypto/b128ops.h>
+#include <crypto/gcm.h>
 #include <crypto/gf128mul.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/xts.h>
+#include <crypto/internal/aead.h>
 #include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
 
@@ -132,6 +134,7 @@ struct aes_ctx {
     u32 (*temp)[AES_BLOCK_WORDS];
     u8 block[AES_BLOCK_SIZE];
     u8 hash[AES_BLOCK_SIZE];
+    struct gf128mul_4k *gf128;
 };
 
 extern int disable_deudma;
@@ -1565,6 +1568,308 @@ static struct shash_alg ifxdeu_cbcmac_aes_alg = {
         }
 };
 
+/*! \fn int aes_set_key_aead (struct crypto_aead *aead, const uint8_t *in_key, unsigned int key_len)
+ *  \ingroup IFX_AES_FUNCTIONS
+ *  \brief sets the AES keys for aead gcm
+ *  \param aead linux crypto aead
+ *  \param in_key input key
+ *  \param key_len key lengths of 16, 24 and 32 bytes supported
+ *  \return -EINVAL - bad key length, 0 - SUCCESS
+*/
+int aes_set_key_aead (struct crypto_aead *aead, const u8 *in_key, unsigned int key_len)
+{
+    struct aes_ctx *ctx = crypto_aead_ctx(aead);
+    int err;
+
+    err = aes_set_key(&aead->base, in_key, key_len);
+    if (err) return err;
+
+    memset(ctx->block, 0, sizeof(ctx->block));
+    memset(ctx->lastbuffer, 0, AES_BLOCK_SIZE);
+    ifx_deu_aes_ctr(ctx, ctx->block, ctx->block,
+                       ctx->lastbuffer, AES_BLOCK_SIZE, CRYPTO_DIR_ENCRYPT, 0);
+    if (ctx->gf128) gf128mul_free_4k(ctx->gf128);
+    ctx->gf128 = gf128mul_init_4k_lle((be128 *)ctx->block);
+
+    return err;
+}
+
+/*! \fn int gcm_aes_setauthsize (struct crypto_aead *aead, unsigned int authsize)
+ *  \ingroup IFX_AES_FUNCTIONS
+ *  \brief sets the AES keys for aead gcm
+ *  \param aead linux crypto aead
+ *  \param in_key input authsize
+ *  \return -EINVAL - bad authsize length, 0 - SUCCESS
+*/
+int gcm_aes_setauthsize (struct crypto_aead *aead, unsigned int authsize)
+{
+    return crypto_gcm_check_authsize(authsize);
+}
+
+/*! \fn int gcm_aes_encrypt(struct aead_request *req)
+ *  \ingroup IFX_AES_FUNCTIONS
+ *  \brief GCM AES encrypt using linux crypto aead
+ *  \param req aead request
+ *  \return err
+*/
+int gcm_aes_encrypt(struct aead_request *req)
+{
+    struct aes_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+    struct skcipher_walk walk;
+    struct skcipher_request request;
+    int err;
+    unsigned int enc_bytes, nbytes;
+    be128 lengths;
+    u8 iv[AES_BLOCK_SIZE];
+
+    lengths.a = cpu_to_be64(req->assoclen * 8);
+    lengths.b = cpu_to_be64(req->cryptlen * 8);
+
+    memset(ctx->hash, 0, sizeof(ctx->hash));
+    memset(ctx->block, 0, sizeof(ctx->block));
+    memcpy(iv, req->iv, GCM_AES_IV_SIZE);
+    *(__be32 *)((void *)iv + GCM_AES_IV_SIZE) = cpu_to_be32(1);
+    ifx_deu_aes_ctr(ctx, ctx->block, ctx->block,
+                       iv, 16, CRYPTO_DIR_ENCRYPT, 0);
+
+    request.cryptlen = req->cryptlen + req->assoclen;
+    request.src = req->src;
+    request.dst = req->dst;
+    request.base = req->base;
+
+    crypto_skcipher_alg(crypto_skcipher_reqtfm(&request))->walksize = AES_BLOCK_SIZE;
+
+    if (req->assoclen && (req->assoclen < AES_BLOCK_SIZE))
+        crypto_skcipher_alg(crypto_skcipher_reqtfm(&request))->walksize = req->assoclen;
+
+    err = skcipher_walk_virt(&walk, &request, false);
+
+    //process assoc data if available
+    if (req->assoclen > 0) {
+        unsigned int assoc_remain, ghashlen;
+
+        assoc_remain = req->assoclen;
+        ghashlen = min(req->assoclen, walk.nbytes);
+        while ((nbytes = enc_bytes = ghashlen) && (ghashlen >= AES_BLOCK_SIZE)) {
+            u8 *temp;
+            if (nbytes > req->assoclen) nbytes = enc_bytes = req->assoclen;
+            enc_bytes -= (nbytes % AES_BLOCK_SIZE);
+            memcpy(walk.dst.virt.addr, walk.src.virt.addr, enc_bytes);
+            assoc_remain -= enc_bytes;
+            temp = walk.dst.virt.addr;
+            while (enc_bytes > 0) {
+                u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)temp);
+                gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+                enc_bytes -= AES_BLOCK_SIZE;
+                temp += 16;
+            }
+            if (assoc_remain < AES_BLOCK_SIZE) walk.stride = assoc_remain;
+            if (assoc_remain == 0) walk.stride = AES_BLOCK_SIZE;
+            enc_bytes = nbytes - (nbytes % AES_BLOCK_SIZE);
+            err = skcipher_walk_done(&walk, (walk.nbytes - enc_bytes));
+            ghashlen = min(assoc_remain, walk.nbytes);
+        }
+
+        if ((enc_bytes = ghashlen)) {
+            memcpy(ctx->lastbuffer, walk.src.virt.addr, enc_bytes);
+            memset(ctx->lastbuffer + enc_bytes, 0, (AES_BLOCK_SIZE - enc_bytes));
+            memcpy(walk.dst.virt.addr, walk.src.virt.addr, ghashlen);
+            u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)ctx->lastbuffer);
+            gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+            walk.stride = AES_BLOCK_SIZE;
+            err = skcipher_walk_done(&walk, (walk.nbytes - ghashlen));
+        }
+    }
+
+    //crypt and hash
+    while ((nbytes = enc_bytes = walk.nbytes) && (walk.nbytes >= AES_BLOCK_SIZE)) {
+        u8 *temp;
+        enc_bytes -= (nbytes % AES_BLOCK_SIZE);
+        ifx_deu_aes_ctr(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+                       iv, enc_bytes, CRYPTO_DIR_ENCRYPT, 0);
+        nbytes &= AES_BLOCK_SIZE - 1;
+        temp = walk.dst.virt.addr;
+        while (enc_bytes) {
+            u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)temp);
+            gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+            enc_bytes -= AES_BLOCK_SIZE;
+            temp += 16;
+        }
+        err = skcipher_walk_done(&walk, nbytes);
+    }
+
+    /* crypt and hash remaining bytes < AES_BLOCK_SIZE */
+    if ((enc_bytes = walk.nbytes)) {
+        ifx_deu_aes_ctr(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+                       iv, walk.nbytes, CRYPTO_DIR_ENCRYPT, 0);
+        memcpy(ctx->lastbuffer, walk.dst.virt.addr, enc_bytes);
+        memset(ctx->lastbuffer + enc_bytes, 0, (AES_BLOCK_SIZE - enc_bytes));
+        u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)ctx->lastbuffer);
+        gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+        err = skcipher_walk_done(&walk, 0);
+    }
+
+    //finalize and copy hash
+    u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)&lengths);
+    gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+    u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)ctx->block);
+    scatterwalk_map_and_copy(ctx->hash, req->dst, req->cryptlen + req->assoclen, crypto_aead_authsize(crypto_aead_reqtfm(req)), 1);
+
+    aead_request_complete(req, 0);
+
+    return err;
+}
+
+/*! \fn int gcm_aes_decrypt(struct aead_request *req)
+ *  \ingroup IFX_AES_FUNCTIONS
+ *  \brief GCM AES decrypt using linux crypto aead
+ *  \param req aead request
+ *  \return err
+*/
+int gcm_aes_decrypt(struct aead_request *req)
+{
+    struct aes_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+    struct skcipher_walk walk;
+    struct skcipher_request request;
+    int err;
+    unsigned int dec_bytes, nbytes, authsize;
+    be128 lengths;
+    u8 iv[AES_BLOCK_SIZE];
+
+    authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
+
+    lengths.a = cpu_to_be64(req->assoclen * 8);
+    lengths.b = cpu_to_be64((req->cryptlen - authsize) * 8);
+
+    memset(ctx->hash, 0, sizeof(ctx->hash));
+    memset(ctx->block, 0, sizeof(ctx->block));
+    memcpy(iv, req->iv, GCM_AES_IV_SIZE);
+    *(__be32 *)((void *)iv + GCM_AES_IV_SIZE) = cpu_to_be32(1);
+    ifx_deu_aes_ctr(ctx, ctx->block, ctx->block,
+                       iv, 16, CRYPTO_DIR_ENCRYPT, 0);
+
+    request.cryptlen = req->cryptlen + req->assoclen - authsize;
+    request.src = req->src;
+    request.dst = req->dst;
+    request.base = req->base;
+    crypto_skcipher_alg(crypto_skcipher_reqtfm(&request))->walksize = AES_BLOCK_SIZE;
+
+    if (req->assoclen && (req->assoclen < AES_BLOCK_SIZE))
+        crypto_skcipher_alg(crypto_skcipher_reqtfm(&request))->walksize = req->assoclen;
+
+    err = skcipher_walk_virt(&walk, &request, false);
+
+    //process assoc data if available
+    if (req->assoclen > 0) {
+        unsigned int assoc_remain, ghashlen;
+
+        assoc_remain = req->assoclen;
+        ghashlen = min(req->assoclen, walk.nbytes);
+        while ((nbytes = dec_bytes = ghashlen) && (ghashlen >= AES_BLOCK_SIZE)) {
+            u8 *temp;
+            if (nbytes > req->assoclen) nbytes = dec_bytes = req->assoclen;
+            dec_bytes -= (nbytes % AES_BLOCK_SIZE);
+            memcpy(walk.dst.virt.addr, walk.src.virt.addr, dec_bytes);
+            assoc_remain -= dec_bytes;
+            temp = walk.dst.virt.addr;
+            while (dec_bytes > 0) {
+                u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)temp);
+                gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+                dec_bytes -= AES_BLOCK_SIZE;
+                temp += 16;
+            }
+            if (assoc_remain < AES_BLOCK_SIZE) walk.stride = assoc_remain;
+            if (assoc_remain == 0) walk.stride = AES_BLOCK_SIZE;
+            dec_bytes = nbytes - (nbytes % AES_BLOCK_SIZE);
+            err = skcipher_walk_done(&walk, (walk.nbytes - dec_bytes));
+            ghashlen = min(assoc_remain, walk.nbytes);
+        }
+
+        if ((dec_bytes = ghashlen)) {
+            memcpy(ctx->lastbuffer, walk.src.virt.addr, dec_bytes);
+            memset(ctx->lastbuffer + dec_bytes, 0, (AES_BLOCK_SIZE - dec_bytes));
+            memcpy(walk.dst.virt.addr, walk.src.virt.addr, ghashlen);
+            u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)ctx->lastbuffer);
+            gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+            walk.stride = AES_BLOCK_SIZE;
+            err = skcipher_walk_done(&walk, (walk.nbytes - ghashlen));
+        }
+    }
+
+    //crypt and hash
+    while ((nbytes = dec_bytes = walk.nbytes) && (walk.nbytes >= AES_BLOCK_SIZE)) {
+        u8 *temp;
+        dec_bytes -= (nbytes % AES_BLOCK_SIZE);
+        temp = walk.src.virt.addr;
+        while (dec_bytes) {
+            u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)temp);
+            gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+            dec_bytes -= AES_BLOCK_SIZE;
+            temp += 16;
+        }
+        dec_bytes = nbytes - (nbytes % AES_BLOCK_SIZE);
+        ifx_deu_aes_ctr(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+                       iv, dec_bytes, CRYPTO_DIR_DECRYPT, 0);
+        nbytes &= AES_BLOCK_SIZE - 1;
+        err = skcipher_walk_done(&walk, nbytes);
+    }
+
+    /* crypt and hash remaining bytes < AES_BLOCK_SIZE */
+    if ((dec_bytes = walk.nbytes)) {
+        memcpy(ctx->lastbuffer, walk.src.virt.addr, dec_bytes);
+        memset(ctx->lastbuffer + dec_bytes, 0, (AES_BLOCK_SIZE - dec_bytes));
+        u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)ctx->lastbuffer);
+        gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+        ifx_deu_aes_ctr(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+                       iv, walk.nbytes, CRYPTO_DIR_DECRYPT, 0);
+        err = skcipher_walk_done(&walk, 0);
+    }
+
+    //finalize and copy hash
+    u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)&lengths);
+    gf128mul_4k_lle((be128 *)ctx->hash, ctx->gf128);
+    u128_xor((u128 *)ctx->hash, (u128 *)ctx->hash, (u128 *)ctx->block);
+
+    scatterwalk_map_and_copy(ctx->lastbuffer, req->src, req->cryptlen + req->assoclen - authsize, authsize, 0);
+    err = crypto_memneq(ctx->lastbuffer, ctx->hash, authsize) ? -EBADMSG : 0;
+
+    aead_request_complete(req, 0);
+
+    return err;
+}
+
+/*! \fn void aes_gcm_exit_tfm(struct crypto_tfm *tfm)
+ *  \ingroup IFX_aes_cbcmac_FUNCTIONS
+ *  \brief free pointers in aes_ctx
+ *  \param tfm linux crypto shash transform
+*/
+static void aes_gcm_exit_tfm(struct crypto_tfm *tfm)
+{
+    struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+    if (ctx->gf128) gf128mul_free_4k(ctx->gf128);
+}
+
+/*
+ * \brief AES function mappings
+*/
+struct aead_alg ifxdeu_gcm_aes_alg = {
+    .base.cra_name           =   "gcm(aes)",
+    .base.cra_driver_name    =   "ifxdeu-gcm(aes)",
+    .base.cra_priority       =   400,
+    .base.cra_flags          =   CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_KERN_DRIVER_ONLY,
+    .base.cra_blocksize      =   1,
+    .base.cra_ctxsize        =   sizeof(struct aes_ctx),
+    .base.cra_module         =   THIS_MODULE,
+    .base.cra_list           =   LIST_HEAD_INIT(ifxdeu_gcm_aes_alg.base.cra_list),
+    .base.cra_exit           =   aes_gcm_exit_tfm,
+    .ivsize                  =   GCM_AES_IV_SIZE,
+    .maxauthsize             =   AES_BLOCK_SIZE,
+    .chunksize               =   AES_BLOCK_SIZE,
+    .setkey                  =   aes_set_key_aead,
+    .encrypt                 =   gcm_aes_encrypt,
+    .decrypt                 =   gcm_aes_decrypt,
+    .setauthsize             =   gcm_aes_setauthsize,
+};
 
 /*! \fn int ifxdeu_init_aes (void)
  *  \ingroup IFX_AES_FUNCTIONS
@@ -1604,12 +1909,19 @@ int ifxdeu_init_aes (void)
     if ((ret = crypto_register_shash(&ifxdeu_cbcmac_aes_alg)))
         goto cbcmac_aes_err;
 
+    if ((ret = crypto_register_aead(&ifxdeu_gcm_aes_alg)))
+        goto gcm_aes_err;
+
     CRTCL_SECT_INIT;
 
 
     printk (KERN_NOTICE "IFX DEU AES initialized%s%s.\n", disable_multiblock ? "" : " (multiblock)", disable_deudma ? "" : " (DMA)");
     return ret;
 
+gcm_aes_err:
+    crypto_unregister_aead(&ifxdeu_gcm_aes_alg);
+    printk (KERN_ERR "IFX gcm_aes initialization failed!\n");
+    return ret;
 cbcmac_aes_err:
     crypto_unregister_shash(&ifxdeu_cbcmac_aes_alg);
     printk (KERN_ERR "IFX cbcmac_aes initialization failed!\n");
@@ -1663,4 +1975,5 @@ void ifxdeu_fini_aes (void)
     crypto_unregister_skcipher (&ifxdeu_ctr_basic_aes_alg);
     crypto_unregister_skcipher (&ifxdeu_ctr_rfc3686_aes_alg);
     crypto_unregister_shash (&ifxdeu_cbcmac_aes_alg);
+    crypto_unregister_aead (&ifxdeu_gcm_aes_alg);
 }