reformat evp_test.c
[openssl.git] / crypto / evp / evp_test.c
index 7706ee135ea4bff90fc7ff5a7df927de8b4e1b44..cc7036a9ad5640583d0a4bed5297d5cdecb310db 100644 (file)
@@ -179,12 +179,16 @@ struct evp_test {
     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 {
@@ -285,6 +289,11 @@ static int setup_test(struct evp_test *t, const struct evp_test_method *tmeth)
     /* 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",
@@ -309,31 +318,45 @@ static int setup_test(struct evp_test *t, const struct evp_test_method *tmeth)
     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;
@@ -345,27 +368,29 @@ static int process_test(struct evp_test *t, char *buf, int verbose)
     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;
         }
@@ -393,11 +418,14 @@ static int process_test(struct evp_test *t, char *buf, int verbose)
         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);
@@ -454,6 +482,8 @@ int main(int argc, char **argv)
 
     ERR_load_crypto_strings();
     OpenSSL_add_all_algorithms();
+
+    memset(&t, 0, sizeof(t));
     t.meth = NULL;
     t.public = NULL;
     t.private = NULL;
@@ -475,8 +505,8 @@ int main(int argc, char **argv)
     /* 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);
@@ -514,8 +544,14 @@ static int digest_test_init(struct evp_test *t, const char *alg)
     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;
@@ -587,7 +623,7 @@ static const struct evp_test_method digest_test_method = {
 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;
@@ -609,8 +645,14 @@ static int cipher_test_init(struct evp_test *t, const char *alg)
     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;
@@ -622,6 +664,7 @@ static int cipher_test_init(struct evp_test *t, const char *alg)
     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
@@ -704,12 +747,8 @@ static int cipher_test_enc(struct evp_test *t, int enc)
         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))
@@ -718,22 +757,18 @@ static int cipher_test_enc(struct evp_test *t, int enc)
     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;
         }
@@ -746,6 +781,14 @@ static int cipher_test_enc(struct evp_test *t, int enc)
     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";
@@ -781,8 +824,7 @@ static int cipher_test_enc(struct evp_test *t, int enc)
             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;
@@ -1035,20 +1077,28 @@ static int pkey_test_init(struct evp_test *t, const char *name,
 {
     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;