/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
#include "testutil.h"
#include "evp_test.h"
+#define AAD_NUM 4
typedef struct evp_test_method_st EVP_TEST_METHOD;
static int find_key(EVP_PKEY **ppk, const char *name, KEY_LIST *lst);
static int parse_bin(const char *value, unsigned char **buf, size_t *buflen);
-static int pkey_test_ctrl(EVP_TEST *t, EVP_PKEY_CTX *pctx,
- const char *value);
/*
* Compare two memory regions for equality, returning zero if they differ.
size_t plaintext_len;
unsigned char *ciphertext;
size_t ciphertext_len;
- /* GCM, CCM and OCB only */
- unsigned char *aad;
- size_t aad_len;
+ /* GCM, CCM, OCB and SIV only */
+ unsigned char *aad[AAD_NUM];
+ size_t aad_len[AAD_NUM];
unsigned char *tag;
size_t tag_len;
} CIPHER_DATA;
m = EVP_CIPHER_mode(cipher);
if (m == EVP_CIPH_GCM_MODE
|| m == EVP_CIPH_OCB_MODE
+ || m == EVP_CIPH_SIV_MODE
|| m == EVP_CIPH_CCM_MODE)
cdat->aead = m;
else if (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
static void cipher_test_cleanup(EVP_TEST *t)
{
+ int i;
CIPHER_DATA *cdat = t->data;
OPENSSL_free(cdat->key);
OPENSSL_free(cdat->iv);
OPENSSL_free(cdat->ciphertext);
OPENSSL_free(cdat->plaintext);
- OPENSSL_free(cdat->aad);
+ for (i = 0; i < AAD_NUM; i++)
+ OPENSSL_free(cdat->aad[i]);
OPENSSL_free(cdat->tag);
}
const char *value)
{
CIPHER_DATA *cdat = t->data;
+ int i;
if (strcmp(keyword, "Key") == 0)
return parse_bin(value, &cdat->key, &cdat->key_len);
if (strcmp(keyword, "Ciphertext") == 0)
return parse_bin(value, &cdat->ciphertext, &cdat->ciphertext_len);
if (cdat->aead) {
- if (strcmp(keyword, "AAD") == 0)
- return parse_bin(value, &cdat->aad, &cdat->aad_len);
+ if (strcmp(keyword, "AAD") == 0) {
+ for (i = 0; i < AAD_NUM; i++) {
+ if (cdat->aad[i] == NULL)
+ return parse_bin(value, &cdat->aad[i], &cdat->aad_len[i]);
+ }
+ return 0;
+ }
if (strcmp(keyword, "Tag") == 0)
return parse_bin(value, &cdat->tag, &cdat->tag_len);
}
CIPHER_DATA *expected = t->data;
unsigned char *in, *expected_out, *tmp = NULL;
size_t in_len, out_len, donelen = 0;
- int ok = 0, tmplen, chunklen, tmpflen;
+ int ok = 0, tmplen, chunklen, tmpflen, i;
EVP_CIPHER_CTX *ctx = NULL;
t->err = "TEST_FAILURE";
goto err;
}
}
- if (expected->aad) {
+ if (expected->aad[0] != NULL) {
t->err = "AAD_SET_ERROR";
if (!frag) {
- if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad,
- expected->aad_len))
- goto err;
+ for (i = 0; expected->aad[i] != NULL; i++) {
+ if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad[i],
+ expected->aad_len[i]))
+ goto err;
+ }
} else {
/*
* Supply the AAD in chunks less than the block size where possible
*/
- if (expected->aad_len > 0) {
- if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad, 1))
- goto err;
- donelen++;
- }
- if (expected->aad_len > 2) {
- if (!EVP_CipherUpdate(ctx, NULL, &chunklen,
- expected->aad + donelen,
- expected->aad_len - 2))
+ for (i = 0; expected->aad[i] != NULL; i++) {
+ if (expected->aad_len[i] > 0) {
+ if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad[i], 1))
+ goto err;
+ donelen++;
+ }
+ if (expected->aad_len[i] > 2) {
+ if (!EVP_CipherUpdate(ctx, NULL, &chunklen,
+ expected->aad[i] + donelen,
+ expected->aad_len[i] - 2))
+ goto err;
+ donelen += expected->aad_len[i] - 2;
+ }
+ if (expected->aad_len[i] > 1
+ && !EVP_CipherUpdate(ctx, NULL, &chunklen,
+ expected->aad[i] + donelen, 1))
goto err;
- donelen += expected->aad_len - 2;
}
- if (expected->aad_len > 1
- && !EVP_CipherUpdate(ctx, NULL, &chunklen,
- expected->aad + donelen, 1))
- goto err;
}
}
EVP_CIPHER_CTX_set_padding(ctx, 0);
if (out_misalign == 1 && frag == 0) {
/*
- * XTS, CCM and Wrap modes have special requirements about input
+ * XTS, SIV, CCM and Wrap modes have special requirements about input
* lengths so we don't fragment for those
*/
if (cdat->aead == EVP_CIPH_CCM_MODE
+ || EVP_CIPHER_mode(cdat->cipher) == EVP_CIPH_SIV_MODE
|| EVP_CIPHER_mode(cdat->cipher) == EVP_CIPH_XTS_MODE
|| EVP_CIPHER_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE)
break;
/* MAC key */
unsigned char *key;
size_t key_len;
+ /* MAC IV (GMAC) */
+ unsigned char *iv;
+ size_t iv_len;
/* Input to MAC */
unsigned char *input;
size_t input_len;
/* Expected output */
unsigned char *output;
size_t output_len;
+ unsigned char *custom;
+ size_t custom_len;
/* Collection of controls */
STACK_OF(OPENSSL_STRING) *controls;
} MAC_DATA;
size_t sz = strlen(alg);
static const char epilogue[] = " by EVP_PKEY";
- if (strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0)
+ if (sz >= sizeof(epilogue)
+ && strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0)
sz -= sizeof(epilogue) - 1;
if (strncmp(alg, "HMAC", sz) == 0) {
sk_OPENSSL_STRING_pop_free(mdat->controls, openssl_free);
OPENSSL_free(mdat->alg);
OPENSSL_free(mdat->key);
+ OPENSSL_free(mdat->iv);
+ OPENSSL_free(mdat->custom);
OPENSSL_free(mdat->input);
OPENSSL_free(mdat->output);
}
if (strcmp(keyword, "Key") == 0)
return parse_bin(value, &mdata->key, &mdata->key_len);
+ if (strcmp(keyword, "IV") == 0)
+ return parse_bin(value, &mdata->iv, &mdata->iv_len);
+ if (strcmp(keyword, "Custom") == 0)
+ return parse_bin(value, &mdata->custom, &mdata->custom_len);
if (strcmp(keyword, "Algorithm") == 0) {
mdata->alg = OPENSSL_strdup(value);
if (!mdata->alg)
return 0;
}
+static int mac_test_ctrl_pkey(EVP_TEST *t, EVP_PKEY_CTX *pctx,
+ const char *value)
+{
+ int rv;
+ char *p, *tmpval;
+
+ if (!TEST_ptr(tmpval = OPENSSL_strdup(value)))
+ return 0;
+ p = strchr(tmpval, ':');
+ if (p != NULL)
+ *p++ = '\0';
+ rv = EVP_PKEY_CTX_ctrl_str(pctx, tmpval, p);
+ if (rv == -2)
+ t->err = "PKEY_CTRL_INVALID";
+ else if (rv <= 0)
+ t->err = "PKEY_CTRL_ERROR";
+ else
+ rv = 1;
+ OPENSSL_free(tmpval);
+ return rv > 0;
+}
+
static int mac_test_run_pkey(EVP_TEST *t)
{
MAC_DATA *expected = t->data;
goto err;
}
for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++)
- if (!pkey_test_ctrl(t, pctx,
- sk_OPENSSL_STRING_value(expected->controls, i))) {
+ if (!mac_test_ctrl_pkey(t, pctx,
+ sk_OPENSSL_STRING_value(expected->controls,
+ i))) {
t->err = "EVPPKEYCTXCTRL_ERROR";
goto err;
}
t->err = "MAC_CTRL_ERROR";
goto err;
}
+ if (expected->custom != NULL) {
+ rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_CUSTOM,
+ expected->custom, expected->custom_len);
+ if (rv == -2) {
+ t->err = "MAC_CTRL_INVALID";
+ goto err;
+ } else if (rv <= 0) {
+ t->err = "MAC_CTRL_ERROR";
+ goto err;
+ }
+ }
+
+ if (expected->iv != NULL) {
+ rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_IV,
+ expected->iv, expected->iv_len);
+ if (rv == -2) {
+ t->err = "MAC_CTRL_INVALID";
+ goto err;
+ } else if (rv <= 0) {
+ t->err = "MAC_CTRL_ERROR";
+ goto err;
+ }
+ }
if (!EVP_MAC_init(ctx)) {
t->err = "MAC_INIT_ERROR";
return 0;
}
if (rv < 0) {
- TEST_info("Line %d: error processing keyword %s\n",
- t->s.curr, pp->key);
+ TEST_info("Line %d: error processing keyword %s = %s\n",
+ t->s.curr, pp->key, pp->value);
return 0;
}
}