int ntests;
/* Error count */
int errors;
+ /* Number of tests skipped */
+ int nskip;
/* If output mismatch expected and got value */
unsigned char *out_got;
unsigned char *out_expected;
size_t out_len;
/* test specific data */
void *data;
+ /* Current test should be skipped */
+ int skip;
};
struct key_list {
/* If we already have a test set up run it */
if (t->meth) {
t->ntests++;
+ if (t->skip) {
+ t->meth = tmeth;
+ t->nskip++;
+ return 1;
+ }
t->err = NULL;
if (t->meth->run_test(t) != 1) {
fprintf(stderr, "%s test error line %d\n",
return 1;
}
-static EVP_PKEY *find_key(const char *name, struct key_list *lst)
+static int find_key(EVP_PKEY **ppk, const char *name, struct key_list *lst)
{
for (; lst; lst = lst->next) {
- if (!strcmp(lst->name, name))
- return lst->key;
+ if (!strcmp(lst->name, name)) {
+ if (ppk)
+ *ppk = lst->key;
+ return 1;
+ }
}
- return NULL;
+ return 0;
}
static void free_key_list(struct key_list *lst)
{
while (lst != NULL) {
- struct key_list *ltmp;
+ struct key_list *ltmp;
EVP_PKEY_free(lst->key);
OPENSSL_free(lst->name);
- ltmp = lst->next;
- OPENSSL_free(lst);
- lst = ltmp;
+ ltmp = lst->next;
+ OPENSSL_free(lst);
+ lst = ltmp;
+ }
+}
+
+static int check_unsupported()
+{
+ long err = ERR_peek_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_EVP
+ && ERR_GET_REASON(err) == EVP_R_UNSUPPORTED_ALGORITHM) {
+ ERR_clear_error();
+ return 1;
}
+ return 0;
}
static int process_test(struct evp_test *t, char *buf, int verbose)
{
char *keyword, *value;
- int rv = 0;
+ int rv = 0, add_key = 0;
long save_pos;
struct key_list **lst, *key;
EVP_PKEY *pk = NULL;
if (!strcmp(keyword, "PrivateKey")) {
save_pos = ftell(t->in);
pk = PEM_read_PrivateKey(t->in, NULL, 0, NULL);
- if (pk == NULL) {
+ if (pk == NULL && !check_unsupported()) {
fprintf(stderr, "Error reading private key %s\n", value);
ERR_print_errors_fp(stderr);
return 0;
}
lst = &t->private;
+ add_key = 1;
}
if (!strcmp(keyword, "PublicKey")) {
save_pos = ftell(t->in);
pk = PEM_read_PUBKEY(t->in, NULL, 0, NULL);
- if (pk == NULL) {
+ if (pk == NULL && !check_unsupported()) {
fprintf(stderr, "Error reading public key %s\n", value);
ERR_print_errors_fp(stderr);
return 0;
}
lst = &t->public;
+ add_key = 1;
}
/* If we have a key add to list */
- if (pk) {
+ if (add_key) {
char tmpbuf[80];
- if (find_key(value, *lst)) {
+ if (find_key(NULL, value, *lst)) {
fprintf(stderr, "Duplicate key %s\n", value);
return 0;
}
if (!setup_test(t, tmeth))
return 0;
t->start_line = t->line;
+ t->skip = 0;
if (!tmeth->init(t, value)) {
fprintf(stderr, "Unknown %s: %s\n", keyword, value);
return 0;
}
return 1;
+ } else if (t->skip) {
+ return 1;
} else if (!strcmp(keyword, "Result")) {
if (t->expected_err) {
fprintf(stderr, "Line %d: multiple result lines\n", t->line);
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
- memset(&t,0,sizeof(t));
+ memset(&t, 0, sizeof(t));
t.meth = NULL;
t.public = NULL;
t.private = NULL;
/* Run any final test we have */
if (!setup_test(&t, NULL))
exit(1);
- fprintf(stderr, "%d tests completed with %d errors\n",
- t.ntests, t.errors);
+ fprintf(stderr, "%d tests completed with %d errors, %d skipped\n",
+ t.ntests, t.errors, t.nskip);
free_key_list(t.public);
free_key_list(t.private);
fclose(in);
const EVP_MD *digest;
struct digest_data *mdat = t->data;
digest = EVP_get_digestbyname(alg);
- if (!digest)
+ if (!digest) {
+ /* If alg has an OID assume disabled algorithm */
+ if (OBJ_sn2nid(alg) != NID_undef || OBJ_ln2nid(alg) != NID_undef) {
+ t->skip = 1;
+ return 1;
+ }
return 0;
+ }
mdat = OPENSSL_malloc(sizeof(struct digest_data));
mdat->digest = digest;
mdat->input = NULL;
struct cipher_data {
const EVP_CIPHER *cipher;
int enc;
- /* Set to EVP_CIPH_GCM_MODE or EVP_CIPH_CCM_MODE if AEAD */
+ /* EVP_CIPH_GCM_MODE, EVP_CIPH_CCM_MODE or EVP_CIPH_OCB_MODE if AEAD */
int aead;
unsigned char *key;
size_t key_len;
const EVP_CIPHER *cipher;
struct cipher_data *cdat = t->data;
cipher = EVP_get_cipherbyname(alg);
- if (!cipher)
+ if (!cipher) {
+ /* If alg has an OID assume disabled algorithm */
+ if (OBJ_sn2nid(alg) != NID_undef || OBJ_ln2nid(alg) != NID_undef) {
+ t->skip = 1;
+ return 1;
+ }
return 0;
+ }
cdat = OPENSSL_malloc(sizeof(struct cipher_data));
cdat->cipher = cipher;
cdat->enc = -1;
cdat->tag = NULL;
t->data = cdat;
if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE
+ || EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE
|| EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE)
cdat->aead = EVP_CIPHER_mode(cipher);
else
goto err;
err = "INVALID_IV_LENGTH";
if (cdat->iv) {
- if (cdat->aead == EVP_CIPH_GCM_MODE) {
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
- cdat->iv_len, 0))
- goto err;
- } else if (cdat->aead == EVP_CIPH_CCM_MODE) {
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN,
+ if (cdat->aead) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
cdat->iv_len, 0))
goto err;
} else if (cdat->iv_len != (size_t)EVP_CIPHER_CTX_iv_length(ctx))
if (cdat->aead) {
unsigned char *tag;
/*
- * If encrypting just set tag length. If decrypting set
- * tag length and value.
+ * If encrypting or OCB just set tag length initially, otherwise
+ * set tag length and value.
*/
- if (enc) {
+ if (enc || cdat->aead == EVP_CIPH_OCB_MODE) {
err = "TAG_LENGTH_SET_ERROR";
tag = NULL;
} else {
err = "TAG_SET_ERROR";
tag = cdat->tag;
}
- if (cdat->aead == EVP_CIPH_GCM_MODE && tag) {
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG,
- cdat->tag_len, tag))
- goto err;
- } else if (cdat->aead == EVP_CIPH_CCM_MODE) {
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG,
+ if (tag || cdat->aead != EVP_CIPH_GCM_MODE) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
cdat->tag_len, tag))
goto err;
}
if (!EVP_CipherInit_ex(ctx, NULL, NULL, cdat->key, cdat->iv, -1))
goto err;
+ if (!enc && cdat->aead == EVP_CIPH_OCB_MODE) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ cdat->tag_len, cdat->tag)) {
+ err = "TAG_SET_ERROR";
+ goto err;
+ }
+ }
+
if (cdat->aead == EVP_CIPH_CCM_MODE) {
if (!EVP_CipherUpdate(ctx, NULL, &tmplen, NULL, out_len)) {
err = "CCM_PLAINTEXT_LENGTH_SET_ERROR";
err = "TAG_LENGTH_INTERNAL_ERROR";
goto err;
}
- /* EVP_CTRL_CCM_GET_TAG and EVP_CTRL_GCM_GET_TAG are equal. */
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG,
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG,
cdat->tag_len, rtag)) {
err = "TAG_RETRIEVE_ERROR";
goto err;
{
struct pkey_data *kdata;
EVP_PKEY *pkey = NULL;
+ int rv = 0;
+ if (use_public)
+ rv = find_key(&pkey, name, t->public);
+ if (!rv)
+ rv = find_key(&pkey, name, t->private);
+ if (!rv)
+ return 0;
+ if (!pkey) {
+ t->skip = 1;
+ return 1;
+ }
+
kdata = OPENSSL_malloc(sizeof(struct pkey_data));
- if (!kdata)
+ if (!kdata) {
+ EVP_PKEY_free(pkey);
return 0;
+ }
kdata->ctx = NULL;
kdata->input = NULL;
kdata->output = NULL;
kdata->keyop = keyop;
t->data = kdata;
- if (use_public)
- pkey = find_key(name, t->public);
- if (!pkey)
- pkey = find_key(name, t->private);
- if (!pkey)
- return 0;
kdata->ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!kdata->ctx)
return 0;