+ u8 nonce[IKEV2_GCM_NONCE_SIZE];
+
+ if (data_len <= IKEV2_GCM_IV_SIZE)
+ /* runt data */
+ return 0;
+
+ /* extract salt from the end of the key */
+ u8 *salt = key + vec_len (key) - IKEV2_GCM_SALT_SIZE;
+ ikev2_init_gcm_nonce (nonce, salt, data);
+
+ data += IKEV2_GCM_IV_SIZE;
+ data_len -= IKEV2_GCM_IV_SIZE;
+
+ EVP_DecryptInit_ex (ctx, tr_encr->cipher, 0, 0, 0);
+ EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0);
+ EVP_DecryptInit_ex (ctx, 0, 0, key, nonce);
+ EVP_DecryptUpdate (ctx, 0, &len, aad, aad_len);
+ EVP_DecryptUpdate (ctx, data, &len, data, data_len);
+ EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_TAG, IKEV2_GCM_ICV_SIZE, tag);
+
+ if (EVP_DecryptFinal_ex (ctx, data + len, &len) > 0)
+ {
+ *out_len = data_len - data[data_len - 1] - 1;
+ return 1;
+ }
+
+ return 0;
+}