/**********************************************************************
  Copyright(c) 2021-2022 Intel Corporation All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the
      distribution.
    * Neither the name of Intel Corporation nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "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 COPYRIGHT
  OWNER 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 <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>		/* for memcmp() */
#include <assert.h>

#include <intel-ipsec-mb.h>
#include "gcm_ctr_vectors_test.h"
#include "utils.h"

#define MAX_BUFFER_LENGTH_IN_BYTES 128

int snow_v_test(IMB_MGR *p_mgr);
/**
 * Test vectors for SNOW-V-GCM from 'A new SNOW stream cipher called SNOW-V',
 * Patrik Ekdahl1, Thomas Johansson2, Alexander Maximov1 and Jing Yang2
**/
static const uint8_t ZERO_KEY[] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const uint8_t ZERO_IV[] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const uint8_t MAX_KEY[] = {
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const uint8_t MAX_IV[] = {
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const uint8_t IV_spec[] = {
        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
        0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
};
static const uint8_t KEY_spec[] = {
        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
        0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
        0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a,
        0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa
};
static const uint8_t ZERO_PLAIN[] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const uint8_t keystreams_from_spec[][128] = {
        {
                0x69, 0xca, 0x6d, 0xaf, 0x9a, 0xe3, 0xb7, 0x2d,
                0xb1, 0x34, 0xa8, 0x5a, 0x83, 0x7e, 0x41, 0x9d,
                0xec, 0x08, 0xaa, 0xd3, 0x9d, 0x7b, 0x0f, 0x00,
                0x9b, 0x60, 0xb2, 0x8c, 0x53, 0x43, 0x00, 0xed,
                0x84, 0xab, 0xf5, 0x94, 0xfb, 0x08, 0xa7, 0xf1,
                0xf3, 0xa2, 0xdf, 0x18, 0xe6, 0x17, 0x68, 0x3b,
                0x48, 0x1f, 0xa3, 0x78, 0x07, 0x9d, 0xcf, 0x04,
                0xdb, 0x53, 0xb5, 0xd6, 0x29, 0xa9, 0xeb, 0x9d,
                0x03, 0x1c, 0x15, 0x9d, 0xcc, 0xd0, 0xa5, 0x0c,
                0x4d, 0x5d, 0xbf, 0x51, 0x15, 0xd8, 0x70, 0x39,
                0xc0, 0xd0, 0x3c, 0xa1, 0x37, 0x0c, 0x19, 0x40,
                0x03, 0x47, 0xa0, 0xb4, 0xd2, 0xe9, 0xdb, 0xe5,
                0xcb, 0xca, 0x60, 0x82, 0x14, 0xa2, 0x65, 0x82,
                0xcf, 0x68, 0x09, 0x16, 0xb3, 0x45, 0x13, 0x21,
                0x95, 0x4f, 0xdf, 0x30, 0x84, 0xaf, 0x02, 0xf6,
                0xa8, 0xe2, 0x48, 0x1d, 0xe6, 0xbf, 0x82, 0x79
        },
        {
                0x30, 0x76, 0x09, 0xfb, 0x10, 0x10, 0x12, 0x54,
                0x4b, 0xc1, 0x75, 0xe3, 0x17, 0xfb, 0x25, 0xff,
                0x33, 0x0d, 0x0d, 0xe2, 0x5a, 0xf6, 0xaa, 0xd1,
                0x05, 0x05, 0xb8, 0x9b, 0x1e, 0x09, 0xa8, 0xec,
                0xdd, 0x46, 0x72, 0xcc, 0xbb, 0x98, 0xc7, 0xf2,
                0xc4, 0xe2, 0x4a, 0xf5, 0x27, 0x28, 0x36, 0xc8,
                0x7c, 0xc7, 0x3a, 0x81, 0x76, 0xb3, 0x9c, 0xe9,
                0x30, 0x3b, 0x3e, 0x76, 0x4e, 0x9b, 0xe3, 0xe7,
                0x48, 0xf7, 0x65, 0x1a, 0x7c, 0x7e, 0x81, 0x3f,
                0xd5, 0x24, 0x90, 0x23, 0x1e, 0x56, 0xf7, 0xc1,
                0x44, 0xe4, 0x38, 0xe7, 0x77, 0x11, 0xa6, 0xb0,
                0xba, 0xfb, 0x60, 0x45, 0x0c, 0x62, 0xd7, 0xd9,
                0xb9, 0x24, 0x1d, 0x12, 0x44, 0xfc, 0xb4, 0x9d,
                0xa1, 0xe5, 0x2b, 0x80, 0x13, 0xde, 0xcd, 0xd4,
                0x86, 0x04, 0xff, 0xfc, 0x62, 0x67, 0x6e, 0x70,
                0x3b, 0x3a, 0xb8, 0x49, 0xcb, 0xa6, 0xea, 0x09
        },
        {
                0xaa, 0x81, 0xea, 0xfb, 0x8b, 0x86, 0x16, 0xce,
                0x3e, 0x5c, 0xe2, 0x22, 0x24, 0x61, 0xc5, 0x0a,
                0x6a, 0xb4, 0x48, 0x77, 0x56, 0xde, 0x4b, 0xd3,
                0x1c, 0x90, 0x4f, 0x3d, 0x97, 0x8a, 0xfe, 0x56,
                0x33, 0x4f, 0x10, 0xdd, 0xdf, 0x2b, 0x95, 0x31,
                0x76, 0x9a, 0x71, 0x05, 0x0b, 0xe4, 0x38, 0x5f,
                0xc2, 0xb6, 0x19, 0x2c, 0x7a, 0x85, 0x7b, 0xe8,
                0xb4, 0xfc, 0x28, 0xb7, 0x09, 0xf0, 0x8f, 0x11,
                0xf2, 0x06, 0x49, 0xe2, 0xee, 0xf2, 0x49, 0x80,
                0xf8, 0x6c, 0x4c, 0x11, 0x36, 0x41, 0xfe, 0xd2,
                0xf3, 0xf6, 0xfa, 0x2b, 0x91, 0x95, 0x12, 0x06,
                0xb8, 0x01, 0xdb, 0x15, 0x46, 0x65, 0x17, 0xa6,
                0x33, 0x0a, 0xdd, 0xa6, 0xb3, 0x5b, 0x26, 0x5e,
                0xfd, 0x72, 0x2e, 0x86, 0x77, 0xb4, 0x8b, 0xfc,
                0x15, 0xb4, 0x41, 0x18, 0xde, 0x52, 0xd0, 0x73,
                0xb0, 0xad, 0x0f, 0xe7, 0x59, 0x4d, 0x62, 0x91
        }
};

static const uint8_t KEYs[][32] = {
        {
                0x67, 0xc6, 0x69, 0x73, 0x51, 0xff, 0x4a, 0xec,
                0x29, 0xcd, 0xba, 0xab, 0xf2, 0xfb, 0xe3, 0x46,
                0x7c, 0xc2, 0x54, 0xf8, 0x1b, 0xe8, 0xe7, 0x8d,
                0x76, 0x5a, 0x2e, 0x63, 0x33, 0x9f, 0xc9, 0x9a
        },
        {
                0xab, 0xb2, 0xcd, 0xc6, 0x9b, 0xb4, 0x54, 0x11,
                0x0e, 0x82, 0x74, 0x41, 0x21, 0x3d, 0xdc, 0x87,
                0x70, 0xe9, 0x3e, 0xa1, 0x41, 0xe1, 0xfc, 0x67,
                0x3e, 0x01, 0x7e, 0x97, 0xea, 0xdc, 0x6b, 0x96
        },
        {
                0x02, 0x1a, 0xfe, 0x43, 0xfb, 0xfa, 0xaa, 0x3a,
                0xfb, 0x29, 0xd1, 0xe6, 0x05, 0x3c, 0x7c, 0x94,
                0x75, 0xd8, 0xbe, 0x61, 0x89, 0xf9, 0x5c, 0xbb,
                0xa8, 0x99, 0x0f, 0x95, 0xb1, 0xeb, 0xf1, 0xb3
        },
        {
                0x1f, 0x23, 0x1e, 0xa8, 0x1c, 0x7b, 0x64, 0xc5,
                0x14, 0x73, 0x5a, 0xc5, 0x5e, 0x4b, 0x79, 0x63,
                0x3b, 0x70, 0x64, 0x24, 0x11, 0x9e, 0x09, 0xdc,
                0xaa, 0xd4, 0xac, 0xf2, 0x1b, 0x10, 0xaf, 0x3b
        },
        {
                0x0b, 0xe1, 0x1a, 0x1c, 0x7f, 0x23, 0xf8, 0x29,
                0xf8, 0xa4, 0x1b, 0x13, 0xb5, 0xca, 0x4e, 0xe8,
                0x98, 0x32, 0x38, 0xe0, 0x79, 0x4d, 0x3d, 0x34,
                0xbc, 0x5f, 0x4e, 0x77, 0xfa, 0xcb, 0x6c, 0x05
        },
        {
                0x36, 0x94, 0xb3, 0xaf, 0xe2, 0xf0, 0xe4, 0x9e,
                0x4f, 0x32, 0x15, 0x49, 0xfd, 0x82, 0x4e, 0xa9,
                0x08, 0x70, 0xd4, 0xb2, 0x8a, 0x29, 0x54, 0x48,
                0x9a, 0x0a, 0xbc, 0xd5, 0x0e, 0x18, 0xa8, 0x44
        },
        {
                0xa3, 0x84, 0x7f, 0x2d, 0xad, 0xd4, 0x76, 0x47,
                0xde, 0x32, 0x1c, 0xec, 0x4a, 0xc4, 0x30, 0xf6,
                0x20, 0x23, 0x85, 0x6c, 0xfb, 0xb2, 0x07, 0x04,
                0xf4, 0xec, 0x0b, 0xb9, 0x20, 0xba, 0x86, 0xc3
        },
        {
                0xf7, 0x5e, 0xa0, 0xf2, 0x10, 0xa8, 0xf6, 0x05,
                0x94, 0x01, 0xbe, 0xb4, 0xbc, 0x44, 0x78, 0xfa,
                0x49, 0x69, 0xe6, 0x23, 0xd0, 0x1a, 0xda, 0x69,
                0x6a, 0x7e, 0x4c, 0x7e, 0x51, 0x25, 0xb3, 0x48
        },
        {
                0x25, 0xcf, 0x08, 0xf5, 0xe9, 0xe2, 0x5e, 0x53,
                0x60, 0xaa, 0xd2, 0xb2, 0xd0, 0x85, 0xfa, 0x54,
                0xd8, 0x35, 0xe8, 0xd4, 0x66, 0x82, 0x64, 0x98,
                0xd9, 0xa8, 0x87, 0x75, 0x65, 0x70, 0x5a, 0x8a
        },
        {
                0x86, 0x95, 0x80, 0xec, 0x17, 0xe4, 0x85, 0xf1,
                0x8c, 0x0c, 0x66, 0xf1, 0x7c, 0xc0, 0x7c, 0xbb,
                0x22, 0xfc, 0xe4, 0x66, 0xda, 0x61, 0x0b, 0x63,
                0xaf, 0x62, 0xbc, 0x83, 0xb4, 0x69, 0x2f, 0x3a
        },
}; /* KEYs */

static const uint8_t IVs[][16] = {
        {
                0x66, 0x32, 0x0d, 0xb7, 0x31, 0x58, 0xa3, 0x5a,
                0x25, 0x5d, 0x05, 0x17, 0x58, 0xe9, 0x5e, 0xd4
        },
        {
                0x8f, 0x38, 0x5c, 0x2a, 0xec, 0xb0, 0x3b, 0xfb,
                0x32, 0xaf, 0x3c, 0x54, 0xec, 0x18, 0xdb, 0x5c
        },
        {
                0x05, 0xef, 0xf7, 0x00, 0xe9, 0xa1, 0x3a, 0xe5,
                0xca, 0x0b, 0xcb, 0xd0, 0x48, 0x47, 0x64, 0xbd
        },
        {
                0x33, 0xcd, 0xe3, 0x50, 0x48, 0x47, 0x15, 0x5c,
                0xbb, 0x6f, 0x22, 0x19, 0xba, 0x9b, 0x7d, 0xf5
        },
        {
                0xac, 0x86, 0x21, 0x2b, 0xaa, 0x1a, 0x55, 0xa2,
                0xbe, 0x70, 0xb5, 0x73, 0x3b, 0x04, 0x5c, 0xd3
        },
        {
                0xac, 0x5b, 0xf3, 0x8e, 0x4c, 0xd7, 0x2d, 0x9b,
                0x09, 0x42, 0xe5, 0x06, 0xc4, 0x33, 0xaf, 0xcd
        },
        {
                0x3e, 0x05, 0xf1, 0xec, 0xd9, 0x67, 0x33, 0xb7,
                0x99, 0x50, 0xa3, 0xe3, 0x14, 0xd3, 0xd9, 0x34
        },
        {
                0x84, 0x53, 0x3a, 0x94, 0xfb, 0x31, 0x99, 0x90,
                0x32, 0x57, 0x44, 0xee, 0x9b, 0xbc, 0xe9, 0xe5
        },
        {
                0x3f, 0x62, 0x80, 0x29, 0x44, 0xde, 0x7c, 0xa5,
                0x89, 0x4e, 0x57, 0x59, 0xd3, 0x51, 0xad, 0xac
        },
        {
                0xff, 0xaf, 0x27, 0x16, 0x93, 0xac, 0x07, 0x1f,
                0xb8, 0x6d, 0x11, 0x34, 0x2d, 0x8d, 0xef, 0x4f
        },
}; /* IVs */

static const uint8_t PLAIN_1[] = { 0x89 };
static const uint8_t CIPHER_1[] = { 0x12 };
static const uint8_t CIPHER_1_ZERO_KEY[] = { 0x0e };
static const uint8_t CIPHER_1_MAX_KEY[] = { 0x2a };
static const uint8_t CIPHER_1_MAX_KEY_IV[] = { 0xb9 };
static const uint8_t CIPHER_1_ZERO_KEY_IV[] = { 0xe0 };
static const uint8_t CIPHER_1_MAX_IV[] = { 0x35 };
static const uint8_t CIPHER_1_ZERO_IV[] = { 0x03 };
static const uint8_t PLAIN_8[] = {
        0xd4, 0xb6, 0x63, 0x35, 0xc1, 0xc7, 0xe4, 0x24 };
static const uint8_t CIPHER_8[] = {
        0x46, 0xde, 0xc7, 0xed, 0xc3, 0xff, 0x4b, 0xd2 };
static const uint8_t CIPHER_8_ZERO_KEY[] = {
        0xbc, 0xd6, 0xd0, 0x0d, 0x57, 0x36, 0x7d, 0x3b };
static const uint8_t CIPHER_8_MAX_KEY[] = {
        0x7a, 0x47, 0x95, 0x16, 0xee, 0x25, 0xdd, 0x37 };
static const uint8_t CIPHER_8_MAX_KEY_IV[] = {
        0xe4, 0xc0, 0x6a, 0xce, 0xd1, 0xd7, 0xf6, 0x70 };
static const uint8_t CIPHER_8_ZERO_KEY_IV[] = {
        0xbd, 0x7c, 0x0e, 0x9a, 0x5b, 0x24, 0x53, 0x09 };
static const uint8_t CIPHER_8_MAX_IV[] = {
        0xab, 0x8b, 0xf1, 0xb2, 0xa5, 0xfb, 0x20, 0xfc };
static const uint8_t CIPHER_8_ZERO_IV[] = {
        0x70, 0xe9, 0x3f, 0x73, 0x20, 0xe0, 0xf6, 0xe5 };
static const uint8_t PLAIN_15[] = {
        0x83, 0x67, 0xd8, 0xed, 0x96, 0x12, 0xec, 0x45,
        0x39, 0x02, 0xd8, 0xe5, 0x0a, 0xf8, 0x9d
};
static const uint8_t CIPHER_15[] = {
        0xd3, 0x15, 0x8d, 0x06, 0x49, 0x58, 0xcc, 0x57,
        0xc4, 0xa7, 0x39, 0x38, 0x9b, 0x25, 0xb6
};
static const uint8_t CIPHER_15_ZERO_KEY[] = {
        0x6e, 0xdd, 0x4a, 0xda, 0xf2, 0x30, 0x33, 0x57,
        0x74, 0x59, 0xd1, 0xbc, 0xe8, 0x40, 0xd5
};
static const uint8_t CIPHER_15_MAX_KEY[] = {
        0xb3, 0xd5, 0xa1, 0x7e, 0x78, 0xa0, 0x13, 0xb5,
        0xa8, 0xa8, 0x22, 0x86, 0xfc, 0x83, 0xc1
};
static const uint8_t CIPHER_15_MAX_KEY_IV[] = {
        0xb3, 0x11, 0xd1, 0x16, 0x86, 0x02, 0xfe, 0x11,
        0x72, 0xc3, 0xad, 0x06, 0x1d, 0x03, 0xb8
};
static const uint8_t CIPHER_15_ZERO_KEY_IV[] = {
        0xea, 0xad, 0xb5, 0x42, 0x0c, 0xf1, 0x5b, 0x68,
        0x88, 0x36, 0x70, 0xbf, 0x89, 0x86, 0xdc
};
static const uint8_t CIPHER_15_MAX_IV[] = {
        0x3e, 0x43, 0x7d, 0x8b, 0xaa, 0xc6, 0x2d, 0x78,
        0x37, 0x16, 0x0f, 0xe9, 0xdd, 0x09, 0xc8
};
static const uint8_t CIPHER_15_ZERO_IV[] = {
        0x8c, 0x30, 0x1f, 0x67, 0x2e, 0xcf, 0x0d, 0x6f,
        0xea, 0x8b, 0x83, 0x51, 0x8a, 0x4f, 0x32
};
static const uint8_t PLAIN_16[] = {
        0x77, 0x09, 0xd1, 0xa5, 0x96, 0xc1, 0xf4, 0x1f,
        0x95, 0xaa, 0x82, 0xca, 0x6c, 0x49, 0xae, 0x90
};
static const uint8_t CIPHER_16[] = {
        0x16, 0x4c, 0x52, 0xa5, 0xed, 0x36, 0x8f, 0xaf,
        0x34, 0x17, 0x3b, 0x25, 0xd7, 0xb9, 0x96, 0x86
};
static const uint8_t CIPHER_16_ZERO_KEY[] = {
        0xae, 0xb6, 0x70, 0x05, 0x7c, 0xc2, 0xc0, 0x2b,
        0xcd, 0x8b, 0xc3, 0x60, 0x80, 0x61, 0xe5, 0x50
};
static const uint8_t CIPHER_16_MAX_KEY[] = {
        0x96, 0x19, 0xac, 0xd2, 0x52, 0xbf, 0xfb, 0x24,
        0x34, 0x82, 0x0c, 0xd1, 0xd9, 0x21, 0x41, 0xe9
};
static const uint8_t CIPHER_16_MAX_KEY_IV[] = {
        0x47, 0x7f, 0xd8, 0x5e, 0x86, 0xd1, 0xe6, 0x4b,
        0xde, 0x6b, 0xf7, 0x29, 0x7b, 0xb2, 0x8b, 0x6f
};
static const uint8_t CIPHER_16_ZERO_KEY_IV[] = {
        0x1e, 0xc3, 0xbc, 0x0a, 0x0c, 0x22, 0x43, 0x32,
        0x24, 0x9e, 0x2a, 0x90, 0xef, 0x37, 0xef, 0x0d
};
static const uint8_t CIPHER_16_MAX_IV[] = {
        0x70, 0x3d, 0x33, 0xd6, 0xae, 0xc6, 0x27, 0x47,
        0x57, 0xf7, 0xfa, 0x57, 0x77, 0xab, 0x6b, 0x14
};
static const uint8_t CIPHER_16_ZERO_IV[] = {
        0x41, 0x1c, 0xe0, 0xe4, 0x41, 0x7c, 0x9a, 0xa6,
        0xff, 0x00, 0x00, 0x83, 0xe6, 0xf9, 0xea, 0x8a
};
static const uint8_t PLAIN_17[] = {
        0xcd, 0x16, 0x68, 0xba, 0xac, 0x7a, 0xa6, 0xf2,
        0xb4, 0xa8, 0xca, 0x99, 0xb2, 0xc2, 0x37, 0x2a,
        0xcb
};
static const uint8_t CIPHER_17[] = {
        0xd4, 0x61, 0x94, 0x70, 0x87, 0x9b, 0x83, 0xa8,
        0x1f, 0xc9, 0x94, 0xc4, 0x91, 0x4f, 0xa8, 0xe4,
        0x29
};
static const uint8_t CIPHER_17_ZERO_KEY[] = {
        0x02, 0x78, 0xe0, 0xce, 0xed, 0xab, 0xeb, 0xb0,
        0x19, 0x65, 0xf5, 0xac, 0x31, 0x21, 0x1e, 0x43,
        0xf0
};
static const uint8_t CIPHER_17_MAX_KEY[] = {
        0xbb, 0xce, 0x3a, 0x68, 0x13, 0x27, 0x79, 0xc9,
        0x45, 0x71, 0x2f, 0x6d, 0x20, 0xb4, 0x00, 0x06,
        0xd5
};
static const uint8_t CIPHER_17_MAX_KEY_IV[] = {
        0xfd, 0x60, 0x61, 0x41, 0xbc, 0x6a, 0xb4, 0xa6,
        0xff, 0x69, 0xbf, 0x7a, 0xa5, 0x39, 0x12, 0xd5,
        0xf8
};
static const uint8_t CIPHER_17_ZERO_KEY_IV[] = {
        0xa4, 0xdc, 0x05, 0x15, 0x36, 0x99, 0x11, 0xdf,
        0x05, 0x9c, 0x62, 0xc3, 0x31, 0xbc, 0x76, 0xb7,
        0x27
};
static const uint8_t CIPHER_17_MAX_IV[] = {
        0x6c, 0x12, 0x44, 0x15, 0x4d, 0x28, 0xf1, 0xdb,
        0x5f, 0x3c, 0x49, 0x88, 0xa1, 0xb6, 0xce, 0x84,
        0x5f
};
static const uint8_t CIPHER_17_ZERO_IV[] = {
        0x0a, 0x61, 0x65, 0x53, 0x74, 0x0e, 0x7e, 0x01,
        0x61, 0xd2, 0xb2, 0xc9, 0x91, 0x3c, 0x80, 0x01,
        0xda
};
static const uint8_t PLAIN_48[] = {
        0x08, 0xcf, 0x61, 0xc9, 0xc3, 0x80, 0x5e, 0x6e,
        0x03, 0x28, 0xda, 0x4c, 0xd7, 0x6a, 0x19, 0xed,
        0xd2, 0xd3, 0x99, 0x4c, 0x79, 0x8b, 0x00, 0x22,
        0x56, 0x9a, 0xd4, 0x18, 0xd1, 0xfe, 0xe4, 0xd9,
        0xcd, 0x45, 0xa3, 0x91, 0xc6, 0x01, 0xff, 0xc9,
        0x2a, 0xd9, 0x15, 0x01, 0x43, 0x2f, 0xee, 0x15
};
static const uint8_t CIPHER_48[] = {
        0xcd, 0x4a, 0x37, 0x9b, 0xc4, 0x8b, 0xa1, 0xd4,
        0xda, 0x27, 0x68, 0x12, 0xdf, 0xce, 0x9c, 0x32,
        0x8a, 0x59, 0x1e, 0x3e, 0x37, 0xe0, 0x04, 0xf7,
        0xae, 0x31, 0x2f, 0xed, 0xe6, 0x0d, 0x78, 0x7c,
        0xe6, 0xd1, 0x6a, 0xde, 0x99, 0xb3, 0x0e, 0x42,
        0xca, 0x83, 0x62, 0x60, 0x99, 0xa7, 0x6f, 0xcc
};
static const uint8_t CIPHER_48_ZERO_KEY[] = {
        0xed, 0x78, 0x21, 0x2b, 0x90, 0xa3, 0xd4, 0x3d,
        0xe9, 0x84, 0x77, 0x37, 0xca, 0xa6, 0x16, 0xa9,
        0x5d, 0x84, 0x2f, 0x25, 0xb0, 0xb9, 0x38, 0x8b,
        0xde, 0x28, 0x66, 0xee, 0x35, 0xe0, 0x05, 0x56,
        0x16, 0x40, 0x68, 0xcf, 0xcd, 0x33, 0xdc, 0xb8,
        0xe4, 0x74, 0x23, 0xf9, 0xef, 0xcf, 0x92, 0xc5
};
static const uint8_t CIPHER_48_MAX_KEY[] = {
        0x92, 0x9a, 0xd1, 0x31, 0x54, 0x33, 0xdb, 0x09,
        0x18, 0x43, 0x31, 0xb9, 0x04, 0x6f, 0x2e, 0x32,
        0x82, 0x25, 0x2d, 0xbf, 0x9e, 0x7b, 0x56, 0xd3,
        0xc8, 0x20, 0xd7, 0x5f, 0xb4, 0x34, 0x13, 0x9e,
        0xc1, 0x55, 0x44, 0xc1, 0xd0, 0xac, 0x61, 0x5b,
        0x27, 0x59, 0xc8, 0x23, 0x2d, 0x00, 0xf2, 0x95
};
static const uint8_t CIPHER_48_MAX_KEY_IV[] = {
        0x38, 0xb9, 0x68, 0x32, 0xd3, 0x90, 0x4c, 0x3a,
        0x48, 0xe9, 0xaf, 0xaf, 0xc0, 0x91, 0x3c, 0x12,
        0xe1, 0xde, 0x94, 0xae, 0x23, 0x7d, 0xaa, 0xf3,
        0x53, 0x9f, 0x6c, 0x83, 0xcf, 0xf7, 0x4c, 0x35,
        0x10, 0x03, 0xd1, 0x5d, 0x7d, 0x99, 0x38, 0x3b,
        0xee, 0x3b, 0x5f, 0xf4, 0x64, 0x07, 0xd8, 0xdd
};
static const uint8_t CIPHER_48_ZERO_KEY_IV[] = {
        0x61, 0x05, 0x0c, 0x66, 0x59, 0x63, 0xe9, 0x43,
        0xb2, 0x1c, 0x72, 0x16, 0x54, 0x14, 0x58, 0x70,
        0x3e, 0xdb, 0x33, 0x9f, 0xe4, 0xf0, 0x0f, 0x22,
        0xcd, 0xfa, 0x66, 0x94, 0x82, 0xbd, 0xe4, 0x34,
        0x49, 0xee, 0x56, 0x05, 0x3d, 0x09, 0x58, 0x38,
        0xd9, 0x7b, 0xca, 0x19, 0xa5, 0x38, 0x86, 0x2e
};
static const uint8_t CIPHER_48_MAX_IV[] = {
        0xba, 0xf1, 0x73, 0xa1, 0x57, 0x58, 0xf1, 0xf1,
        0x6b, 0x9e, 0x41, 0xa8, 0xc7, 0xdd, 0xef, 0x13,
        0x1e, 0x91, 0xb1, 0x45, 0x70, 0x5b, 0x83, 0x40,
        0x42, 0x5d, 0x70, 0xcf, 0x01, 0x7c, 0x8a, 0x90,
        0x0c, 0x10, 0x3b, 0x6d, 0xdd, 0x81, 0x04, 0xa2,
        0x66, 0x6e, 0x0f, 0xaf, 0xf3, 0x75, 0x92, 0x1f
};
static const uint8_t CIPHER_48_ZERO_IV[] = {
        0x23, 0x46, 0x9f, 0xcd, 0x94, 0xd4, 0x9a, 0x62,
        0x5e, 0x37, 0xe9, 0x11, 0xc2, 0x90, 0x22, 0x16,
        0xe3, 0x78, 0xaf, 0x06, 0x9e, 0xf8, 0x68, 0x43,
        0x85, 0x20, 0x28, 0xae, 0xc6, 0x2e, 0x71, 0x64,
        0x4d, 0x4b, 0xae, 0xbf, 0x94, 0x69, 0x4c, 0xf4,
        0x6c, 0x93, 0xb0, 0x81, 0x40, 0xaf, 0xf2, 0x27
};
static const uint8_t PLAIN_63[] = {
        0x02, 0x87, 0x61, 0x7c, 0x13, 0x62, 0x9e, 0x69,
        0xfc, 0x72, 0x81, 0xcd, 0x71, 0x65, 0xa6, 0x3e,
        0xab, 0x49, 0xcf, 0x71, 0x4b, 0xce, 0x3a, 0x75,
        0xa7, 0x4f, 0x76, 0xea, 0x7e, 0x64, 0xff, 0x81,
        0xeb, 0x61, 0xfd, 0xfe, 0xc3, 0x9b, 0x67, 0xbf,
        0x0d, 0xe9, 0x8c, 0x7e, 0x4e, 0x32, 0xbd, 0xf9,
        0x7c, 0x8c, 0x6a, 0xc7, 0x5b, 0xa4, 0x3c, 0x02,
        0xf4, 0xb2, 0xed, 0x72, 0x16, 0xec, 0xf3
};
static const uint8_t CIPHER_63[] = {
        0xbf, 0xc8, 0x9e, 0x4c, 0xcf, 0x93, 0x3e, 0x48,
        0x66, 0xe3, 0xc8, 0x15, 0x4d, 0xf9, 0x54, 0xcd,
        0x9a, 0x03, 0xae, 0xac, 0x2e, 0x8a, 0xa1, 0x83,
        0xfb, 0x25, 0xa1, 0xe3, 0x9b, 0xd0, 0x8f, 0x46,
        0x19, 0x0d, 0x25, 0x12, 0xd6, 0x97, 0x41, 0x79,
        0xe9, 0x7e, 0x57, 0x56, 0x9a, 0x27, 0xa2, 0x24,
        0x8e, 0x04, 0xf2, 0x20, 0x42, 0xcf, 0xff, 0x3e,
        0x15, 0x4a, 0x1b, 0x9b, 0x57, 0x2e, 0xf7
};
static const uint8_t CIPHER_63_ZERO_KEY[] = {
        0xd6, 0xb0, 0xe9, 0xb6, 0x89, 0x0c, 0xd0, 0x21,
        0x15, 0x34, 0xf7, 0x47, 0xc2, 0xd9, 0xf9, 0x9c,
        0xcd, 0xec, 0x81, 0xa0, 0x06, 0x58, 0xe9, 0x0d,
        0x6e, 0x12, 0x1d, 0x0e, 0xb4, 0x4a, 0x02, 0xc2,
        0x1d, 0xca, 0x52, 0x69, 0xf1, 0xfd, 0xdc, 0x32,
        0x48, 0x80, 0x94, 0x0f, 0x0c, 0x49, 0xd9, 0x15,
        0x70, 0x87, 0xb0, 0x47, 0x0c, 0xd3, 0x6f, 0x5a,
        0x36, 0x5e, 0x5c, 0x4d, 0x6e, 0x39, 0x49
};
static const uint8_t CIPHER_63_MAX_KEY[] = {
        0xe2, 0xfe, 0x73, 0x01, 0x6a, 0xfe, 0x53, 0x9f,
        0xfd, 0x08, 0x83, 0x8c, 0xf5, 0x4f, 0x7a, 0x83,
        0xf2, 0x6d, 0xef, 0x53, 0xfd, 0xa0, 0xf6, 0xa3,
        0x6f, 0xf9, 0x6e, 0xd5, 0xf2, 0xdd, 0x41, 0x94,
        0x41, 0x81, 0x55, 0xe0, 0x6b, 0xdc, 0xf3, 0x77,
        0x8b, 0x1a, 0x8a, 0x69, 0xce, 0xa9, 0xb6, 0x58,
        0xb7, 0x61, 0x42, 0x17, 0x1a, 0xf2, 0x46, 0x42,
        0x78, 0xa8, 0x22, 0xeb, 0x29, 0x7c, 0xb8
};
static const uint8_t CIPHER_63_MAX_KEY_IV[] = {
        0x32, 0xf1, 0x68, 0x87, 0x03, 0x72, 0x8c, 0x3d,
        0xb7, 0xb3, 0xf4, 0x2e, 0x66, 0x9e, 0x83, 0xc1,
        0x98, 0x44, 0xc2, 0x93, 0x11, 0x38, 0x90, 0xa4,
        0xa2, 0x4a, 0xce, 0x71, 0x60, 0x6d, 0x57, 0x6d,
        0x36, 0x27, 0x8f, 0x32, 0x78, 0x03, 0xa0, 0x4d,
        0xc9, 0x0b, 0xc6, 0x8b, 0x69, 0x1a, 0x8b, 0x31,
        0x00, 0x4b, 0x50, 0x46, 0x2d, 0x17, 0xa0, 0xeb,
        0xc4, 0x89, 0xd3, 0x04, 0x58, 0x77, 0x10
};
static const uint8_t CIPHER_63_ZERO_KEY_IV[] = {
        0x6b, 0x4d, 0x0c, 0xd3, 0x89, 0x81, 0x29, 0x44,
        0x4d, 0x46, 0x29, 0x97, 0xf2, 0x1b, 0xe7, 0xa3,
        0x47, 0x41, 0x65, 0xa2, 0xd6, 0xb5, 0x35, 0x75,
        0x3c, 0x2f, 0xc4, 0x66, 0x2d, 0x27, 0xff, 0x6c,
        0x6f, 0xca, 0x08, 0x6a, 0x38, 0x93, 0xc0, 0x4e,
        0xfe, 0x4b, 0x53, 0x66, 0xa8, 0x25, 0xd5, 0xc2,
        0x34, 0x93, 0xc9, 0xbf, 0x5c, 0x39, 0xf3, 0x06,
        0x2f, 0xe1, 0x58, 0xa4, 0x3f, 0x45, 0x18
};
static const uint8_t CIPHER_63_MAX_IV[] = {
        0x0c, 0xbc, 0x6e, 0x7c, 0x67, 0xa7, 0x49, 0x0f,
        0xd9, 0x0a, 0x6e, 0x5a, 0xe0, 0xe0, 0x82, 0xbd,
        0x32, 0x64, 0xdf, 0xe4, 0xec, 0x68, 0x94, 0xe4,
        0x7d, 0x77, 0x44, 0x0d, 0x7f, 0x64, 0xfd, 0xb0,
        0x51, 0xda, 0x68, 0x8a, 0x17, 0x08, 0xce, 0x5d,
        0x0d, 0x56, 0x38, 0x7d, 0x6a, 0xf5, 0x3d, 0x41,
        0x7a, 0xa1, 0xdd, 0xea, 0xd2, 0x58, 0xb0, 0x45,
        0xd0, 0xea, 0xcb, 0xd2, 0x43, 0x5e, 0x4d
};
static const uint8_t CIPHER_63_ZERO_IV[] = {
        0x90, 0xfb, 0x35, 0x72, 0xf3, 0x45, 0x99, 0xed,
        0x9c, 0x72, 0x8d, 0xd7, 0x14, 0x38, 0xea, 0xd0,
        0xbd, 0xea, 0x2e, 0xd8, 0x27, 0x34, 0xc9, 0xa6,
        0x50, 0x56, 0xb5, 0xd0, 0x8c, 0x6f, 0xe9, 0x40,
        0xbb, 0x98, 0xd2, 0xba, 0xf3, 0x77, 0x1b, 0x79,
        0x8f, 0x8a, 0x88, 0x2b, 0x13, 0x91, 0x86, 0x20,
        0x77, 0x73, 0x5b, 0x7d, 0xef, 0x34, 0xfc, 0xde,
        0x9b, 0xed, 0xff, 0xe1, 0x3d, 0x1d, 0xf5
};
static const uint8_t PLAIN_64[] = {
        0x01, 0x4d, 0xf0, 0x00, 0x10, 0x8b, 0x67, 0xcf,
        0x99, 0x50, 0x5b, 0x17, 0x9f, 0x8e, 0xd4, 0x98,
        0x0a, 0x61, 0x03, 0xd1, 0xbc, 0xa7, 0x0d, 0xbe,
        0x9b, 0xbf, 0xab, 0x0e, 0xd5, 0x98, 0x01, 0xd6,
        0xe5, 0xf2, 0xd6, 0xf6, 0x7d, 0x3e, 0xc5, 0x16,
        0x8e, 0x21, 0x2e, 0x2d, 0xaf, 0x02, 0xc6, 0xb9,
        0x63, 0xc9, 0x8a, 0x1f, 0x70, 0x97, 0xde, 0x0c,
        0x56, 0x89, 0x1a, 0x2b, 0x21, 0x1b, 0x01, 0x07
};
static const uint8_t CIPHER_64[] = {
        0x34, 0x6c, 0xaa, 0xc1, 0xa3, 0x38, 0xad, 0x4e,
        0xcf, 0x42, 0x89, 0x2e, 0x30, 0xd4, 0x3d, 0xf5,
        0x99, 0xce, 0xeb, 0xe3, 0x15, 0x2d, 0xf4, 0xaa,
        0x51, 0x67, 0x10, 0x8e, 0x75, 0x09, 0xec, 0x45,
        0x31, 0xd6, 0x0d, 0xa3, 0x4d, 0x90, 0x35, 0x37,
        0xb1, 0x16, 0xcb, 0xb5, 0x5c, 0x57, 0xc3, 0x4f,
        0x04, 0x86, 0x07, 0x66, 0x39, 0xb8, 0xba, 0xdf,
        0x4b, 0x70, 0xaf, 0x84, 0x4e, 0x06, 0xd1, 0x8c
};
static const uint8_t CIPHER_64_ZERO_KEY[] = {
        0x01, 0xcb, 0x4f, 0x84, 0x1a, 0xdd, 0x1e, 0x20,
        0x4f, 0x7b, 0xb6, 0xe0, 0x81, 0xbc, 0x6b, 0x17,
        0x2e, 0x0d, 0xce, 0x24, 0x64, 0xea, 0x5e, 0xce,
        0x75, 0x27, 0xb5, 0xbd, 0xa0, 0x79, 0x1d, 0x22,
        0xc5, 0xf3, 0xb0, 0x64, 0x65, 0x7c, 0x41, 0x4c,
        0x6a, 0xf7, 0xaf, 0x64, 0x3c, 0x31, 0x89, 0x5f,
        0xb1, 0x45, 0x6b, 0x5b, 0xbf, 0xc6, 0x82, 0x4e,
        0xb4, 0xc3, 0x5d, 0x5d, 0xac, 0x4b, 0x0c, 0xf2
};
static const uint8_t CIPHER_64_MAX_KEY[] = {
        0xa3, 0x4a, 0x7d, 0xdc, 0xb2, 0x9d, 0xab, 0xf3,
        0xf4, 0xb8, 0xa3, 0x48, 0x4a, 0xf3, 0x24, 0x45,
        0xd5, 0xa3, 0x19, 0xfc, 0xa4, 0x03, 0xdc, 0xc6,
        0xd4, 0x1f, 0x2d, 0xc4, 0xb4, 0xfc, 0xd6, 0xaf,
        0xf5, 0x01, 0x81, 0xfc, 0xfd, 0x13, 0x5d, 0x87,
        0x46, 0x1c, 0xf6, 0xfc, 0xeb, 0x56, 0xff, 0xaa,
        0xda, 0xaf, 0xdd, 0x7c, 0xd3, 0xd3, 0xd0, 0xa9,
        0x57, 0x16, 0x69, 0x1f, 0x41, 0xf0, 0x3d, 0x12
};
static const uint8_t CIPHER_64_MAX_KEY_IV[] = {
        0x31, 0x3b, 0xf9, 0xfb, 0x00, 0x9b, 0x75, 0x9b,
        0xd2, 0x91, 0x2e, 0xf4, 0x88, 0x75, 0xf1, 0x67,
        0x39, 0x6c, 0x0e, 0x33, 0xe6, 0x51, 0xa7, 0x6f,
        0x9e, 0xba, 0x13, 0x95, 0xcb, 0x91, 0xa9, 0x3a,
        0x38, 0xb4, 0xa4, 0x3a, 0xc6, 0xa6, 0x02, 0xe4,
        0x4a, 0xc3, 0x64, 0xd8, 0x88, 0x2a, 0xf0, 0x71,
        0x1f, 0x0e, 0xb0, 0x9e, 0x06, 0x24, 0x42, 0xe5,
        0x66, 0xb2, 0x24, 0x5d, 0x6f, 0x80, 0xe2, 0xe0
};
static const uint8_t CIPHER_64_ZERO_KEY_IV[] = {
        0x68, 0x87, 0x9d, 0xaf, 0x8a, 0x68, 0xd0, 0xe2,
        0x28, 0x64, 0xf3, 0x4d, 0x1c, 0xf0, 0x95, 0x05,
        0xe6, 0x69, 0xa9, 0x02, 0x21, 0xdc, 0x02, 0xbe,
        0x00, 0xdf, 0x19, 0x82, 0x86, 0xdb, 0x01, 0x3b,
        0x61, 0x59, 0x23, 0x62, 0x86, 0x36, 0x62, 0xe7,
        0x7d, 0x83, 0xf1, 0x35, 0x49, 0x15, 0xae, 0x82,
        0x2b, 0xd6, 0x29, 0x67, 0x77, 0x0a, 0x11, 0x08,
        0x8d, 0xda, 0xaf, 0xfd, 0x08, 0xb2, 0xea, 0x9a
};
static const uint8_t CIPHER_64_MAX_IV[] = {
        0x6a, 0xd5, 0xae, 0xcf, 0x9a, 0xb0, 0xa7, 0x9f,
        0xe4, 0xf7, 0xe9, 0x8c, 0x90, 0x51, 0x4d, 0x75,
        0x4b, 0xd6, 0x6c, 0xeb, 0xe4, 0xc3, 0x44, 0x9b,
        0xd2, 0x72, 0x23, 0xd5, 0xcb, 0xde, 0xd8, 0x7e,
        0x56, 0xbd, 0x53, 0x75, 0xd6, 0x22, 0xaa, 0x13,
        0x44, 0x74, 0xe6, 0x5b, 0x50, 0xb6, 0x03, 0xb3,
        0x29, 0x56, 0xa0, 0xc6, 0x15, 0x38, 0x26, 0x6a,
        0x32, 0xef, 0x44, 0xc3, 0x27, 0xdc, 0xf5, 0xe1
};
static const uint8_t CIPHER_64_ZERO_IV[] = {
        0x11, 0x9b, 0x07, 0x7a, 0x35, 0x62, 0xb7, 0x71,
        0xbf, 0x1c, 0x06, 0x70, 0xc3, 0xc8, 0xac, 0xa6,
        0x57, 0x4f, 0xe1, 0x18, 0x04, 0xe2, 0x60, 0xe7,
        0x8c, 0x07, 0xf0, 0xd4, 0x14, 0xa0, 0xca, 0xb3,
        0xec, 0xc0, 0x22, 0x8b, 0xa5, 0xcc, 0xd1, 0x99,
        0xb3, 0x46, 0x07, 0x7e, 0x48, 0xfd, 0x36, 0xb3,
        0x06, 0x4e, 0x64, 0x9d, 0x3c, 0x5a, 0x7e, 0xdc,
        0x49, 0xbc, 0xc7, 0x2e, 0x4a, 0xad, 0x97, 0xd9
};
static const uint8_t PLAIN_65[] = {
        0x0d, 0xd8, 0xfd, 0x8b, 0x16, 0xc2, 0xa1, 0xa4,
        0xe3, 0xcf, 0xd2, 0x92, 0xd2, 0x98, 0x4b, 0x35,
        0x61, 0xd5, 0x55, 0xd1, 0x6c, 0x33, 0xdd, 0xc2,
        0xbc, 0xf7, 0xed, 0xde, 0x13, 0xef, 0xe5, 0x20,
        0xc7, 0xe2, 0xab, 0xdd, 0xa4, 0x4d, 0x81, 0x88,
        0x1c, 0x53, 0x1a, 0xee, 0xeb, 0x66, 0x24, 0x4c,
        0x3b, 0x79, 0x1e, 0xa8, 0xac, 0xfb, 0x6a, 0x68,
        0xf3, 0x58, 0x46, 0x06, 0x47, 0x2b, 0x26, 0x0e,
        0x0d
};
static const uint8_t CIPHER_65[] = {
        0xcd, 0x39, 0xb4, 0x9c, 0xdf, 0x0c, 0x8a, 0xae,
        0x75, 0x31, 0x1d, 0x7c, 0xce, 0x09, 0x0b, 0x7d,
        0x3a, 0xf1, 0xc6, 0x9f, 0x6c, 0x86, 0x16, 0xea,
        0x51, 0x34, 0xe3, 0x79, 0x28, 0x91, 0x91, 0xc2,
        0x18, 0xf1, 0xd9, 0xc6, 0x6b, 0x3d, 0x78, 0xd4,
        0xbc, 0x1c, 0x78, 0x02, 0x21, 0x5e, 0x91, 0x4f,
        0x26, 0x75, 0x9b, 0xb9, 0xfd, 0xdd, 0xc5, 0xec,
        0xda, 0x2f, 0x94, 0x05, 0xeb, 0xe3, 0xd0, 0xc6,
        0xd9
};
static const uint8_t CIPHER_65_ZERO_KEY[] = {
        0xfa, 0x27, 0x86, 0x2d, 0x1b, 0x12, 0x7d, 0x2f,
        0x8b, 0x89, 0x5c, 0x89, 0x0e, 0x3c, 0x31, 0xb1,
        0xdb, 0x7f, 0x5a, 0x41, 0xb0, 0xd7, 0x02, 0x18,
        0xc6, 0x75, 0xd6, 0x05, 0x54, 0xcc, 0x6f, 0xa4,
        0x36, 0x00, 0xec, 0x19, 0xe6, 0x76, 0x2c, 0x58,
        0x43, 0x0c, 0x7b, 0xea, 0xbd, 0x45, 0x92, 0x32,
        0x2a, 0xf4, 0xe6, 0x7b, 0x23, 0x75, 0x5a, 0xf9,
        0x38, 0x64, 0xd0, 0x95, 0x89, 0x48, 0x69, 0x07,
        0x4e
};
static const uint8_t CIPHER_65_MAX_KEY[] = {
        0x7a, 0x88, 0x66, 0xab, 0x26, 0xbc, 0xff, 0x20,
        0xb1, 0xf8, 0x90, 0x45, 0xcc, 0xd3, 0x00, 0x94,
        0xcf, 0x73, 0xe2, 0xe5, 0x5e, 0x06, 0x43, 0xab,
        0xe6, 0x7a, 0x61, 0x3c, 0x76, 0x13, 0x62, 0x88,
        0x8c, 0x22, 0xf5, 0x29, 0x2e, 0x0a, 0x05, 0xf8,
        0x31, 0xdf, 0x28, 0xe1, 0xd7, 0x6b, 0x7f, 0x57,
        0xff, 0x67, 0x68, 0x15, 0x3c, 0x90, 0x56, 0x47,
        0x6d, 0x7f, 0x14, 0x3e, 0x45, 0x67, 0x69, 0x70,
        0xcb
};
static const uint8_t CIPHER_65_MAX_KEY_IV[] = {
        0x3d, 0xae, 0xf4, 0x70, 0x06, 0xd2, 0xb3, 0xf0,
        0xa8, 0x0e, 0xa7, 0x71, 0xc5, 0x63, 0x6e, 0xca,
        0x52, 0xd8, 0x58, 0x33, 0x36, 0xc5, 0x77, 0x13,
        0xb9, 0xf2, 0x55, 0x45, 0x0d, 0xe6, 0x4d, 0xcc,
        0x1a, 0xa4, 0xd9, 0x11, 0x1f, 0xd5, 0x46, 0x7a,
        0xd8, 0xb1, 0x50, 0x1b, 0xcc, 0x4e, 0x12, 0x84,
        0x47, 0xbe, 0x24, 0x29, 0xda, 0x48, 0xf6, 0x81,
        0xc3, 0x63, 0x78, 0x70, 0x09, 0xb0, 0xc5, 0xe9,
        0x45
};
static const uint8_t CIPHER_65_ZERO_KEY_IV[] = {
        0x64, 0x12, 0x90, 0x24, 0x8c, 0x21, 0x16, 0x89,
        0x52, 0xfb, 0x7a, 0xc8, 0x51, 0xe6, 0x0a, 0xa8,
        0x8d, 0xdd, 0xff, 0x02, 0xf1, 0x48, 0xd2, 0xc2,
        0x27, 0x97, 0x5f, 0x52, 0x40, 0xac, 0xe5, 0xcd,
        0x43, 0x49, 0x5e, 0x49, 0x5f, 0x45, 0x26, 0x79,
        0xef, 0xf1, 0xc5, 0xf6, 0x0d, 0x71, 0x4c, 0x77,
        0x73, 0x66, 0xbd, 0xd0, 0xab, 0x66, 0xa5, 0x6c,
        0x28, 0x0b, 0xf3, 0xd0, 0x6e, 0x82, 0xcd, 0x93,
        0x0e
};
static const uint8_t CIPHER_65_MAX_IV[] = {
        0x13, 0xdb, 0x04, 0xcc, 0xdb, 0xd5, 0x09, 0x2e,
        0xf9, 0xfb, 0x32, 0xdc, 0x56, 0x28, 0x17, 0xfb,
        0xfb, 0x8f, 0x35, 0x76, 0xa9, 0x7a, 0x38, 0xf6,
        0xe2, 0xe5, 0x39, 0x7d, 0x1a, 0x0e, 0x0c, 0xcf,
        0x67, 0xe9, 0x37, 0xb4, 0x1e, 0x34, 0xeb, 0xb7,
        0x0e, 0x22, 0xed, 0x23, 0x72, 0xf9, 0xa0, 0xc1,
        0x8d, 0x4b, 0xb7, 0xa8, 0xf4, 0x47, 0xee, 0xa4,
        0x62, 0xf2, 0xa2, 0xbe, 0xff, 0x9f, 0x8d, 0x66,
        0xd4
};
static const uint8_t CIPHER_65_ZERO_IV[] = {
        0x09, 0xe6, 0xdb, 0x40, 0x1a, 0x5d, 0xf1, 0xbc,
        0x3a, 0xf1, 0x08, 0xb5, 0xe9, 0x9c, 0xc2, 0x5f,
        0xa3, 0x21, 0xec, 0xc8, 0x24, 0xb1, 0xe1, 0x8e,
        0x52, 0xf7, 0x2b, 0x4b, 0xec, 0x2f, 0x8c, 0x69,
        0xe9, 0x6a, 0x72, 0x54, 0xce, 0x98, 0x6b, 0xbe,
        0x85, 0x7e, 0xc0, 0xaf, 0x51, 0xf2, 0x1a, 0x3b,
        0xdd, 0x46, 0xc6, 0x05, 0xe2, 0x57, 0x95, 0xa0,
        0x60, 0xf1, 0x6e, 0xe2, 0x9e, 0x22, 0xe4, 0x21,
        0xcf
};

typedef struct snow_v_test_vectors_s {
	const uint8_t *KEY;
	const uint8_t *IV;
	uint64_t length_in_bytes;
        const uint8_t *plaintext;
	const uint8_t *ciphertext;
} snow_v_test_vectors_t;

static const snow_v_test_vectors_t snow_v_vectors_cov[] = {
        /* {  key,       iv,  bytes,    plain,    cipher   } */
        /* == SNOW-V test vectors from spec #1, #2, #3 */
        { ZERO_KEY,  ZERO_IV,    128,   ZERO_PLAIN, keystreams_from_spec[0] },
        { MAX_KEY,    MAX_IV,    128,   ZERO_PLAIN, keystreams_from_spec[1] },
        { KEY_spec,  IV_spec,    128,   ZERO_PLAIN, keystreams_from_spec[2] },
        /* Vectors generated for better coverage*/
        {  KEYs[0],   IVs[0],      0,   NULL,  NULL },
        {  KEYs[0],  ZERO_IV,      0,   NULL,  NULL },
        {  KEYs[0],   MAX_IV,      0,   NULL,  NULL },
        { ZERO_KEY,   IVs[0],      0,   NULL,  NULL },
        { ZERO_KEY,  ZERO_IV,      0,   NULL,  NULL },
        {  MAX_KEY,   IVs[0],      0,   NULL,  NULL },
        {  MAX_KEY,   MAX_IV,      0,   NULL,  NULL },
        {  KEYs[1],   IVs[1],      1,   PLAIN_1,  CIPHER_1 },
        {  KEYs[1],  ZERO_IV,      1,   PLAIN_1,  CIPHER_1_ZERO_IV },
        {  KEYs[1],   MAX_IV,      1,   PLAIN_1,  CIPHER_1_MAX_IV },
        { ZERO_KEY,   IVs[1],      1,   PLAIN_1,  CIPHER_1_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      1,   PLAIN_1,  CIPHER_1_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[1],      1,   PLAIN_1,  CIPHER_1_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      1,   PLAIN_1,  CIPHER_1_MAX_KEY_IV },
        {  KEYs[2],   IVs[2],      2,   PLAIN_8,  CIPHER_8 },
        {  KEYs[2],  ZERO_IV,      2,   PLAIN_8,  CIPHER_8_ZERO_IV },
        {  KEYs[2],   MAX_IV,      2,   PLAIN_8,  CIPHER_8_MAX_IV },
        { ZERO_KEY,   IVs[2],      2,   PLAIN_8,  CIPHER_8_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      2,   PLAIN_8,  CIPHER_8_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[2],      2,   PLAIN_8,  CIPHER_8_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      2,   PLAIN_8,  CIPHER_8_MAX_KEY_IV },
        {  KEYs[3],   IVs[3],      3,  PLAIN_15,  CIPHER_15 },
        {  KEYs[3],  ZERO_IV,      3,  PLAIN_15,  CIPHER_15_ZERO_IV },
        {  KEYs[3],   MAX_IV,      3,  PLAIN_15,  CIPHER_15_MAX_IV },
        { ZERO_KEY,   IVs[3],      3,  PLAIN_15,  CIPHER_15_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      3,  PLAIN_15,  CIPHER_15_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[3],      3,  PLAIN_15,  CIPHER_15_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      3,  PLAIN_15,  CIPHER_15_MAX_KEY_IV },
        {  KEYs[4],   IVs[4],      4,  PLAIN_16,  CIPHER_16 },
        {  KEYs[4],  ZERO_IV,      4,  PLAIN_16,  CIPHER_16_ZERO_IV },
        {  KEYs[4],   MAX_IV,      4,  PLAIN_16,  CIPHER_16_MAX_IV },
        { ZERO_KEY,   IVs[4],      4,  PLAIN_16,  CIPHER_16_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      4,  PLAIN_16,  CIPHER_16_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[4],      4,  PLAIN_16,  CIPHER_16_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      4,  PLAIN_16,  CIPHER_16_MAX_KEY_IV },
        {  KEYs[5],   IVs[5],      5,  PLAIN_17,  CIPHER_17 },
        {  KEYs[5],  ZERO_IV,      5,  PLAIN_17,  CIPHER_17_ZERO_IV },
        {  KEYs[5],   MAX_IV,      5,  PLAIN_17,  CIPHER_17_MAX_IV },
        { ZERO_KEY,   IVs[5],      5,  PLAIN_17,  CIPHER_17_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      5,  PLAIN_17,  CIPHER_17_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[5],      5,  PLAIN_17,  CIPHER_17_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      5,  PLAIN_17,  CIPHER_17_MAX_KEY_IV },
        {  KEYs[6],   IVs[6],      6,  PLAIN_48,  CIPHER_48 },
        {  KEYs[6],  ZERO_IV,      6,  PLAIN_48,  CIPHER_48_ZERO_IV },
        {  KEYs[6],   MAX_IV,      6,  PLAIN_48,  CIPHER_48_MAX_IV },
        { ZERO_KEY,   IVs[6],      6,  PLAIN_48,  CIPHER_48_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      6,  PLAIN_48,  CIPHER_48_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[6],      6,  PLAIN_48,  CIPHER_48_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      6,  PLAIN_48,  CIPHER_48_MAX_KEY_IV },
        {  KEYs[7],   IVs[7],      7,  PLAIN_63,  CIPHER_63 },
        {  KEYs[7],  ZERO_IV,      7,  PLAIN_63,  CIPHER_63_ZERO_IV },
        {  KEYs[7],   MAX_IV,      7,  PLAIN_63,  CIPHER_63_MAX_IV },
        { ZERO_KEY,   IVs[7],      7,  PLAIN_63,  CIPHER_63_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      7,  PLAIN_63,  CIPHER_63_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[7],      7,  PLAIN_63,  CIPHER_63_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      7,  PLAIN_63,  CIPHER_63_MAX_KEY_IV },
        {  KEYs[8],   IVs[8],      8,  PLAIN_64,  CIPHER_64 },
        {  KEYs[8],  ZERO_IV,      8,  PLAIN_64,  CIPHER_64_ZERO_IV },
        {  KEYs[8],   MAX_IV,      8,  PLAIN_64,  CIPHER_64_MAX_IV },
        { ZERO_KEY,   IVs[8],      8,  PLAIN_64,  CIPHER_64_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      8,  PLAIN_64,  CIPHER_64_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[8],      8,  PLAIN_64,  CIPHER_64_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      8,  PLAIN_64,  CIPHER_64_MAX_KEY_IV },
        {  KEYs[9],   IVs[9],      9,  PLAIN_65,  CIPHER_65 },
        {  KEYs[9],  ZERO_IV,      9,  PLAIN_65,  CIPHER_65_ZERO_IV },
        {  KEYs[9],   MAX_IV,      9,  PLAIN_65,  CIPHER_65_MAX_IV },
        { ZERO_KEY,   IVs[9],      9,  PLAIN_65,  CIPHER_65_ZERO_KEY },
        { ZERO_KEY,  ZERO_IV,      9,  PLAIN_65,  CIPHER_65_ZERO_KEY_IV },
        {  MAX_KEY,   IVs[9],      9,  PLAIN_65,  CIPHER_65_MAX_KEY },
        {  MAX_KEY,   MAX_IV,      9,  PLAIN_65,  CIPHER_65_MAX_KEY_IV }
};

static const uint8_t SPEC_SNOW_V_GCM_AUTH_TAGs[][16] = {
        {
                0x02, 0x9a, 0x62, 0x4c, 0xda, 0xa4, 0xd4, 0x6c,
                0xb9, 0xa0, 0xef, 0x40, 0x46, 0x95, 0x6c, 0x9f
        },
        {
                0xfc, 0x7c, 0xac, 0x57, 0x4c, 0x49, 0xfe, 0xae,
                0x61, 0x50, 0x31, 0x5b, 0x96, 0x85, 0x42, 0x4c
        },
        {
                0x5a, 0x5a, 0xa5, 0xfb, 0xd6, 0x35, 0xef, 0x1a,
                0xe1, 0x29, 0x61, 0x42, 0x03, 0xe1, 0x03, 0x84
        },
        {
                0x25, 0x0e, 0xc8, 0xd7, 0x7a, 0x02, 0x2c, 0x08,
                0x7a, 0xdf, 0x08, 0xb6, 0x5a, 0xdc, 0xbb, 0x1a
        },
};

static const uint8_t SPEC_SNOW_V_GCM_CIPHER[] = {
        0xdd, 0x7e, 0x01, 0xb2, 0xb4, 0x24, 0xa2, 0xef,
        0x82, 0x50,
        0xdd, 0xfe, 0x4e, 0x31, 0xe7, 0xbf, 0xe6, 0x90,
        0x23, 0x31, 0xec, 0x5c, 0xe3, 0x19, 0xd9, 0x0d
};

static const uint8_t SPEC_SNOW_V_GCM_KEY[] = {
        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
        0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
        0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a,
        0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa
};

static const uint8_t SPEC_SNOW_V_GCM_IV[] = {
        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
        0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
};

static const uint8_t SPEC_SNOW_V_GCM_AAD[] = {
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
        0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
};

static const uint8_t SPEC_SNOW_V_GCM_AAD_2[] = {
        0x41, 0x41, 0x44, 0x20, 0x74, 0x65, 0x73, 0x74,
        0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x21
};

static const uint8_t SPEC_SNOW_V_GCM_PLAIN[] = {
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
        0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
        0x20, 0x53, 0x6e, 0x6f, 0x77, 0x56, 0x2d, 0x41,
        0x45, 0x41, 0x44, 0x20, 0x6d, 0x6f, 0x64, 0x65,
        0x21
};

static const uint8_t SPEC_SNOW_V_GCM_CIPHER_V6[] = {
        0xdd, 0x7e, 0x01, 0xb2, 0xb4, 0x24, 0xa2, 0xef,
        0x82, 0x50, 0x27, 0x07, 0xe8, 0x7a, 0x32, 0xc1,
        0x52, 0xb0, 0xd0, 0x18, 0x18, 0xfd, 0x7f, 0x12,
        0x24, 0x3e, 0xb5, 0xa1, 0x56, 0x59, 0xe9, 0x1b,
        0x4c, 0x90, 0x7e, 0xa6, 0xa5, 0xb7, 0x3a, 0x51,
        0xde, 0x74, 0x7c, 0x3e, 0x9a, 0xd9, 0xee, 0x02,
        0x9b
};

typedef struct snow_v_aead_test_vectors_s {
	const uint8_t *KEY;
	const uint8_t *IV;
        const uint8_t *aad;
        uint64_t aad_length_in_bytes;
	uint64_t length_in_bytes;
        const uint8_t *plaintext;
	const uint8_t *ciphertext;
} snow_v_aead_test_vectors_t;

static const snow_v_aead_test_vectors_t snow_v_aead_test_vectors[] = {
        /* == SNOW-V-GCM test vectors from spec #1 - #6 */
        {
                ZERO_KEY, ZERO_IV, NULL, 0, 0, ZERO_PLAIN,
                SPEC_SNOW_V_GCM_AUTH_TAGs[0]
        },
        {
                SPEC_SNOW_V_GCM_KEY, SPEC_SNOW_V_GCM_IV,
                NULL, 0, 0, ZERO_PLAIN, SPEC_SNOW_V_GCM_AUTH_TAGs[1]
        },
        {
                ZERO_KEY, ZERO_IV, SPEC_SNOW_V_GCM_AAD, 16, 0,
                ZERO_PLAIN, SPEC_SNOW_V_GCM_AUTH_TAGs[2]
        },
        {
                SPEC_SNOW_V_GCM_KEY, SPEC_SNOW_V_GCM_IV, SPEC_SNOW_V_GCM_AAD,
                16, 0, ZERO_PLAIN, SPEC_SNOW_V_GCM_AUTH_TAGs[3]
        },
        {
                SPEC_SNOW_V_GCM_KEY, SPEC_SNOW_V_GCM_IV, NULL, 0,
                10, SPEC_SNOW_V_GCM_AAD, SPEC_SNOW_V_GCM_CIPHER
        },
        {
                SPEC_SNOW_V_GCM_KEY, SPEC_SNOW_V_GCM_IV, SPEC_SNOW_V_GCM_AAD_2,
                sizeof(SPEC_SNOW_V_GCM_AAD_2), sizeof(SPEC_SNOW_V_GCM_PLAIN),
                SPEC_SNOW_V_GCM_PLAIN, SPEC_SNOW_V_GCM_CIPHER_V6
        }
};

static uint32_t compare(const uint8_t *result,
                        const uint8_t *expected,
                        const size_t size)
{
        if (memcmp(result, expected, size) != 0) {
                hexdump(stderr, "expected", expected, size);
                hexdump(stderr, "received", result, size);
                return 1;
        }
        return 0;
}

/* check for buffer under/over-write */
static uint32_t check_buffer_over_under_write(uint8_t *result,
                        const int pad_pattern,
                        const size_t pad_size,
                        const size_t alloc_size)
{
        uint8_t *pad_block = malloc(pad_size);
        uint8_t error = 0;

        if (pad_block == NULL) {
                fprintf(stderr, "Error allocating %lu bytes!\n",
                        (unsigned long) pad_size);
                exit(EXIT_FAILURE);
        }

        /* check for buffer under/over-write */
        memset(pad_block, pad_pattern, pad_size);

        if (memcmp(pad_block, result, pad_size) != 0) {
                hexdump(stderr, "underwrite detected", result,
                        pad_size);
                error = 1;
        }

        if (memcmp(pad_block, &result[alloc_size - pad_size],
                        pad_size) != 0) {
                hexdump(stderr, "overwrite detected",
                        &result[alloc_size - pad_size], pad_size);
                error = 1;
        }

        free(pad_block);

        return error;
}

static void
snow_v_single_test(IMB_MGR *p_mgr,
                   struct test_suite_context *ts,
                   const uint8_t *key,
                   const uint8_t *iv,
                   const uint8_t *plain,
                   const size_t size,
                   const uint8_t *expected)
{
        const size_t pad_size = 16;
        const size_t alloc_size = size + (2 * pad_size);
        const int pad_pattern = 0xa5;
        uint8_t *dst_ptr = NULL, *output = malloc(alloc_size);
        uint32_t pass = 0, fail = 0;
        struct IMB_JOB *job;

        if (output == NULL) {
                fprintf(stderr, "Error allocating %lu bytes!\n",
                        (unsigned long) alloc_size);
                exit(EXIT_FAILURE);
        }

        dst_ptr = &output[pad_size];

        /* Prime padding blocks with a pattern */
        memset(output, pad_pattern, pad_size);
        memset(&output[alloc_size - pad_size], pad_pattern, pad_size);

        job = IMB_GET_NEXT_JOB(p_mgr);

        job->cipher_direction = IMB_DIR_ENCRYPT;
        job->chain_order = IMB_ORDER_HASH_CIPHER;
        job->cipher_mode = IMB_CIPHER_SNOW_V;
        job->hash_alg = IMB_AUTH_NULL;
        job->key_len_in_bytes = 32;
        job->iv_len_in_bytes = 16;
        job->cipher_start_src_offset_in_bytes = 0;

        job->enc_keys = key;
        job->iv = iv;
        job->dst = dst_ptr;
        job->src = plain;
        job->msg_len_to_cipher_in_bytes = size;

        job = IMB_SUBMIT_JOB(p_mgr);
        if (job == NULL) {
                const int err = imb_get_errno(p_mgr);

                if (err != 0)
                        printf("Error: %s!\n", imb_get_strerror(err));
                fail++;
        } else {
                int fail_found = 0;
                /* check for vector match */
                fail_found = compare(dst_ptr, expected, size);

                fail_found += check_buffer_over_under_write(
                                output, pad_pattern,
                                pad_size, alloc_size);

                if (fail_found)
                        fail++;
                else
                        pass++;
        }

        test_suite_update(ts, pass, fail);
        free(output);
}

static void
snow_v_aead_single_test(IMB_MGR *p_mgr,
                   struct test_suite_context *ts,
                   const uint8_t *key,
                   const uint8_t *iv,
                   const uint8_t *aad,
                   const uint8_t *plain,
                   const size_t size,
                   const size_t aad_len,
                   const uint8_t *expected,
                   int dir_encrypt) /* 1-encrypt, 0-decrypt */
{
        const size_t pad_size = 16;
        /* alloc space for auth tag after output */
        const size_t alloc_size = size + 16 + (2 * pad_size);
        const int pad_pattern = 0xa5;
        uint8_t *dst_ptr = NULL, *output = malloc(alloc_size);
        uint32_t pass = 0, fail = 0;
        struct IMB_JOB *job;

        if (output == NULL) {
                fprintf(stderr, "Error allocating %lu bytes!\n",
                        (unsigned long) alloc_size);
                exit(EXIT_FAILURE);
        }

        dst_ptr = &output[pad_size];

        /* Prime padding blocks with a pattern */
        memset(output, pad_pattern, pad_size);
        memset(&output[alloc_size - pad_size], pad_pattern, pad_size);

        job = IMB_GET_NEXT_JOB(p_mgr);

        job->chain_order = IMB_ORDER_HASH_CIPHER;
        job->hash_alg = IMB_AUTH_SNOW_V_AEAD;
        job->cipher_mode = IMB_CIPHER_SNOW_V_AEAD;
        job->key_len_in_bytes = 32;
        job->iv_len_in_bytes = 16;
        job->cipher_start_src_offset_in_bytes = 0;
        job->enc_keys = key;
        job->iv = iv;
        if (dir_encrypt) {
                job->cipher_direction = IMB_DIR_ENCRYPT;
                job->dst = dst_ptr;
                job->src = plain;
        } else {
                job->cipher_direction = IMB_DIR_DECRYPT;
                job->dst = dst_ptr;
                job->src = expected;
        }
        job->auth_tag_output = dst_ptr + size;
        job->auth_tag_output_len_in_bytes = 16;
        job->msg_len_to_cipher_in_bytes = size;

        job->u.SNOW_V_AEAD.aad = aad;
        job->u.SNOW_V_AEAD.aad_len_in_bytes = aad_len;

        job = IMB_SUBMIT_JOB(p_mgr);
        if (job == NULL) {
                const int err = imb_get_errno(p_mgr);

                if (err != 0)
                        printf("Error: %s!\n", imb_get_strerror(err));
                fail++;
        } else {
                int fail_found = compare(job->auth_tag_output,
                        expected+size, 16);

                /* check for vector match */
                if (dir_encrypt)
                        fail_found += compare(dst_ptr, expected, size);
                else
                        fail_found += compare(dst_ptr, plain, size);

                fail_found += check_buffer_over_under_write(
                                output, pad_pattern,
                                pad_size, alloc_size);
                if (fail_found)
                        fail++;
                else
                        pass++;
        }

        test_suite_update(ts, pass, fail);
        free(output);
}


int snow_v_test(IMB_MGR *p_mgr)
{
        struct test_suite_context ts_snow_v;
        struct test_suite_context ts_snow_v_aead;
        int errors = 0;
        uint64_t i;

        /* flush the scheduler */
        while (IMB_FLUSH_JOB(p_mgr) != NULL)
                ;

        /* Test SNOW-V */
        printf("SNOW-V test vectors\n");
        test_suite_start(&ts_snow_v, "SNOW-V");
        for (i = 0; i < DIM(snow_v_vectors_cov); i++)
                snow_v_single_test(p_mgr, &ts_snow_v,
                        snow_v_vectors_cov[i].KEY,
                        snow_v_vectors_cov[i].IV,
                        snow_v_vectors_cov[i].plaintext,
                        snow_v_vectors_cov[i].length_in_bytes,
                        snow_v_vectors_cov[i].ciphertext);

        errors += test_suite_end(&ts_snow_v);

        /* Test SNOW-V-GCM */
        printf("SNOW-V-AEAD test vectors - ENCRYPT\n");
        test_suite_start(&ts_snow_v_aead, "SNOW-V-AEAD");

        for (i = 0; i < DIM(snow_v_aead_test_vectors); i++)
                snow_v_aead_single_test(p_mgr, &ts_snow_v_aead,
                        snow_v_aead_test_vectors[i].KEY,
                        snow_v_aead_test_vectors[i].IV,
                        snow_v_aead_test_vectors[i].aad,
                        snow_v_aead_test_vectors[i].plaintext,
                        snow_v_aead_test_vectors[i].length_in_bytes,
                        snow_v_aead_test_vectors[i].aad_length_in_bytes,
                        snow_v_aead_test_vectors[i].ciphertext, 1);

        printf("SNOW-V-AEAD test vectors - DECRYPT\n");
        for (i = 0; i < DIM(snow_v_aead_test_vectors); i++)
                snow_v_aead_single_test(p_mgr, &ts_snow_v_aead,
                        snow_v_aead_test_vectors[i].KEY,
                        snow_v_aead_test_vectors[i].IV,
                        snow_v_aead_test_vectors[i].aad,
                        snow_v_aead_test_vectors[i].plaintext,
                        snow_v_aead_test_vectors[i].length_in_bytes,
                        snow_v_aead_test_vectors[i].aad_length_in_bytes,
                        snow_v_aead_test_vectors[i].ciphertext, 0);
        errors += test_suite_end(&ts_snow_v_aead);


        return errors;
}
