+
+#define NO_PAYLOAD_LENGTH ((size_t)-1)
+# define data(ctx) ((EVP_AES_HMAC_SHA1 *)EVP_CIPHER_CTX_get_cipher_data(ctx))
+
+static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *inkey,
+ const unsigned char *iv,
+ int enc)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+ key->payload_length = NO_PAYLOAD_LENGTH;
+ return 1;
+}
+
+static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
+ unsigned char *out,
+ const unsigned char *in,
+ size_t len)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+ unsigned int l;
+ size_t plen = key->payload_length;
+
+ key->payload_length = NO_PAYLOAD_LENGTH;
+
+ if (len % AES_BLOCK_SIZE)
+ return 0;
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ if (plen == NO_PAYLOAD_LENGTH)
+ plen = len;
+ else if (len !=
+ ((plen + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
+ return 0;
+
+ memmove(out, in, plen);
+
+ if (plen != len) { /* "TLS" mode of operation */
+ /* calculate HMAC and append it to payload */
+ fill_known_data(out + plen, SHA_DIGEST_LENGTH);
+
+ /* pad the payload|hmac */
+ plen += SHA_DIGEST_LENGTH;
+ for (l = len - plen - 1; plen < len; plen++)
+ out[plen] = l;
+ }
+ } else {
+ /* decrypt HMAC|padding at once */
+ memmove(out, in, len);
+
+ if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
+ unsigned int maxpad, pad;
+
+ if (key->tls_ver >= TLS1_1_VERSION) {
+ if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* omit explicit iv */
+ in += AES_BLOCK_SIZE;
+ out += AES_BLOCK_SIZE;
+ len -= AES_BLOCK_SIZE;
+ } else if (len < (SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* figure out payload length */
+ pad = out[len - 1];
+ maxpad = len - (SHA_DIGEST_LENGTH + 1);
+ if (pad > maxpad)
+ return 0;
+ for (plen = len - pad - 1; plen < len; plen++)
+ if (out[plen] != pad)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
+ int arg, void *ptr)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+
+ switch (type) {
+ case EVP_CTRL_AEAD_SET_MAC_KEY:
+ return 1;
+
+ case EVP_CTRL_AEAD_TLS1_AAD:
+ {
+ unsigned char *p = ptr;
+ unsigned int len;
+
+ if (arg != EVP_AEAD_TLS1_AAD_LEN)
+ return -1;
+
+ len = p[arg - 2] << 8 | p[arg - 1];
+ key->tls_ver = p[arg - 4] << 8 | p[arg - 3];
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ key->payload_length = len;
+ if (key->tls_ver >= TLS1_1_VERSION) {
+ if (len < AES_BLOCK_SIZE)
+ return 0;
+ len -= AES_BLOCK_SIZE;
+ p[arg - 2] = len >> 8;
+ p[arg - 1] = len;
+ }
+
+ return (int)(((len + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
+ - len);
+ } else {
+ key->payload_length = arg;
+
+ return SHA_DIGEST_LENGTH;
+ }
+ }
+ default:
+ return -1;
+ }
+}
+
+static int ossltest_rand_bytes(unsigned char *buf, int num)
+{
+ unsigned char val = 1;
+
+ while (--num >= 0)
+ *buf++ = val++;
+ return 1;
+}
+
+static int ossltest_rand_status(void)
+{
+ return 1;
+}
+
+static const RAND_METHOD *ossltest_rand_method(void)
+{
+
+ static RAND_METHOD osslt_rand_meth = {
+ NULL,
+ ossltest_rand_bytes,
+ NULL,
+ NULL,
+ ossltest_rand_bytes,
+ ossltest_rand_status
+ };
+
+ return &osslt_rand_meth;
+}