[openssl-commits] [openssl] master update

Richard Levitte levitte at openssl.org
Mon Sep 7 14:11:49 UTC 2015


The branch master has been updated
       via  a351805733a2c0511c61e7fef06fe645e31a4796 (commit)
       via  eb8cd5dec28313d03025c160f81207ac6137f44a (commit)
       via  1c73c3bcf02731b4ce693b6e3ece9543cef4f2a0 (commit)
       via  ca5d7dff72b10cb030437a03d779c4fcf8ab832b (commit)
       via  49b147f85b96482be3931abda306afdf84d75d17 (commit)
       via  e3ff089249a31765c23faaf9d8019b7889dd0c58 (commit)
       via  5beb63c41e8bc140cd8096af8195b0b95bef1ff5 (commit)
       via  5ab4f893ce6d10e9286fd746acebe382c36cd32d (commit)
       via  24d794de25ae419f925b9ccc1e5dbab1b372cce8 (commit)
       via  50f0a9b3dd41c37875def805c2c48f8b2ed3ef24 (commit)
       via  c27a4049475428b902004a47104c17e1eaaadd20 (commit)
       via  25be5f44b81e1c45e15e689ba55713e455dfe624 (commit)
       via  53520ebe8757fea7d2e9ffe3d0c610dd6b9b9cc6 (commit)
       via  2511c12bf2d5f07f329d1e90cde8791817e4357e (commit)
       via  8de4f3d3a63f5eb5afa4bd92043953b501d0d7eb (commit)
       via  2a74b62e3ae1b6916190ff19276ed49a9b728b8f (commit)
       via  ca904707b6df0f5077f9eff94f29bd8035d042a7 (commit)
       via  8368d46bcadf13dd2c675da8113fcc9400ae12fc (commit)
       via  f5098edb14ce7da8db814dd392358d53c2b81496 (commit)
       via  fd99c6b599a8ed87b726caaa6d88c6915a60e0f4 (commit)
       via  caadc54381af04dd49d9812737d40fea320c8674 (commit)
       via  fb921436f3dc03daf4a7ac1fec9f1e458772e17b (commit)
       via  d6c5b66c1c9457a7f8c8f69c1ad3b4557dcd3fa2 (commit)
       via  204e41ed504b6deb370bdbf85fd988c03eff363b (commit)
       via  71a4f2832c3fe02d026af8241767ee80f440e876 (commit)
       via  fd9ad2300b280c0f71d24456bfbf04579331bc94 (commit)
       via  93de4f58ef8be2cb764343cb3102d41c81f11593 (commit)
       via  d11b43fdd30f084c19136359d0e3e4a06631abf9 (commit)
       via  7dc11227a385fd7e248e1292653761ec9ce9c105 (commit)
       via  127d25903fc705756ac211ea373104d8e8858ae1 (commit)
       via  88b8a5279f452027c193c2de7909dd9f7c9736c6 (commit)
       via  4fb35f8fcba5b49bdf8223e1964ef4cf640ea0ca (commit)
       via  4650de3e431d123e988821215f6473e93c3d4b17 (commit)
       via  0c85cc506916039bba86e8335aa71e0e44f038b0 (commit)
       via  904ae3342600fe1dae3e0835a784c73b7c237106 (commit)
       via  13350a0c0eb8937c299c394a88d6cb51d3356d1f (commit)
       via  894025c6428e7a78fb251e7a16522c3b7351f357 (commit)
       via  f3356b7f49823ddf31683667dfd376312b0a92a3 (commit)
       via  aec27d4d5210234560deab85c97bd453535f66ae (commit)
      from  8098fc566351cb76a2c5ad4f465df51f5e7e8c12 (commit)


- Log -----------------------------------------------------------------
commit a351805733a2c0511c61e7fef06fe645e31a4796
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Sep 7 01:09:23 2015 +0200

    Make sure that 80-test_ca.t finds all the config files
    
    This recipe counted too much on being called with test/ as its current
    working directory.  That's a mistake on, for example, Windows.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit eb8cd5dec28313d03025c160f81207ac6137f44a
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Sep 6 16:04:15 2015 +0200

    Add a recipe for the new null pointer test
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 1c73c3bcf02731b4ce693b6e3ece9543cef4f2a0
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Sep 6 16:03:30 2015 +0200

    Change the 80-test_tsa recipe as per changes in testtsa
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit ca5d7dff72b10cb030437a03d779c4fcf8ab832b
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Sep 3 21:17:31 2015 +0200

    Add a recipe for the new pbelu test
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 49b147f85b96482be3931abda306afdf84d75d17
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Sep 3 20:54:01 2015 +0200

    Remake the testsslproxy tests
    
    The testsslproxy tests turned out to be useless as they were.  They
    were really just for show and the results were ignore.  Now they are
    changed into a more veerifiable test
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit e3ff089249a31765c23faaf9d8019b7889dd0c58
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Sep 3 19:41:40 2015 +0200

    Small fix in OpenSSL::Test
    
    Be careful when shifting in a function argument, you end up changing
    the caller's value.  Instead, when it is an array, make a shallow copy
    and shift in that instead.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 5beb63c41e8bc140cd8096af8195b0b95bef1ff5
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Sep 3 19:39:58 2015 +0200

    Incorporate recent changes that were originally made in test/testssl
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 5ab4f893ce6d10e9286fd746acebe382c36cd32d
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Sep 3 12:00:28 2015 +0200

    Add documentation for the new testing framework
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 24d794de25ae419f925b9ccc1e5dbab1b372cce8
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Sep 3 09:24:01 2015 +0200

    Add a recipe for the new gmdiff test
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 50f0a9b3dd41c37875def805c2c48f8b2ed3ef24
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Sep 3 09:23:32 2015 +0200

    Correct test name
    
    Some tests were copied from test_jpake, but the title wasn't changed
    accordingly.  This might seem like a small thing, but it does affect
    the log file name...
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit c27a4049475428b902004a47104c17e1eaaadd20
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Aug 28 03:07:24 2015 +0200

    Remake test/sslsessionticktest.pl into a recipe
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 25be5f44b81e1c45e15e689ba55713e455dfe624
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Aug 13 19:38:59 2015 +0200

    Adapt the libssl test harness testing scripts to new testing framework
    
    This involves adding $TOP/util as perl library in test/run_tests.pl.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 53520ebe8757fea7d2e9ffe3d0c610dd6b9b9cc6
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Aug 9 06:52:50 2015 +0200

    Check the validity of MINFO
    
    MINFO may be an old file lying around, which might have
    00-check_testexes.t produce incorrect results.  To make sure this
    doesn't happen, check the variable VERSION in it against the same
    variable in the top Makefile.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 2511c12bf2d5f07f329d1e90cde8791817e4357e
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Aug 9 05:35:57 2015 +0200

    Better method of skipping all the tests in 00-check_testexes.t
    
    Before trying to read MINFO, we have no idea how many to test for, and
    because skip expects to get an exact number somehow, it's better to
    use 'plan skip_all'.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 8de4f3d3a63f5eb5afa4bd92043953b501d0d7eb
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Aug 8 11:45:54 2015 +0200

    Remove special x509 test conversions
    
    Following the commit from July 2 that removed netscape formated certs,
    it is no longer necessary to have conversion tests for it.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 2a74b62e3ae1b6916190ff19276ed49a9b728b8f
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Aug 8 11:33:10 2015 +0200

    Add a few missing tests
    
    test_clienthello
    test_packet
    test_verify_extra
    test_secmem
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit ca904707b6df0f5077f9eff94f29bd8035d042a7
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Apr 30 19:52:36 2015 +0200

    Push the line buffer filter on the out BIO on VMS
    
    VMS files are normally record oriented rather than stream oriented.
    This means that every write() will create a new record, which is seen
    as a line of its own, regardless of if there was a \n in there or not.
    bntest uses BN_print, which prints out number with more than one
    write(), thereby dividing up the numbers in several lines, which
    greatly disturbs the post-bntest checks that expect to find a full
    formula to calculate on one line.
    
    So, for VMS, we need to push the linebuffer filter on the out BIO.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 8368d46bcadf13dd2c675da8113fcc9400ae12fc
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Apr 30 19:38:47 2015 +0200

    Rework 00-test_checkexes.t for VMS
    
    Unfortunately, a file spec with character range globs interfere with
    paths on VMS, and are therefore disabled.  Rework this test to collect
    a list of expected tests and a list of all recipes and compare the two
    using grep.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit f5098edb14ce7da8db814dd392358d53c2b81496
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Apr 30 14:30:15 2015 +0200

    Document OpenSSL::Test and OpenSSL::Test::Simple
    
    For OpenSSL::Test, it meant rearranging the code to better suite the
    structure of the documentation.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit fd99c6b599a8ed87b726caaa6d88c6915a60e0f4
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Apr 30 08:51:24 2015 +0200

    Change OpenSSL::Test to be an extension of Test::More
    
    It became tedious as well as error prone to have all recipes use
    Test::More as well as OpenSSL::Test.  The easier way is to make
    OpenSSL::Test an extension of Test::More, thereby having all version
    checks as well as future checks firmly there.  Additionally, that
    allows us to extend existing Test::More functions if the need would
    arise.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit caadc54381af04dd49d9812737d40fea320c8674
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Apr 29 21:51:25 2015 +0200

    New feature: STOPTEST
    
    When the environment variable STOPTEST is defined (with any value other
    than the empty string), the test machinery in OpenSSL::Test goes into a
    different mode that will stop all testing at the end of a failing recipe.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit fb921436f3dc03daf4a7ac1fec9f1e458772e17b
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Apr 28 20:39:09 2015 +0200

    Add version numbers on some modules we use.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit d6c5b66c1c9457a7f8c8f69c1ad3b4557dcd3fa2
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Apr 28 17:59:06 2015 +0200

    Have 'make clean' clean away the log files.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 204e41ed504b6deb370bdbf85fd988c03eff363b
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Apr 23 11:11:14 2015 +0200

    Tone down the requirements of a test that will go away.
    
    00-check_testexes.t was a way for me to check that I didn't forget a
    compiled test app.  The way it worked was to require MINFO to be present.
    Considering the need for this test has diminished considerably at this
    point, I might as well tone down the requirement, and have it skip the
    test (and not fail it) if MINFO isn't present.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 71a4f2832c3fe02d026af8241767ee80f440e876
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Apr 21 21:10:01 2015 +0200

    Remove old testing scripts out of the way.
    
    For now, I'm moving them into Attic/.  They will be removed later.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit fd9ad2300b280c0f71d24456bfbf04579331bc94
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Apr 21 20:09:36 2015 +0200

    Adapt mk1mf.pl and helpers to the new testing framework.
    
    With the new testing framework, building a test target with mk1mf.pl
    becomes a very simple thing.  And especially, no more need to do the
    amount of hackery in unix.pl we did.
    
    Also, some tests need a working apps/CA.pl as well as rehashed certs
    in certs/demo.  So, move the code creating those files so it gets done
    regardless, not just in non-mk1mf environments.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 93de4f58ef8be2cb764343cb3102d41c81f11593
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Apr 21 19:29:01 2015 +0200

    Simplify very simple test recipes further.
    
    Very simple test recipes easily become tedious, so they might benefit
    from being made as simple as possible.  Therefore, OpenSSL::Test::Simple
    is born.  It currently provides but one function, simple_test(), which
    takes a minimum of two parameters (test name and program to run), with
    the optional third, being the algorithm to be checked for before
    running the test itself.
    
    All recipes with that simple thing to do have been rewritten to be as
    minimal as possible.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit d11b43fdd30f084c19136359d0e3e4a06631abf9
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Apr 19 23:49:30 2015 +0200

    Remove test targets from Makefile, have it use run_tests.pl
    
    Also remove recipes/00-check_testalltests.t, since it will lack the
    information from the now gone alltests target.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 7dc11227a385fd7e248e1292653761ec9ce9c105
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Apr 19 22:29:46 2015 +0200

    Ignore the log files
    
    The new test framework produces a lot of log files (one for each
    test).  Git doesn't need to know.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 127d25903fc705756ac211ea373104d8e8858ae1
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Apr 19 22:26:12 2015 +0200

    Add recipes for misc other things we want to test
    
    Note that this required a change in constant_time_test.c, as it says
    "ok", which interferes with what Test::Harness expects to see.  I had
    constant_time_test.c say "success" instead.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 88b8a5279f452027c193c2de7909dd9f7c9736c6
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Apr 19 22:24:17 2015 +0200

    Add recipes for the larger protocols
    
    This covers the certificate authority commands, the cms and smime
    commands, OCSP, SSL and TSA.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 4fb35f8fcba5b49bdf8223e1964ef4cf640ea0ca
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Apr 17 20:16:13 2015 +0200

    Add engine and evp test recipes.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 4650de3e431d123e988821215f6473e93c3d4b17
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Apr 17 20:15:22 2015 +0200

    Add recipes for tests related to certificates
    
    Some of them make use of recipes/tconversion.pl.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 0c85cc506916039bba86e8335aa71e0e44f038b0
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Apr 17 20:13:58 2015 +0200

    Add asymetric cipher test recipes
    
    Some of them make use of recipes/tconversion.pl.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 904ae3342600fe1dae3e0835a784c73b7c237106
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Apr 17 20:10:24 2015 +0200

    Add a helper script for key file format conversion tests
    
    As tests are done until now, there are a few scripts that look almost,
    but not quite the same.  tkey, tx509, tcrl, tpkcs7, treq, tsid and
    probably a few more.
    
    recipes/tconversions.pl is a helper script that generalises the
    function of each of those, and can then be used in a general manner
    from test recipes.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 13350a0c0eb8937c299c394a88d6cb51d3356d1f
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Apr 17 20:07:13 2015 +0200

    Add the encryption test recipe
    
    This tests all available openssl cipher commands.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 894025c6428e7a78fb251e7a16522c3b7351f357
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Apr 17 20:04:19 2015 +0200

    Add recipes for individual block ciphers, stream ciphers and digests
    
    These recipes all correspond to a compiled test program.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit f3356b7f49823ddf31683667dfd376312b0a92a3
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Apr 17 19:57:55 2015 +0200

    Add math tests recipes
    
    The math recipes are among the heavier, but also quite important.
    For the BN test, we have previously relied on bc to verify the numbers.
    Unfortunately, bc doesn't exist everywhere, making tests on some platforms
    rather painful.  With the new recipe (recipes/10-test_bn.t), we rely
    on perl's Math::BigInt and a homegrown simple calculator (recipes/bc.pl)
    that can do enough to cover for bc.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit aec27d4d5210234560deab85c97bd453535f66ae
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Apr 17 19:44:48 2015 +0200

    Groundwork for a perl based testing framework
    
    The idea with this perl based testing framework is to make use of
    what's delivered with perl and exists on all sorts of platforms.
    
    The choice came to using Test::More and Test::Harness, as that seems
    to be the most widely spread foundation, even if perl is aged.
    
    The main runner of the show is run_tests.pl.  As it currently stands,
    it's designed to run from inside Makefile, but it's absolutely
    possible to run it from the command line as well, like so:
    
    	cd test
    	OPENSSL_SRCDIR=.. perl run_tests.pl
    
    The tester scripts themselves are stored in the subdirectory recipes/,
    and initially, we have two such scripts, recipes/00-check_testalltests.t
    and recipes/00-check_testexes.t.  recipes/00-check_testalltests.t will
    pick out the dependencies of "alltests" in test/Makefile, and check if
    it can find recipes with corresponding names.  recipes/00-check_testexes.t
    does something similar, but bases it on existing compiled test binaries.
    They make it easy to figure out what's to be added, and will be
    removed when this effort is finished.
    
    Individual recipes can be run as well, of course, as they are perl
    scripts in themselves.  For example, you can run only
    recipes/00-check_testexes.t like so:
    
    	cd test
    	OPENSSL_SRCDIR=.. perl recipes/00-check_testexes.t
    
    To make coding easier, there's a routine library OpenSSL::Test, which
    is reachable in a perl script like so:
    
    	use lib 'testlib';
    	use OpenSSL::Test;
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 .gitignore                                         |   1 +
 CHANGES                                            |  15 +
 Configure                                          |  18 +-
 test/{ => Attic}/VMSca-response.1                  |   0
 test/{ => Attic}/VMSca-response.2                  |   0
 test/{ => Attic}/bctest                            |   0
 test/{ => Attic}/bctest.com                        |   0
 test/{ => Attic}/bntest.com                        |   0
 test/{ => Attic}/cms-test.pl                       |   0
 test/{ => Attic}/tcrl                              |   0
 test/{ => Attic}/tcrl.com                          |   0
 test/{ => Attic}/testca                            |   0
 test/{ => Attic}/testca.com                        |   0
 test/{ => Attic}/testenc                           |   0
 test/{ => Attic}/testenc.com                       |   0
 test/{ => Attic}/testgen                           |   0
 test/{ => Attic}/testgen.com                       |   0
 test/{ => Attic}/testss                            |   0
 test/{ => Attic}/testss.com                        |   0
 test/{ => Attic}/testssl                           |   0
 test/{ => Attic}/testssl.com                       |   0
 test/{ => Attic}/testsslproxy                      |   0
 test/{ => Attic}/testtsa                           |   0
 test/{ => Attic}/testtsa.com                       |   0
 test/{ => Attic}/tkey                              |   0
 test/{ => Attic}/tocsp                             |   0
 test/{ => Attic}/tocsp.com                         |   0
 test/{ => Attic}/tpkcs7                            |   0
 test/{ => Attic}/tpkcs7.com                        |   0
 test/{ => Attic}/tpkcs7d                           |   0
 test/{ => Attic}/tpkcs7d.com                       |   0
 test/{ => Attic}/treq                              |   0
 test/{ => Attic}/treq.com                          |   0
 test/{ => Attic}/trsa.com                          |   0
 test/{ => Attic}/tsid                              |   0
 test/{ => Attic}/tsid.com                          |   0
 test/{ => Attic}/tverify.com                       |   0
 test/{ => Attic}/tx509                             |   0
 test/{ => Attic}/tx509.com                         |   0
 test/Makefile                                      | 321 +--------
 test/README                                        | 107 +++
 test/bntest.c                                      |   6 +
 test/constant_time_test.c                          |   2 +-
 test/recipes/00-check_testexes.t                   |  59 ++
 test/recipes/05-test_bf.t                          |   5 +
 test/recipes/05-test_cast.t                        |   5 +
 test/recipes/05-test_des.t                         |   5 +
 test/recipes/05-test_hmac.t                        |   5 +
 test/recipes/05-test_idea.t                        |   5 +
 test/recipes/05-test_md2.t                         |   5 +
 test/recipes/05-test_md4.t                         |   5 +
 test/recipes/05-test_md5.t                         |   5 +
 test/recipes/05-test_mdc2.t                        |   5 +
 test/recipes/05-test_rand.t                        |   5 +
 test/recipes/05-test_rc2.t                         |   5 +
 test/recipes/05-test_rc4.t                         |   5 +
 test/recipes/05-test_rc5.t                         |   5 +
 test/recipes/05-test_rmd.t                         |   5 +
 test/recipes/05-test_sha1.t                        |   5 +
 test/recipes/05-test_sha256.t                      |   5 +
 test/recipes/05-test_sha512.t                      |   5 +
 test/recipes/05-test_wp.t                          |   5 +
 test/recipes/10-test_bn.t                          |  75 +++
 test/recipes/10-test_exp.t                         |   5 +
 test/recipes/15-test_dh.t                          |   5 +
 test/recipes/15-test_dsa.t                         |  32 +
 test/recipes/15-test_ec.t                          |  30 +
 test/recipes/15-test_ecdh.t                        |   5 +
 test/recipes/15-test_ecdsa.t                       |   5 +
 test/recipes/15-test_rsa.t                         |  31 +
 test/recipes/20-test_enc.t                         |  64 ++
 test/recipes/25-test_crl.t                         |  17 +
 test/recipes/25-test_gen.t                         |  43 ++
 test/recipes/25-test_pkcs7.t                       |  20 +
 test/recipes/25-test_req.t                         |  43 ++
 test/recipes/25-test_sid.t                         |  17 +
 test/recipes/25-test_verify.t                      |  15 +
 test/recipes/25-test_x509.t                        |  23 +
 test/recipes/30-test_engine.t                      |  11 +
 test/recipes/30-test_evp.t                         |  12 +
 test/recipes/30-test_evp_extra.t                   |  11 +
 test/recipes/30-test_pbelu.t                       |   5 +
 test/recipes/70-test_clienthello.t                 |   5 +
 test/recipes/70-test_packet.t                      |   5 +
 .../70-test_sslextension.t}                        |  20 +-
 .../70-test_sslsessiontick.t}                      |  91 +--
 .../70-test_sslskewith0p.t}                        |  20 +-
 .../70-test_sslvertol.t}                           |  22 +-
 test/recipes/70-test_verify_extra.t                |   5 +
 test/recipes/80-test_ca.t                          |  54 ++
 test/recipes/80-test_cms.t                         | 476 +++++++++++++
 test/recipes/80-test_ocsp.t                        | 193 ++++++
 test/recipes/80-test_ssl.t                         | 627 +++++++++++++++++
 test/recipes/80-test_tsa.t                         | 192 ++++++
 test/recipes/90-test_constant_time.t               |   5 +
 test/recipes/90-test_gmdiff.t                      |   5 +
 test/recipes/90-test_gost2814789.t                 |  13 +
 test/recipes/90-test_heartbeat.t                   |   5 +
 test/recipes/90-test_ige.t                         |   5 +
 test/recipes/90-test_jpake.t                       |   5 +
 test/recipes/90-test_np.t                          |   5 +
 test/recipes/90-test_p5_crpt2.t                    |   5 +
 test/recipes/90-test_secmem.t                      |   5 +
 test/recipes/90-test_srp.t                         |   5 +
 test/recipes/90-test_v3name.t                      |   5 +
 test/recipes/bc.pl                                 |  97 +++
 test/recipes/tconversion.pl                        |  88 +++
 test/run_tests.pl                                  |  45 ++
 test/testlib/OpenSSL/Test.pm                       | 741 +++++++++++++++++++++
 test/testlib/OpenSSL/Test/Simple.pm                |  78 +++
 util/mk1mf.pl                                      |  17 +-
 util/pl/BC-32.pl                                   |  23 +
 util/pl/VC-32.pl                                   |  23 +
 util/pl/unix.pl                                    | 279 +-------
 114 files changed, 3606 insertions(+), 646 deletions(-)
 rename test/{ => Attic}/VMSca-response.1 (100%)
 rename test/{ => Attic}/VMSca-response.2 (100%)
 rename test/{ => Attic}/bctest (100%)
 rename test/{ => Attic}/bctest.com (100%)
 rename test/{ => Attic}/bntest.com (100%)
 rename test/{ => Attic}/cms-test.pl (100%)
 rename test/{ => Attic}/tcrl (100%)
 rename test/{ => Attic}/tcrl.com (100%)
 rename test/{ => Attic}/testca (100%)
 rename test/{ => Attic}/testca.com (100%)
 rename test/{ => Attic}/testenc (100%)
 rename test/{ => Attic}/testenc.com (100%)
 rename test/{ => Attic}/testgen (100%)
 rename test/{ => Attic}/testgen.com (100%)
 rename test/{ => Attic}/testss (100%)
 rename test/{ => Attic}/testss.com (100%)
 rename test/{ => Attic}/testssl (100%)
 rename test/{ => Attic}/testssl.com (100%)
 rename test/{ => Attic}/testsslproxy (100%)
 rename test/{ => Attic}/testtsa (100%)
 rename test/{ => Attic}/testtsa.com (100%)
 rename test/{ => Attic}/tkey (100%)
 rename test/{ => Attic}/tocsp (100%)
 rename test/{ => Attic}/tocsp.com (100%)
 rename test/{ => Attic}/tpkcs7 (100%)
 rename test/{ => Attic}/tpkcs7.com (100%)
 rename test/{ => Attic}/tpkcs7d (100%)
 rename test/{ => Attic}/tpkcs7d.com (100%)
 rename test/{ => Attic}/treq (100%)
 rename test/{ => Attic}/treq.com (100%)
 rename test/{ => Attic}/trsa.com (100%)
 rename test/{ => Attic}/tsid (100%)
 rename test/{ => Attic}/tsid.com (100%)
 rename test/{ => Attic}/tverify.com (100%)
 rename test/{ => Attic}/tx509 (100%)
 rename test/{ => Attic}/tx509.com (100%)
 create mode 100644 test/README
 create mode 100644 test/recipes/00-check_testexes.t
 create mode 100644 test/recipes/05-test_bf.t
 create mode 100644 test/recipes/05-test_cast.t
 create mode 100644 test/recipes/05-test_des.t
 create mode 100644 test/recipes/05-test_hmac.t
 create mode 100644 test/recipes/05-test_idea.t
 create mode 100644 test/recipes/05-test_md2.t
 create mode 100644 test/recipes/05-test_md4.t
 create mode 100644 test/recipes/05-test_md5.t
 create mode 100644 test/recipes/05-test_mdc2.t
 create mode 100644 test/recipes/05-test_rand.t
 create mode 100644 test/recipes/05-test_rc2.t
 create mode 100644 test/recipes/05-test_rc4.t
 create mode 100644 test/recipes/05-test_rc5.t
 create mode 100644 test/recipes/05-test_rmd.t
 create mode 100644 test/recipes/05-test_sha1.t
 create mode 100644 test/recipes/05-test_sha256.t
 create mode 100644 test/recipes/05-test_sha512.t
 create mode 100644 test/recipes/05-test_wp.t
 create mode 100644 test/recipes/10-test_bn.t
 create mode 100644 test/recipes/10-test_exp.t
 create mode 100644 test/recipes/15-test_dh.t
 create mode 100644 test/recipes/15-test_dsa.t
 create mode 100644 test/recipes/15-test_ec.t
 create mode 100644 test/recipes/15-test_ecdh.t
 create mode 100644 test/recipes/15-test_ecdsa.t
 create mode 100644 test/recipes/15-test_rsa.t
 create mode 100644 test/recipes/20-test_enc.t
 create mode 100644 test/recipes/25-test_crl.t
 create mode 100644 test/recipes/25-test_gen.t
 create mode 100644 test/recipes/25-test_pkcs7.t
 create mode 100644 test/recipes/25-test_req.t
 create mode 100644 test/recipes/25-test_sid.t
 create mode 100644 test/recipes/25-test_verify.t
 create mode 100644 test/recipes/25-test_x509.t
 create mode 100644 test/recipes/30-test_engine.t
 create mode 100644 test/recipes/30-test_evp.t
 create mode 100644 test/recipes/30-test_evp_extra.t
 create mode 100644 test/recipes/30-test_pbelu.t
 create mode 100644 test/recipes/70-test_clienthello.t
 create mode 100644 test/recipes/70-test_packet.t
 rename test/{sslextensiontest.pl => recipes/70-test_sslextension.t} (85%)
 rename test/{sslsessionticktest.pl => recipes/70-test_sslsessiontick.t} (75%)
 rename test/{sslskewith0ptest.pl => recipes/70-test_sslskewith0p.t} (85%)
 rename test/{sslvertoltest.pl => recipes/70-test_sslvertol.t} (84%)
 create mode 100644 test/recipes/70-test_verify_extra.t
 create mode 100644 test/recipes/80-test_ca.t
 create mode 100644 test/recipes/80-test_cms.t
 create mode 100644 test/recipes/80-test_ocsp.t
 create mode 100644 test/recipes/80-test_ssl.t
 create mode 100644 test/recipes/80-test_tsa.t
 create mode 100644 test/recipes/90-test_constant_time.t
 create mode 100644 test/recipes/90-test_gmdiff.t
 create mode 100644 test/recipes/90-test_gost2814789.t
 create mode 100644 test/recipes/90-test_heartbeat.t
 create mode 100644 test/recipes/90-test_ige.t
 create mode 100644 test/recipes/90-test_jpake.t
 create mode 100644 test/recipes/90-test_np.t
 create mode 100644 test/recipes/90-test_p5_crpt2.t
 create mode 100644 test/recipes/90-test_secmem.t
 create mode 100644 test/recipes/90-test_srp.t
 create mode 100644 test/recipes/90-test_v3name.t
 create mode 100644 test/recipes/bc.pl
 create mode 100644 test/recipes/tconversion.pl
 create mode 100644 test/run_tests.pl
 create mode 100644 test/testlib/OpenSSL/Test.pm
 create mode 100644 test/testlib/OpenSSL/Test/Simple.pm

diff --git a/.gitignore b/.gitignore
index 3292837..92f17c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,7 @@
 /test/.rnd
 /test/test*.pem
 /test/newkey.pem
+/test/*.log
 
 # Certificate symbolic links
 *.0
diff --git a/CHANGES b/CHANGES
index 384abf8..a7dab6c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,21 @@
 
  Changes between 1.0.2 and 1.1.0  [xx XXX xxxx]
 
+  *) New testing framework
+     The testing framework has been largely rewritten and is now using
+     perl and the perl modules Test::Harness and an extended variant of
+     Test::More called OpenSSL::Test to do its work.  All test scripts in
+     test/ have been rewritten into test recipes, and all direct calls to
+     executables in test/Makefile have become individual recipes using the
+     simplified testing OpenSSL::Test::Simple.
+
+     For documentation on our testing modules, do:
+
+        perldoc test/testlib/OpenSSL/Test/Simple.pm
+        perldoc test/testlib/OpenSSL/Test.pm
+
+     [Richard Levitte]
+
   *) In DSA_generate_parameters_ex, if the provided seed is too short,
      return an error
      [Rich Salz and Ismo Puustinen <ismo.puustinen at intel.com>]
diff --git a/Configure b/Configure
index f6007c1..2fc1e59 100755
--- a/Configure
+++ b/Configure
@@ -1983,6 +1983,16 @@ print "RC2 uses u$type[$rc2_int]\n" if $rc2_int != $def_int;
 print "BF_PTR used\n" if $bf_ptr == 1;
 print "BF_PTR2 used\n" if $bf_ptr == 2;
 
+{
+    my $perlguess = $perl =~ m@^/@ ? $perl : '/usr/local/bin/perl';
+
+    &dofile("tools/c_rehash",$perlguess,
+	    '^#!/'		=> '#!%s',
+	    '^my \$dir;$'	=> 'my $dir = "' . $openssldir . '";',
+	    '^my \$prefix;$'	=> 'my $prefix = "' . $prefix . '";');
+    &dofile("apps/CA.pl",$perl,
+	    '^#!/'		=> '#!%s');
+}
 if($IsMK1MF) {
 	open (OUT,">crypto/buildinf.h") || die "Can't open buildinf.h";
 	printf OUT <<EOF;
@@ -2001,14 +2011,6 @@ EOF
 	$make_targets .= " depend" if $depflags ne $default_depflags && $make_depend;
 	(system $make_command.$make_targets) == 0 or die "make $make_targets failed"
 		if $make_targets ne "";
-	if ( $perl =~ m@^/@) {
-	    &dofile("tools/c_rehash",$perl,'^#!/', '#!%s','^my \$dir;$', 'my $dir = "' . $openssldir . '";', '^my \$prefix;$', 'my $prefix = "' . $prefix . '";');
-	    &dofile("apps/CA.pl",$perl,'^#!/', '#!%s');
-	} else {
-	    # No path for Perl known ...
-	    &dofile("tools/c_rehash",'/usr/local/bin/perl','^#!/', '#!%s','^my \$dir;$', 'my $dir = "' . $openssldir . '";',  '^my \$prefix;$', 'my $prefix = "' . $prefix . '";');
-	    &dofile("apps/CA.pl",'/usr/local/bin/perl','^#!/', '#!%s');
-	}
 	if ($depflags ne $default_depflags && !$make_depend) {
 		print <<EOF;
 
diff --git a/test/VMSca-response.1 b/test/Attic/VMSca-response.1
similarity index 100%
rename from test/VMSca-response.1
rename to test/Attic/VMSca-response.1
diff --git a/test/VMSca-response.2 b/test/Attic/VMSca-response.2
similarity index 100%
rename from test/VMSca-response.2
rename to test/Attic/VMSca-response.2
diff --git a/test/bctest b/test/Attic/bctest
similarity index 100%
rename from test/bctest
rename to test/Attic/bctest
diff --git a/test/bctest.com b/test/Attic/bctest.com
similarity index 100%
rename from test/bctest.com
rename to test/Attic/bctest.com
diff --git a/test/bntest.com b/test/Attic/bntest.com
similarity index 100%
rename from test/bntest.com
rename to test/Attic/bntest.com
diff --git a/test/cms-test.pl b/test/Attic/cms-test.pl
similarity index 100%
rename from test/cms-test.pl
rename to test/Attic/cms-test.pl
diff --git a/test/tcrl b/test/Attic/tcrl
similarity index 100%
rename from test/tcrl
rename to test/Attic/tcrl
diff --git a/test/tcrl.com b/test/Attic/tcrl.com
similarity index 100%
rename from test/tcrl.com
rename to test/Attic/tcrl.com
diff --git a/test/testca b/test/Attic/testca
similarity index 100%
rename from test/testca
rename to test/Attic/testca
diff --git a/test/testca.com b/test/Attic/testca.com
similarity index 100%
rename from test/testca.com
rename to test/Attic/testca.com
diff --git a/test/testenc b/test/Attic/testenc
similarity index 100%
rename from test/testenc
rename to test/Attic/testenc
diff --git a/test/testenc.com b/test/Attic/testenc.com
similarity index 100%
rename from test/testenc.com
rename to test/Attic/testenc.com
diff --git a/test/testgen b/test/Attic/testgen
similarity index 100%
rename from test/testgen
rename to test/Attic/testgen
diff --git a/test/testgen.com b/test/Attic/testgen.com
similarity index 100%
rename from test/testgen.com
rename to test/Attic/testgen.com
diff --git a/test/testss b/test/Attic/testss
similarity index 100%
rename from test/testss
rename to test/Attic/testss
diff --git a/test/testss.com b/test/Attic/testss.com
similarity index 100%
rename from test/testss.com
rename to test/Attic/testss.com
diff --git a/test/testssl b/test/Attic/testssl
similarity index 100%
rename from test/testssl
rename to test/Attic/testssl
diff --git a/test/testssl.com b/test/Attic/testssl.com
similarity index 100%
rename from test/testssl.com
rename to test/Attic/testssl.com
diff --git a/test/testsslproxy b/test/Attic/testsslproxy
similarity index 100%
rename from test/testsslproxy
rename to test/Attic/testsslproxy
diff --git a/test/testtsa b/test/Attic/testtsa
similarity index 100%
rename from test/testtsa
rename to test/Attic/testtsa
diff --git a/test/testtsa.com b/test/Attic/testtsa.com
similarity index 100%
rename from test/testtsa.com
rename to test/Attic/testtsa.com
diff --git a/test/tkey b/test/Attic/tkey
similarity index 100%
rename from test/tkey
rename to test/Attic/tkey
diff --git a/test/tocsp b/test/Attic/tocsp
similarity index 100%
rename from test/tocsp
rename to test/Attic/tocsp
diff --git a/test/tocsp.com b/test/Attic/tocsp.com
similarity index 100%
rename from test/tocsp.com
rename to test/Attic/tocsp.com
diff --git a/test/tpkcs7 b/test/Attic/tpkcs7
similarity index 100%
rename from test/tpkcs7
rename to test/Attic/tpkcs7
diff --git a/test/tpkcs7.com b/test/Attic/tpkcs7.com
similarity index 100%
rename from test/tpkcs7.com
rename to test/Attic/tpkcs7.com
diff --git a/test/tpkcs7d b/test/Attic/tpkcs7d
similarity index 100%
rename from test/tpkcs7d
rename to test/Attic/tpkcs7d
diff --git a/test/tpkcs7d.com b/test/Attic/tpkcs7d.com
similarity index 100%
rename from test/tpkcs7d.com
rename to test/Attic/tpkcs7d.com
diff --git a/test/treq b/test/Attic/treq
similarity index 100%
rename from test/treq
rename to test/Attic/treq
diff --git a/test/treq.com b/test/Attic/treq.com
similarity index 100%
rename from test/treq.com
rename to test/Attic/treq.com
diff --git a/test/trsa.com b/test/Attic/trsa.com
similarity index 100%
rename from test/trsa.com
rename to test/Attic/trsa.com
diff --git a/test/tsid b/test/Attic/tsid
similarity index 100%
rename from test/tsid
rename to test/Attic/tsid
diff --git a/test/tsid.com b/test/Attic/tsid.com
similarity index 100%
rename from test/tsid.com
rename to test/Attic/tsid.com
diff --git a/test/tverify.com b/test/Attic/tverify.com
similarity index 100%
rename from test/tverify.com
rename to test/Attic/tverify.com
diff --git a/test/tx509 b/test/Attic/tx509
similarity index 100%
rename from test/tx509
rename to test/Attic/tx509
diff --git a/test/tx509.com b/test/Attic/tx509.com
similarity index 100%
rename from test/tx509.com
rename to test/Attic/tx509.com
diff --git a/test/Makefile b/test/Makefile
index 0900a92..9ead38e 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -74,10 +74,10 @@ CONSTTIMETEST=  constant_time_test
 VERIFYEXTRATEST=	verify_extra_test
 CLIENTHELLOTEST=	clienthellotest
 PACKETTEST=	packettest
-SSLVERTOLTEST=	sslvertoltest.pl
-SSLEXTENSIONTEST=	sslextensiontest.pl
-SSLSESSIONTICKTEST= 	sslsessionticktest.pl
-SSLSKEWITH0PTEST=	sslskewith0ptest.pl
+SSLVERTOLTEST=	sslvertoltest
+SSLEXTENSIONTEST=	sslextensiontest
+SSLSESSIONTICKTEST= 	sslsessionticktest
+SSLSKEWITH0PTEST=	sslskewith0ptest
 
 TESTS=		alltests
 
@@ -151,319 +151,12 @@ errors:
 tags:
 	ctags $(SRC)
 
-tests:	exe apps $(TESTS)
+tests:	exe apps
+	TOP=$(TOP) PERL=$(PERL) $(PERL) run_tests.pl $(TESTS)
 
 apps:
 	@(cd ..; $(MAKE) DIRS=apps all)
 
-alltests: \
-	test_np \
-	test_des test_gmdiff test_idea test_sha test_md4 test_md5 test_hmac \
-	test_pbelu test_md2 test_mdc2 test_wp \
-	test_rmd test_rc2 test_rc4 test_rc5 test_bf test_cast \
-	test_rand test_bn test_ec test_ecdsa test_ecdh \
-	test_enc test_x509 test_rsa test_crl test_sid \
-	test_gen test_req test_pkcs7 test_verify test_dh test_dsa \
-	test_ss test_ca test_engine test_evp test_evp_extra test_ssl test_tsa \
-	test_ige test_jpake test_secmem \
-	test_srp test_cms test_v3name test_ocsp \
-	test_gost2814789 test_heartbeat test_p5_crpt2 \
-	test_constant_time test_verify_extra test_clienthello test_packet \
-	test_sslvertol test_sslextension test_sslsessionticket test_sslskewith0p
-
-test_np: $(NPTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(NPTEST)
-
-test_evp: $(EVPTEST)$(EXE_EXT) evptests.txt
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(EVPTEST) evptests.txt
-
-test_evp_extra: $(EVPEXTRATEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(EVPEXTRATEST)
-
-test_p5_crpt2: $(P5_CRPT2_TEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(P5_CRPT2_TEST)
-
-test_des: $(DESTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(DESTEST)
-
-test_gmdiff: $(GMDIFFTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(GMDIFFTEST)
-
-test_pbelu: $(PBELUTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(PBELUTEST)
-
-test_idea: $(IDEATEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(IDEATEST)
-
-test_sha: $(SHA1TEST)$(EXE_EXT) $(SHA256TEST)$(EXE_EXT) $(SHA512TEST)$(EXE_EXT)
-	@echo $(START) $@ -- sha1
-	../util/shlib_wrap.sh ./$(SHA1TEST)
-	@echo $(START) $@ -- sha256
-	../util/shlib_wrap.sh ./$(SHA256TEST)
-	@echo $(START) $@ -- sha512
-	../util/shlib_wrap.sh ./$(SHA512TEST)
-
-test_mdc2: $(MDC2TEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(MDC2TEST)
-
-test_md5: $(MD5TEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(MD5TEST)
-
-test_md4: $(MD4TEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(MD4TEST)
-
-test_hmac: $(HMACTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(HMACTEST)
-
-test_wp: $(WPTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(WPTEST)
-
-test_md2: $(MD2TEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(MD2TEST)
-
-test_rmd: $(RMDTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(RMDTEST)
-
-test_bf: $(BFTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(BFTEST)
-
-test_cast: $(CASTTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(CASTTEST)
-
-test_rc2: $(RC2TEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(RC2TEST)
-
-test_rc4: $(RC4TEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(RC4TEST)
-
-test_rc5: $(RC5TEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(RC5TEST)
-
-test_rand: $(RANDTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(RANDTEST)
-
-test_gost2814789: $(GOST2814789TEST)$(EXE_EXT)
-	@echo $(START) $@
-	OPENSSL_ENGINES=../engines/ccgost ../util/shlib_wrap.sh ./$(GOST2814789TEST)
-
-test_enc: ../apps/openssl$(EXE_EXT) testenc
-	@echo $(START) $@
-	@sh ./testenc
-
-test_x509: ../apps/openssl$(EXE_EXT) tx509 testx509.pem v3-cert1.pem v3-cert2.pem
-	@echo $(START) $@ -- x509v1 certificate
-	sh ./tx509
-	@echo $(START) $@ -- first x509v3 certificate
-	sh ./tx509 v3-cert1.pem
-	@echo $(START) $@ -- second x509v3 certificate
-	sh ./tx509 v3-cert2.pem
-
-test_rsa: $(RSATEST)$(EXE_EXT) ../apps/openssl$(EXE_EXT) tkey testrsa.pem testrsapub.pem
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(RSATEST)
-	@echo $(START) $@ -- private key
-	@sh ./tkey testrsa.pem rsa private
-	@echo $(START) $@ -- public public
-	@sh ./tkey testrsapub.pem rsa public
-
-test_crl: ../apps/openssl$(EXE_EXT) tcrl testcrl.pem
-	@echo $(START) $@
-	sh ./tcrl
-
-test_sid: ../apps/openssl$(EXE_EXT) tsid testsid.pem
-	@echo $(START) $@
-	@sh ./tsid
-
-test_req: ../apps/openssl$(EXE_EXT) treq testreq.pem testreq2.pem
-	@echo $(START) $@
-	@sh ./treq
-	@echo $(START) $@ -- testreq2
-	@sh ./treq testreq2.pem
-
-test_pkcs7: ../apps/openssl$(EXE_EXT) tpkcs7 tpkcs7d testp7.pem pkcs7-1.pem
-	@echo $(START) $@ -- pkcs7
-	@sh ./tpkcs7
-	@echo $(START) $@ -- pkcs7d
-	@sh ./tpkcs7d
-
-test_bn: $(BNTEST)$(EXE_EXT) $(EXPTEST)$(EXE_EXT) bctest
-	@echo $(START) $@ -- could take  a while.
-	@../util/shlib_wrap.sh ./$(BNTEST) >tmp.bntest
-	@echo quit >>tmp.bntest
-	@echo $(START) $@ -- running bc
-	@<tmp.bntest sh -c "`sh ./bctest ignore`" | $(PERL) -e '$$i=0; while (<STDIN>) {if (/^test (.*)/) {print STDERR "\nverify $$1";} elsif (!/^0\r?$$/) {die "\nFailed! bc: $$_";} else {print STDERR "."; $$i++;}} print STDERR "\n$$i tests passed\n"'
-	@echo $(START) $@ -- $(EXPTEST)
-	../util/shlib_wrap.sh ./$(EXPTEST)
-
-test_ec: $(ECTEST)$(EXE_EXT) tkey testec-p256.pem testecpub-p256.pem
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(ECTEST)
-	@echo $(START) $@ -- private
-	@sh ./tkey testec-p256.pem ec private
-	@echo $(START) $@ -- public
-	@sh ./tkey testecpub-p256.pem ec public
-
-test_ecdsa: $(ECDSATEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(ECDSATEST)
-
-test_ecdh: $(ECDHTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(ECDHTEST)
-
-test_verify: ../apps/openssl$(EXE_EXT)
-	@echo $(START) $@ -- expect some failures and expired certificates
-	../util/shlib_wrap.sh ../apps/openssl verify -CApath ../certs/demo ../certs/demo/*.pem
-
-test_dh: $(DHTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(DHTEST)
-
-test_dsa: $(DSATEST)$(EXE_EXT) tkey testdsa.pem testdsapub.pem
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(DSATEST)
-	@echo $(START) $@ -- app2_1
-	../util/shlib_wrap.sh ./$(DSATEST) -app2_1
-	@echo $(START) $@ -- private
-	@sh ./tkey testdsa.pem dsa private
-	@echo $(START) $@ -- public
-	@sh ./tkey testdsapub.pem dsa public
-
-test_gen testreq.pem: ../apps/openssl$(EXE_EXT) testgen test.cnf
-	@echo $(START) test_gen
-	@sh ./testgen
-
-test_ss keyU.ss certU.ss certCA.ss certP1.ss keyP1.ss certP2.ss keyP2.ss \
-		intP1.ss intP2.ss: testss CAss.cnf Uss.cnf P1ss.cnf P2ss.cnf \
-                                   ../apps/openssl$(EXE_EXT)
-	@echo $(START) test_ss
-	@sh ./testss
-	@cat certCA.ss certU.ss > intP1.ss
-	@cat certCA.ss certU.ss certP1.ss > intP2.ss
-
-test_engine: $(ENGINETEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(ENGINETEST)
-
-test_ssl: keyU.ss certU.ss certCA.ss certP1.ss keyP1.ss certP2.ss keyP2.ss \
-		intP1.ss intP2.ss $(SSLTEST)$(EXE_EXT) testssl testsslproxy \
-		../apps/server2.pem serverinfo.pem
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(SSLTEST) -test_cipherlist
-	@echo $(START) $@ -- key U
-	@sh ./testssl keyU.ss certU.ss certCA.ss
-	@echo $(START) $@ -- key P1
-	@sh ./testsslproxy keyP1.ss certP1.ss intP1.ss
-	@echo $(START) $@ -- key P2
-	@sh ./testsslproxy keyP2.ss certP2.ss intP2.ss
-
-test_ca: ../apps/openssl$(EXE_EXT) testca CAss.cnf Uss.cnf
-	@if ../util/shlib_wrap.sh ../apps/openssl no-rsa; then \
-	  echo SKIP $@ -- requires RSA; \
-	else \
-	  echo $(START) $@; \
-	  sh ./testca $(PERL); \
-	fi
-
-test_tsa: ../apps/openssl$(EXE_EXT) testtsa CAtsa.cnf ../util/shlib_wrap.sh
-	@if ../util/shlib_wrap.sh ../apps/openssl no-rsa; then \
-	    echo SKIP $@ -- requires RSA; \
-	else \
-	  echo $(START) $@; \
-	  sh ./testtsa; \
-	fi
-
-test_ige: $(IGETEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(IGETEST)
-
-test_jpake: $(JPAKETEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(JPAKETEST)
-
-test_cms: ../apps/openssl$(EXE_EXT) cms-test.pl smcont.txt
-	@echo $(START) $@
-	$(PERL) cms-test.pl
-
-test_secmem: $(SECMEMTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./secmemtest
-
-test_srp: $(SRPTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./srptest
-
-test_v3name: $(V3NAMETEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(V3NAMETEST)
-
-test_ocsp: ../apps/openssl$(EXE_EXT) tocsp
-	@echo $(START) $@
-	@sh ./tocsp
-
-test_heartbeat: $(HEARTBEATTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(HEARTBEATTEST)
-
-test_constant_time: $(CONSTTIMETEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(CONSTTIMETEST)
-
-test_verify_extra: $(VERIFYEXTRATEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(VERIFYEXTRATEST) \
-                certs/roots.pem certs/untrusted.pem certs/bad.pem
-
-test_clienthello: $(CLIENTHELLOTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(CLIENTHELLOTEST)
-
-test_packet: $(PACKETTEST)$(EXE_EXT)
-	@echo $(START) $@
-	../util/shlib_wrap.sh ./$(PACKETTEST)
-
-#OPENSSL_ia32cap=... in ssl tests below ensures AES-NI is switched off (AES-NI does not go through the testmode engine)
-test_sslvertol: ../apps/openssl$(EXE_EXT)
-	@echo $(START) $@
-	[ -z "$(SHARED_LIBS)" ] || OPENSSL_ENGINES=../engines ../util/shlib_wrap.sh $(PERL) -I../util -w ./$(SSLVERTOLTEST) "OPENSSL_ia32cap='~0x200000200000000' ../apps/openssl$(EXE_EXT)" ../apps/server.pem
-	@[ -n "$(SHARED_LIBS)" ] || echo test_sslvertol can only be performed with OpenSSL configured shared
-
-test_sslextension: ../apps/openssl$(EXE_EXT)
-	@echo $(START) $@
-	[ -z "$(SHARED_LIBS)" ] || OPENSSL_ENGINES=../engines ../util/shlib_wrap.sh $(PERL) -I../util -w ./$(SSLEXTENSIONTEST) "OPENSSL_ia32cap='~0x200000200000000' ../apps/openssl$(EXE_EXT)" ../apps/server.pem
-	@[ -n "$(SHARED_LIBS)" ] || echo test_sslextension can only be performed with OpenSSL configured shared
-
-test_sslsessionticket: ../apps/openssl$(EXE_EXT)
-	@echo $(START) $@
-	[ -z "$(SHARED_LIBS)" ] || PERL5LIB=$$PERL5LIB:../util OPENSSL_ENGINES=../engines ../util/shlib_wrap.sh ./$(SSLSESSIONTICKTEST) "OPENSSL_ia32cap='~0x200000200000000' ../apps/openssl$(EXE_EXT)" ../apps/server.pem
-	@[ -n "$(SHARED_LIBS)" ] || echo test_sslsessionticket can only be performed with OpenSSL configured shared
-
-test_sslskewith0p: ../apps/openssl$(EXE_EXT)
-	@echo $(START) $@
-	[ -z "$(SHARED_LIBS)" ] || OPENSSL_ENGINES=../engines ../util/shlib_wrap.sh $(PERL) -I../util -w ./$(SSLSKEWITH0PTEST) "OPENSSL_ia32cap='~0x200000200000000' ../apps/openssl$(EXE_EXT)" ../apps/server.pem
-	@[ -n "$(SHARED_LIBS)" ] || echo test_sslskewith0p can only be performed with OpenSSL configured shared
-
 update: local_depend
 	@if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi
 
@@ -478,7 +171,7 @@ dclean:
 	rm -f newkey.pem testkey.pem testreq.pem
 
 clean:
-	rm -f .rnd tmp.bntest tmp.bctest *.o *.obj *.dll lib tags core .pure .nfs* *.old *.bak fluff $(EXE) *.ss *.srl log dummytest
+	rm -f .rnd tmp.bntest tmp.bctest *.o *.obj *.dll lib tags core .pure .nfs* *.old *.bak fluff $(EXE) *.ss *.srl log *.log dummytest
 
 $(DLIBSSL):
 	(cd ..; $(MAKE) build_libssl)
diff --git a/test/README b/test/README
new file mode 100644
index 0000000..8df35fe
--- /dev/null
+++ b/test/README
@@ -0,0 +1,107 @@
+How to add recipes
+==================
+
+For any test that you want to perform, you write a script located in
+test/recipes/, named {nn}-test_{name}.t, where {nn} is a two digit number and
+{name} is a unique name of your choice.
+
+Please note that if a test involves a new testing executable, you will need to
+do some additions in test/Makefile.  More on this later.
+
+
+Naming convetions
+=================
+
+A test executable is named test/{name}test.c
+
+A test recipe is named test/recipes/{nn}-test_{name}.t, where {nn} is a two
+digit number and {name} is a unique name of your choice.
+
+The number {nn} is (somewhat loosely) grouped as follows:
+
+05  individual symmetric cipher algorithms
+10  math (bignum)
+15  individual asymmetric cipher algorithms
+20  openssl enc
+25  certificate forms, generation and verification
+30  engine and evp
+70  PACKET layer
+80  "larger" protocols (CA, CMS, OCSP, SSL, TSA)
+90  misc
+
+
+A recipe that just runs a test executable
+=========================================
+
+A script that just runs a program looks like this:
+
+    #! /usr/bin/perl
+    
+    use OpenSSL::Test::Simple;
+    
+    simple_test("test_{name}", "{name}test", "{name}");
+
+{name} is the unique name you have chosen for your test.
+
+The second argument to `simple_test' is the test executable, and `simple_test'
+expects it to be located in test/
+
+For documentation on OpenSSL::Test::Simple, do
+`perldoc test/testlib/OpenSSL/Test/Simple.pm'.
+
+
+A recipe that runs a more complex test
+======================================
+
+For more complex tests, you will need to read up on Test::More and
+OpenSSL::Test.  Test::More is normally preinstalled, do `man Test::More' for
+documentation.  For OpenSSL::Test, do `perldoc test/testlib/OpenSSL/Test.pm'.
+
+A script to start from could be this:
+
+    #! /usr/bin/perl
+    
+    use strict;
+    use warnings;
+    use OpenSSL::Test;
+    
+    setup("test_{name}");
+    
+    plan tests => 2;                # The number of tests being performed
+    
+    ok(test1, "test1");
+    ok(test2, "test1");
+    
+    sub test1
+    {
+        # test feature 1
+    }
+    
+    sub test2
+    {
+        # test feature 2
+    }
+    
+
+Changes to test/Makefile
+========================
+
+Whenever a new test involves a new test executable you need to do the
+following (at all times, replace {NAME} and {name} with the name of your
+test):
+
+* among the variables for test executables at the beginning, add a line like
+  this:
+
+    {NAME}TEST= {name}test
+
+* add `$({NAME}TEST)$(EXE_EXT)' to the assignment of EXE:
+
+* add `$({NAME}TEST).o' to the assignment of OBJ:
+
+* add `$({NAME}TEST).c' to the assignment of SRC:
+
+* add the following lines for building the executable:
+
+    $({NAME}TEST)$(EXE_EXT): $({NAME}TEST).o $(DLIBCRYPTO)
+           @target=$({NAME}TEST); $(BUILD_CMD)
diff --git a/test/bntest.c b/test/bntest.c
index 675d0eb..be358c8 100644
--- a/test/bntest.c
+++ b/test/bntest.c
@@ -175,6 +175,12 @@ int main(int argc, char *argv[])
             EXIT(1);
         }
     }
+#ifdef OPENSSL_SYS_VMS
+    {
+        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
+        out = BIO_push(tmpbio, out);
+    }
+#endif
 
     if (!results)
         BIO_puts(out, "obase=16\nibase=16\n");
diff --git a/test/constant_time_test.c b/test/constant_time_test.c
index ed3d7ea..1c04cb7 100644
--- a/test/constant_time_test.c
+++ b/test/constant_time_test.c
@@ -295,7 +295,7 @@ int main(int argc, char *argv[])
     }
 
     if (!num_failed) {
-        fprintf(stdout, "ok (ran %d tests)\n", num_all);
+        fprintf(stdout, "success (ran %d tests)\n", num_all);
         return EXIT_SUCCESS;
     } else {
         fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
diff --git a/test/recipes/00-check_testexes.t b/test/recipes/00-check_testexes.t
new file mode 100644
index 0000000..3ab38c7
--- /dev/null
+++ b/test/recipes/00-check_testexes.t
@@ -0,0 +1,59 @@
+#! /usr/bin/perl
+
+use strict;
+
+use File::Spec::Functions;
+use File::Basename;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("check_testexes");
+
+my $OpenSSL_ver = "";
+my $Makefile = top_file("Makefile");
+if (open(FH, $Makefile)) {
+    $OpenSSL_ver =
+	(map { chomp; s/^VERSION=([^\s]*)\s*$//; $1 } grep { /^VERSION=/ } <FH>)[0];
+    close FH;
+}
+
+my $MINFO = top_file("MINFO");
+
+plan skip_all => "because MINFO not found. If you want this test to run, please do 'perl util/mkfiles.pl > MINFO'"
+    unless open(FH,$MINFO);
+
+my $MINFO_ver = "";
+
+while(<FH>) {
+    chomp;
+    if (/^VERSION=([^\s]*)\s*$/) {
+	$MINFO_ver = $1;
+    }
+    last if /^RELATIVE_DIRECTORY=test$/;
+}
+while(<FH>) {
+    chomp;
+    last if /^EXE=/;
+}
+close FH;
+
+plan skip_all => "because MINFO is not from this OpenSSL version. If you want this test to run, please do 'perl util/mkfiles.pl > MINFO'"
+    unless $OpenSSL_ver eq $MINFO_ver;
+
+s/^EXE=\s*//;
+s/\s*$//;
+my @expected_tests =
+    map { s/\..*$//;		# Remove extension
+	  s/_?test$//;		# Remove 'test', possibly prefixed with '_'
+	  s/(sha\d+)t/$1/;	# sha comes with no t at the end
+	  $_; } split(/\s+/, $_);
+
+plan tests => scalar @expected_tests;
+
+my @found_tests =
+    map { basename($_) } glob(top_file("test", "recipes", "*.t"));
+
+foreach my $test (sort @expected_tests) {
+    ok(scalar(grep(/^[0-9][0-9]-test_$test\.t$/, @found_tests)),
+       "check that a test for $test exists")
+	|| diag("Expected to find something matching '[0-9][0-9]-test_$test.t'");
+}
diff --git a/test/recipes/05-test_bf.t b/test/recipes/05-test_bf.t
new file mode 100644
index 0000000..4794bf0
--- /dev/null
+++ b/test/recipes/05-test_bf.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_bf", "bftest", "bf");
diff --git a/test/recipes/05-test_cast.t b/test/recipes/05-test_cast.t
new file mode 100644
index 0000000..621e1ae
--- /dev/null
+++ b/test/recipes/05-test_cast.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_cast", "casttest", "cast");
diff --git a/test/recipes/05-test_des.t b/test/recipes/05-test_des.t
new file mode 100644
index 0000000..71de4b4
--- /dev/null
+++ b/test/recipes/05-test_des.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_des", "destest", "des");
diff --git a/test/recipes/05-test_hmac.t b/test/recipes/05-test_hmac.t
new file mode 100644
index 0000000..469d43f
--- /dev/null
+++ b/test/recipes/05-test_hmac.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_hmac", "hmactest", "hmac");
diff --git a/test/recipes/05-test_idea.t b/test/recipes/05-test_idea.t
new file mode 100644
index 0000000..c43ba5c
--- /dev/null
+++ b/test/recipes/05-test_idea.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_idea", "ideatest", "idea");
diff --git a/test/recipes/05-test_md2.t b/test/recipes/05-test_md2.t
new file mode 100644
index 0000000..2175c5f
--- /dev/null
+++ b/test/recipes/05-test_md2.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_md2", "md2test", "md2");
diff --git a/test/recipes/05-test_md4.t b/test/recipes/05-test_md4.t
new file mode 100644
index 0000000..2337223
--- /dev/null
+++ b/test/recipes/05-test_md4.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_md4", "md4test", "md4");
diff --git a/test/recipes/05-test_md5.t b/test/recipes/05-test_md5.t
new file mode 100644
index 0000000..e9331e2
--- /dev/null
+++ b/test/recipes/05-test_md5.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_md5", "md5test", "md5");
diff --git a/test/recipes/05-test_mdc2.t b/test/recipes/05-test_mdc2.t
new file mode 100644
index 0000000..23e904c
--- /dev/null
+++ b/test/recipes/05-test_mdc2.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_mdc2", "mdc2test", "mdc2");
diff --git a/test/recipes/05-test_rand.t b/test/recipes/05-test_rand.t
new file mode 100644
index 0000000..afa66a6
--- /dev/null
+++ b/test/recipes/05-test_rand.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_rand", "randtest", "rand");
diff --git a/test/recipes/05-test_rc2.t b/test/recipes/05-test_rc2.t
new file mode 100644
index 0000000..423b3b7
--- /dev/null
+++ b/test/recipes/05-test_rc2.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_rc2", "rc2test", "rc2");
diff --git a/test/recipes/05-test_rc4.t b/test/recipes/05-test_rc4.t
new file mode 100644
index 0000000..a16455f
--- /dev/null
+++ b/test/recipes/05-test_rc4.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_rc4", "rc4test", "rc4");
diff --git a/test/recipes/05-test_rc5.t b/test/recipes/05-test_rc5.t
new file mode 100644
index 0000000..4c5390a
--- /dev/null
+++ b/test/recipes/05-test_rc5.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_rc5", "rc5test", "rc5");
diff --git a/test/recipes/05-test_rmd.t b/test/recipes/05-test_rmd.t
new file mode 100644
index 0000000..7ad91c4
--- /dev/null
+++ b/test/recipes/05-test_rmd.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_rmd", "rmdtest", "rmd");
diff --git a/test/recipes/05-test_sha1.t b/test/recipes/05-test_sha1.t
new file mode 100644
index 0000000..9f8a570
--- /dev/null
+++ b/test/recipes/05-test_sha1.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_sha1", "sha1test", "sha1");
diff --git a/test/recipes/05-test_sha256.t b/test/recipes/05-test_sha256.t
new file mode 100644
index 0000000..cb63aa8
--- /dev/null
+++ b/test/recipes/05-test_sha256.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_sha256", "sha256t", "sha256");
diff --git a/test/recipes/05-test_sha512.t b/test/recipes/05-test_sha512.t
new file mode 100644
index 0000000..f353ac1
--- /dev/null
+++ b/test/recipes/05-test_sha512.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_sha512", "sha512t", "sha512");
diff --git a/test/recipes/05-test_wp.t b/test/recipes/05-test_wp.t
new file mode 100644
index 0000000..c05be9c
--- /dev/null
+++ b/test/recipes/05-test_wp.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_wp", "wptest", "wp");
diff --git a/test/recipes/10-test_bn.t b/test/recipes/10-test_bn.t
new file mode 100644
index 0000000..29b449f
--- /dev/null
+++ b/test/recipes/10-test_bn.t
@@ -0,0 +1,75 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use Math::BigInt;
+
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_bn");
+
+plan tests => 3;
+
+require_ok(top_file("test","recipes","bc.pl"));
+
+my $testresults = "tmp.bntest";
+my $init = ok(run(test(["bntest"], stdout => $testresults)), 'initialize');
+
+ SKIP: {
+     skip "Initializing failed, skipping", 1 if !$init;
+
+     subtest 'Checking the bn results' => sub {
+	 my @lines = ();
+	 if (open DATA, $testresults) {
+	     @lines = <DATA>;
+	     close DATA;
+	 }
+	 chomp(@lines);
+
+	 plan tests => scalar grep(/^print /, @lines);
+
+	 my $l = "";
+
+	 while (scalar @lines) {
+	     $l = shift @lines;
+
+	     last if $l =~ /^print /;
+	 }
+
+	 while (1) {
+	     $l =~ s/^print "//;
+	     $l =~ s/\\n"//;
+	     my $t = $l;
+	     my @operations = ();
+
+	     $l = undef;
+	     while (scalar @lines) {
+		 $l = shift @lines;
+
+		 last if $l =~ /^print /;
+		 push @operations, $l;
+		 $l = undef;
+	     }
+
+	     ok(check_operations(@operations), "verify $t");
+
+	     last unless $l;
+	 }
+     };
+}
+
+sub check_operations {
+    my $failcount = 0;
+
+    foreach my $line (@_) {
+	my $result = calc(split /\s+/, $line);
+
+	if ($result ne "0" && $result ne "0x0") {
+	    $failcount++;
+	    print STDERR "Failed! $line => $result\n";
+	}
+    }
+
+    return $failcount == 0;
+}
diff --git a/test/recipes/10-test_exp.t b/test/recipes/10-test_exp.t
new file mode 100644
index 0000000..b8083e7
--- /dev/null
+++ b/test/recipes/10-test_exp.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_exp", "exptest");
diff --git a/test/recipes/15-test_dh.t b/test/recipes/15-test_dh.t
new file mode 100644
index 0000000..35e9564
--- /dev/null
+++ b/test/recipes/15-test_dh.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_dh", "dhtest", "dh");
diff --git a/test/recipes/15-test_dsa.t b/test/recipes/15-test_dsa.t
new file mode 100644
index 0000000..e338b0b
--- /dev/null
+++ b/test/recipes/15-test_dsa.t
@@ -0,0 +1,32 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_dsa");
+
+plan tests => 6;
+
+require_ok(top_file('test','recipes','tconversion.pl'));
+
+ok(run(test(["dsatest"])), "running dsatest");
+ok(run(test(["dsatest", "-app2_1"])), "running dsatest -app2_1");
+
+ SKIP: {
+     skip "Skipping dsa conversion test", 3
+	 if run(app(["openssl","no-dsa"], stdout => undef));
+
+     subtest 'dsa conversions -- private key' => sub {
+	 tconversion("dsa", top_file("test","testdsa.pem"));
+     };
+     subtest 'dsa conversions -- private key PKCS#8' => sub {
+	 tconversion("dsa", top_file("test","testdsa.pem"), "pkey");
+     };
+     subtest 'dsa conversions -- public key' => sub {
+	 tconversion("dsa", top_file("test","testdsapub.pem"), "dsa",
+		     "-pubin", "-pubout");
+     };
+}
diff --git a/test/recipes/15-test_ec.t b/test/recipes/15-test_ec.t
new file mode 100644
index 0000000..bbda19a
--- /dev/null
+++ b/test/recipes/15-test_ec.t
@@ -0,0 +1,30 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_ec");
+
+plan tests => 5;
+
+require_ok(top_file('test','recipes','tconversion.pl'));
+
+ok(run(test(["ectest"])), "running ectest");
+
+ SKIP: {
+     skip "Skipping ec conversion test", 3
+	 if run(app(["openssl","no-ec"], stdout => undef));
+
+     subtest 'ec conversions -- private key' => sub {
+	 tconversion("ec", top_file("test","testec-p256.pem"));
+     };
+     subtest 'ec conversions -- private key PKCS#8' => sub {
+	 tconversion("ec", top_file("test","testec-p256.pem"), "pkey");
+     };
+     subtest 'ec conversions -- public key' => sub {
+	 tconversion("ec", top_file("test","testecpub-p256.pem"), "ec", "-pubin", "-pubout");
+     };
+}
diff --git a/test/recipes/15-test_ecdh.t b/test/recipes/15-test_ecdh.t
new file mode 100644
index 0000000..7cdfea6
--- /dev/null
+++ b/test/recipes/15-test_ecdh.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_ecdh", "ecdhtest", "ecdh");
diff --git a/test/recipes/15-test_ecdsa.t b/test/recipes/15-test_ecdsa.t
new file mode 100644
index 0000000..aa4622f
--- /dev/null
+++ b/test/recipes/15-test_ecdsa.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_ecdsa", "ecdsatest", "ecdsa");
diff --git a/test/recipes/15-test_rsa.t b/test/recipes/15-test_rsa.t
new file mode 100644
index 0000000..2eaeb0d
--- /dev/null
+++ b/test/recipes/15-test_rsa.t
@@ -0,0 +1,31 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_rsa");
+
+plan tests => 5;
+
+require_ok(top_file('test','recipes','tconversion.pl'));
+
+ok(run(test(["rsa_test"])), "running rsatest");
+
+ SKIP: {
+     skip "Skipping rsa conversion test", 3
+	 if run(app(["openssl","no-rsa"], stdout => undef));
+
+     subtest 'rsa conversions -- private key' => sub {
+	 tconversion("rsa", top_file("test","testrsa.pem"));
+     };
+     subtest 'rsa conversions -- private key PKCS#8' => sub {
+	 tconversion("rsa", top_file("test","testrsa.pem"), "pkey");
+     };
+     subtest 'rsa conversions -- public key' => sub {
+	 tconversion("rsa", top_file("test","testrsapub.pem"), "rsa",
+		     "-pubin", "-pubout");
+     };
+}
diff --git a/test/recipes/20-test_enc.t b/test/recipes/20-test_enc.t
new file mode 100644
index 0000000..bd5a436
--- /dev/null
+++ b/test/recipes/20-test_enc.t
@@ -0,0 +1,64 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec::Functions qw/catfile/;
+use File::Copy;
+use File::Compare qw/compare_text/;
+use File::Basename;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_enc");
+
+# We do it this way, because setup() may have moved us around,
+# so the directory portion of $0 might not be correct any more.
+# However, the name hasn't changed.
+my $testsrc = top_file("test","recipes",basename($0));
+
+my $test = catfile(".", "p");
+
+my $cmd = "openssl";
+
+my @ciphers =
+    map { chomp; s/^\s+//; s/\s+$//; split /\s+/ }
+    run(app([$cmd, "list", "-cipher-commands"]), capture => 1);
+
+plan tests => 1 + (scalar @ciphers)*2;
+
+my $init = ok(copy($testsrc,$test));
+
+if (!$init) {
+    diag("Trying to copy $testsrc to $test : $!");
+}
+
+ SKIP: {
+     skip "Not initialized, skipping...", 11 unless $init;
+
+     foreach my $c (@ciphers) {
+	 my %variant = ("$c" => [],
+			"$c base64" => [ "-a" ]);
+
+	 foreach my $t (sort keys %variant) {
+	     my $cipherfile = "$test.$c.cipher";
+	     my $clearfile = "$test.$c.clear";
+	     my @e = ( "$c", "-bufsize", "113", @{$variant{$t}}, "-e", "-k", "test" );
+	     my @d = ( "$c", "-bufsize", "157", @{$variant{$t}}, "-d", "-k", "test" );
+	     if ($c eq "cat") {
+		 $cipherfile = "$test.cipher";
+		 $clearfile = "$test.clear";
+		 @e = ( "enc", @{$variant{$t}}, "-e" );
+		 @d = ( "enc", @{$variant{$t}}, "-d" );
+	     }
+
+	     ok(run(app([$cmd, @e],
+			stdin => $test, stdout => $cipherfile))
+		&& run(app([$cmd, @d],
+			   stdin => $cipherfile, stdout => $clearfile))
+		&& compare_text($test,$clearfile) == 0, $t);
+	     unlink $cipherfile, $clearfile;
+	 }
+     }
+}
+
+unlink $test;
diff --git a/test/recipes/25-test_crl.t b/test/recipes/25-test_crl.t
new file mode 100644
index 0000000..6779a0b
--- /dev/null
+++ b/test/recipes/25-test_crl.t
@@ -0,0 +1,17 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_crl");
+
+plan tests => 2;
+
+require_ok(top_file('test','recipes','tconversion.pl'));
+
+subtest 'crl conversions' => sub {
+    tconversion("crl", top_file("test","testcrl.pem"));
+};
diff --git a/test/recipes/25-test_gen.t b/test/recipes/25-test_gen.t
new file mode 100644
index 0000000..9427bde
--- /dev/null
+++ b/test/recipes/25-test_gen.t
@@ -0,0 +1,43 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_gen");
+
+plan tests => 1;
+
+my $T = "testcert";
+my $KEY = 512;
+my $CA = top_file("certs", "testca.pem");
+
+unlink "$T.1", "$T.2", "$T.key";
+open RND, ">>", ".rnd";
+print RND "string to make the random number generator think it has entropy";
+close RND;
+
+subtest "generating certificate requests" => sub {
+    my @req_new;
+    if (run(app(["openssl", "no-rsa"], stdout => undef))) {
+	@req_new = ("-newkey", "dsa:".top_file("apps", "dsa512.pem"));
+    } else {
+	@req_new = ("-new");
+	note("There should be a 2 sequences of .'s and some +'s.");
+	note("There should not be more that at most 80 per line");
+    }
+
+    unlink "testkey.pem", "testreq.pem";
+
+    plan tests => 2;
+
+    ok(run(app(["openssl", "req", "-config", top_file("test", "test.cnf"),
+		@req_new, "-out", "testreq.pem"])),
+       "Generating request");
+
+    ok(run(app(["openssl", "req", "-config", top_file("test", "test.cnf"),
+		"-verify", "-in", "testreq.pem", "-noout"])),
+       "Verifying signature on request");
+};
diff --git a/test/recipes/25-test_pkcs7.t b/test/recipes/25-test_pkcs7.t
new file mode 100644
index 0000000..3a4dbb4
--- /dev/null
+++ b/test/recipes/25-test_pkcs7.t
@@ -0,0 +1,20 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_pkcs7");
+
+plan tests => 3;
+
+require_ok(top_file('test','recipes','tconversion.pl'));
+
+subtest 'pkcs7 conversions -- pkcs7' => sub {
+    tconversion("p7", top_file("test", "testp7.pem"), "pkcs7");
+};
+subtest 'pkcs7 conversions -- pkcs7d' => sub {
+    tconversion("p7d", top_file("test", "pkcs7-1.pem"), "pkcs7");
+};
diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t
new file mode 100644
index 0000000..4f9de77
--- /dev/null
+++ b/test/recipes/25-test_req.t
@@ -0,0 +1,43 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_req");
+
+plan tests => 3;
+
+require_ok(top_file('test','recipes','tconversion.pl'));
+
+my @openssl_args = ("req", "-config", "../apps/openssl.cnf");
+
+run_conversion('req conversions',
+	       "testreq.pem");
+run_conversion('req conversions -- testreq2',
+	       "testreq2.pem");
+
+sub run_conversion {
+    my $title = shift;
+    my $reqfile = shift;
+
+    subtest $title => sub {
+	run(app(["openssl", @openssl_args,
+		 "-in", $reqfile, "-inform", "p",
+		 "-noout", "-text"],
+		stderr => "req-check.err", stdout => undef));
+	open DATA, "req-check.err";
+      SKIP: {
+	  plan skip_all => "skipping req conversion test for $reqfile"
+	      if grep /Unknown Public Key/, map { chomp } <DATA>;
+
+	  tconversion("req", "testreq.pem", @openssl_args);
+	}
+	close DATA;
+	unlink "req-check.err";
+
+	done_testing();
+    };
+}
diff --git a/test/recipes/25-test_sid.t b/test/recipes/25-test_sid.t
new file mode 100644
index 0000000..b223c0d
--- /dev/null
+++ b/test/recipes/25-test_sid.t
@@ -0,0 +1,17 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_sid");
+
+plan tests => 2;
+
+require_ok(top_file('test','recipes','tconversion.pl'));
+
+subtest 'sid conversions' => sub {
+    tconversion("sid", top_file("test","testsid.pem"), "sess_id");
+};
diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t
new file mode 100644
index 0000000..10897a1
--- /dev/null
+++ b/test/recipes/25-test_verify.t
@@ -0,0 +1,15 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec::Functions qw/canonpath/;
+use OpenSSL::Test qw/:DEFAULT top_dir top_file/;
+
+setup("test_verify");
+
+plan tests => 1;
+
+note("Expect some failures and expired certificate");
+ok(run(app(["openssl", "verify", "-CApath", top_dir("certs", "demo"),
+	    glob(top_file("certs", "demo", "*.pem"))])), "verying demo certs");
diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t
new file mode 100644
index 0000000..e2d795a
--- /dev/null
+++ b/test/recipes/25-test_x509.t
@@ -0,0 +1,23 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec;
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_x509");
+
+plan tests => 4;
+
+require_ok(top_file('test','recipes','tconversion.pl'));
+
+subtest 'x509 -- x.509 v1 certificate' => sub {
+    tconversion("x509", top_file("test","testx509.pem"));
+};
+subtest 'x509 -- first x.509 v3 certificate' => sub {
+    tconversion("x509", top_file("test","v3-cert1.pem"));
+};
+subtest 'x509 -- second x.509 v3 certificate' => sub {
+    tconversion("x509", top_file("test","v3-cert2.pem"));
+};
diff --git a/test/recipes/30-test_engine.t b/test/recipes/30-test_engine.t
new file mode 100644
index 0000000..c097b6f
--- /dev/null
+++ b/test/recipes/30-test_engine.t
@@ -0,0 +1,11 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use OpenSSL::Test;
+
+setup("test_engine");
+
+plan tests => 1;
+ok(run(test(["enginetest"])), "running enginetest");
diff --git a/test/recipes/30-test_evp.t b/test/recipes/30-test_evp.t
new file mode 100644
index 0000000..9d5ce6f
--- /dev/null
+++ b/test/recipes/30-test_evp.t
@@ -0,0 +1,12 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+setup("test_evp");
+
+plan tests => 1;
+ok(run(test(["evp_test", top_file("test", "evptests.txt")])),
+   "running evp_test evptests.txt");
diff --git a/test/recipes/30-test_evp_extra.t b/test/recipes/30-test_evp_extra.t
new file mode 100644
index 0000000..0f90b21
--- /dev/null
+++ b/test/recipes/30-test_evp_extra.t
@@ -0,0 +1,11 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use OpenSSL::Test;
+
+setup("test_evp_extra");
+
+plan tests => 1;
+ok(run(test(["evp_extra_test"])), "running evp_extra_test");
diff --git a/test/recipes/30-test_pbelu.t b/test/recipes/30-test_pbelu.t
new file mode 100644
index 0000000..635fb69
--- /dev/null
+++ b/test/recipes/30-test_pbelu.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_pbelu", "pbelutest");
diff --git a/test/recipes/70-test_clienthello.t b/test/recipes/70-test_clienthello.t
new file mode 100644
index 0000000..73b83f2
--- /dev/null
+++ b/test/recipes/70-test_clienthello.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_clienthello", "clienthellotest");
diff --git a/test/recipes/70-test_packet.t b/test/recipes/70-test_packet.t
new file mode 100644
index 0000000..b1609d5
--- /dev/null
+++ b/test/recipes/70-test_packet.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_packet", "packettest");
diff --git a/test/sslextensiontest.pl b/test/recipes/70-test_sslextension.t
similarity index 85%
rename from test/sslextensiontest.pl
rename to test/recipes/70-test_sslextension.t
index 802bac1..4aa3f61 100755
--- a/test/sslextensiontest.pl
+++ b/test/recipes/70-test_sslextension.t
@@ -53,18 +53,30 @@
 # Hudson (tjh at cryptsoft.com).
 
 use strict;
+use OpenSSL::Test qw/:DEFAULT cmdstr top_file top_dir/;
 use TLSProxy::Proxy;
 
+my $test_name = "test_sslextension";
+setup($test_name);
+
+plan skip_all => "$test_name can only be performed with OpenSSL configured shared"
+    unless (map { chomp; s/^SHARED_LIBS=\s*//; $_ }
+	    grep { /^SHARED_LIBS=/ }
+	    do { local @ARGV = ( top_file("Makefile") ); <> })[0] ne "";
+
+$ENV{OPENSSL_ENGINES} = top_dir("engines");
+$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
 my $proxy = TLSProxy::Proxy->new(
     \&extension_filter,
-    @ARGV
+    cmdstr(app(["openssl"])),
+    top_file("apps", "server.pem")
 );
 
+plan tests => 1;
+
 #Test 1: Sending a zero length extension block should pass
 $proxy->start();
-TLSProxy::Message->success or die "FAILED: Zero extension length test\n";
-
-print "SUCCESS: Extension test\n";
+ok(TLSProxy::Message->success, "Zero extension length test");
 
 sub extension_filter
 {
diff --git a/test/sslsessionticktest.pl b/test/recipes/70-test_sslsessiontick.t
similarity index 75%
rename from test/sslsessionticktest.pl
rename to test/recipes/70-test_sslsessiontick.t
index 922a359..7f90bea 100755
--- a/test/sslsessionticktest.pl
+++ b/test/recipes/70-test_sslsessiontick.t
@@ -53,9 +53,24 @@
 # Hudson (tjh at cryptsoft.com).
 
 use strict;
+use OpenSSL::Test qw/:DEFAULT cmdstr top_file top_dir/;
 use TLSProxy::Proxy;
 use File::Temp qw(tempfile);
 
+my $test_name = "test_sslsessiontick";
+setup($test_name);
+
+plan skip_all => "$test_name can only be performed with OpenSSL configured shared"
+    unless (map { chomp; s/^SHARED_LIBS=\s*//; $_ }
+	    grep { /^SHARED_LIBS=/ }
+	    do { local @ARGV = ( top_file("Makefile") ); <> })[0] ne "";
+
+$ENV{OPENSSL_ENGINES} = top_dir("engines");
+$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
+
+sub checkmessages($$$$$$);
+sub clearall();
+
 my $chellotickext = 0;
 my $shellotickext = 0;
 my $fullhand = 0;
@@ -63,9 +78,12 @@ my $ticketseen = 0;
 
 my $proxy = TLSProxy::Proxy->new(
     undef,
-    @ARGV
+    cmdstr(app(["openssl"])),
+    top_file("apps", "server.pem")
 );
 
+plan tests => 5;
+
 #Test 1: By default with no existing session we should get a session ticket
 #Expected result: ClientHello extension seen; ServerHello extension seen
 #                 NewSessionTicket message seen; Full handshake
@@ -107,7 +125,7 @@ checkmessages(4, "Session resumption session ticket test", 1, 0, 0, 0);
 #Expected result: ClientHello extension seen; ServerHello extension seen
 #                 NewSessionTicket message seen; Abbreviated handshake
 clearall();
-(my $fh, my $session) = tempfile();
+($fh, $session) = tempfile();
 $proxy->serverconnects(2);
 $proxy->clientflags("-sess_out ".$session." -no_ticket");
 $proxy->start();
@@ -117,50 +135,45 @@ $proxy->clientstart();
 checkmessages(5, "Session resumption with ticket capable client without a "
                  ."ticket", 1, 1, 1, 0);
 
-sub checkmessages()
+sub checkmessages($$$$$$)
 {
     my ($testno, $testname, $testch, $testsh, $testtickseen, $testhand) = @_;
 
-    foreach my $message (@{$proxy->message_list}) {
-        if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO
+    subtest $testname => sub {
+
+	foreach my $message (@{$proxy->message_list}) {
+	    if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO
                 || $message->mt == TLSProxy::Message::MT_SERVER_HELLO) {
-            #Get the extensions data
-            my %extensions = %{$message->extension_data};
-            if (defined
+		#Get the extensions data
+		my %extensions = %{$message->extension_data};
+		if (defined
                     $extensions{TLSProxy::ClientHello::EXT_SESSION_TICKET}) {
-                if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
-                    $chellotickext = 1;
-                } else {
-                    $shellotickext = 1;
-                }
-            }
-        } elsif ($message->mt == TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE) {
-            #Must be doing a full handshake
-            $fullhand = 1;
-        } elsif ($message->mt == TLSProxy::Message::MT_NEW_SESSION_TICKET) {
-            $ticketseen = 1;
-        }
-    }
+		    if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
+			$chellotickext = 1;
+		    } else {
+			$shellotickext = 1;
+		    }
+		}
+	    } elsif ($message->mt == TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE) {
+		#Must be doing a full handshake
+		$fullhand = 1;
+	    } elsif ($message->mt == TLSProxy::Message::MT_NEW_SESSION_TICKET) {
+		$ticketseen = 1;
+	    }
+	}
 
-    TLSProxy::Message->success or die "FAILED: $testname: Hanshake failed "
-                                      ."(Test $testno)\n";
-    if (($testch && !$chellotickext) || (!$testch && $chellotickext)) {
-        die "FAILED: $testname: ClientHello extension Session Ticket check "
-            ."failed (Test $testno)\n";
-    }
-    if (($testsh && !$shellotickext) || (!$testsh && $shellotickext)) {
-        die "FAILED: $testname: ServerHello extension Session Ticket check "
-            ."failed (Test $testno)\n";
-    }
-    if (($testtickseen && !$ticketseen) || (!$testtickseen && $ticketseen)) {
-        die "FAILED: $testname: Session Ticket message presence check failed "
-            ."(Test $testno)\n";
-    }
-    if (($testhand && !$fullhand) || (!$testhand && $fullhand)) {
-        die "FAILED: $testname: Session Ticket full handshake check failed "
-            ."(Test $testno)\n";
+	plan tests => 5;
+
+	ok(TLSProxy::Message->success, "Hanshake");
+	ok(($testch && $chellotickext) || (!$testch && !$chellotickext),
+	   "ClientHello extension Session Ticket check");
+	ok(($testsh && $shellotickext) || (!$testsh && !$shellotickext),
+	   "ServerHello extension Session Ticket check");
+	ok(($testtickseen && $ticketseen) || (!$testtickseen && !$ticketseen),
+	   "Session Ticket message presence check");
+	ok(($testhand && $fullhand) || (!$testhand && !$fullhand),
+	   "Session Ticket full handshake check");
     }
-    print "SUCCESS: $testname (Test#$testno)\n";
 }
 
 sub clearall()
diff --git a/test/sslskewith0ptest.pl b/test/recipes/70-test_sslskewith0p.t
similarity index 85%
rename from test/sslskewith0ptest.pl
rename to test/recipes/70-test_sslskewith0p.t
index 63f8398..d8d74b3 100755
--- a/test/sslskewith0ptest.pl
+++ b/test/recipes/70-test_sslskewith0p.t
@@ -53,21 +53,33 @@
 # Hudson (tjh at cryptsoft.com).
 
 use strict;
+use OpenSSL::Test qw/:DEFAULT cmdstr top_file top_dir/;
 use TLSProxy::Proxy;
 
+my $test_name = "test_sslskewith0p";
+setup($test_name);
+
+plan skip_all => "$test_name can only be performed with OpenSSL configured shared"
+    unless (map { chomp; s/^SHARED_LIBS=\s*//; $_ }
+	    grep { /^SHARED_LIBS=/ }
+	    do { local @ARGV = ( top_file("Makefile") ); <> })[0] ne "";
+
+$ENV{OPENSSL_ENGINES} = top_dir("engines");
+$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
 my $proxy = TLSProxy::Proxy->new(
     \&ske_0_p_filter,
-    @ARGV
+    cmdstr(app(["openssl"])),
+    top_file("apps", "server.pem")
 );
 
+plan tests => 1;
+
 #We must use an anon DHE cipher for this test
 $proxy->cipherc('ADH-AES128-SHA:@SECLEVEL=0');
 $proxy->ciphers('ADH-AES128-SHA:@SECLEVEL=0');
 
 $proxy->start();
-TLSProxy::Message->fail or die "FAILED: ServerKeyExchange with 0 p\n";
-
-print "SUCCESS: ServerKeyExchange with 0 p\n";
+ok(TLSProxy::Message->fail, "ServerKeyExchange with 0 p");
 
 sub ske_0_p_filter
 {
diff --git a/test/sslvertoltest.pl b/test/recipes/70-test_sslvertol.t
similarity index 84%
rename from test/sslvertoltest.pl
rename to test/recipes/70-test_sslvertol.t
index 1828a7d..9717f80 100755
--- a/test/sslvertoltest.pl
+++ b/test/recipes/70-test_sslvertol.t
@@ -53,24 +53,36 @@
 # Hudson (tjh at cryptsoft.com).
 
 use strict;
+use OpenSSL::Test qw/:DEFAULT cmdstr top_file top_dir/;
 use TLSProxy::Proxy;
 
+my $test_name = "test_sslextension";
+setup($test_name);
+
+plan skip_all => "$test_name can only be performed with OpenSSL configured shared"
+    unless (map { chomp; s/^SHARED_LIBS=\s*//; $_ }
+	    grep { /^SHARED_LIBS=/ }
+	    do { local @ARGV = ( top_file("Makefile") ); <> })[0] ne "";
+
+$ENV{OPENSSL_ENGINES} = top_dir("engines");
+$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
 my $proxy = TLSProxy::Proxy->new(
     \&vers_tolerance_filter,
-    @ARGV
+    cmdstr(app(["openssl"])),
+    top_file("apps", "server.pem")
 );
 
+plan tests => 2;
+
 #Test 1: Asking for TLS1.3 should pass
 my $client_version = TLSProxy::Record::VERS_TLS_1_3;
 $proxy->start();
-TLSProxy::Message->success or die "FAILED: Version tolerance test\n";
+ok(TLSProxy::Message->success(), "Version tolerance test, TLS 1.3");
 
 #Test 2: Testing something below SSLv3 should fail
 $client_version = TLSProxy::Record::VERS_SSL_3_0 - 1;
 $proxy->restart();
-TLSProxy::Message->success and die "FAILED: Version tolerance test\n";
-
-print "SUCCESS: Version tolerance test\n";
+ok(TLSProxy::Message->fail(), "Version tolerance test, SSL < 3.0");
 
 sub vers_tolerance_filter
 {
diff --git a/test/recipes/70-test_verify_extra.t b/test/recipes/70-test_verify_extra.t
new file mode 100644
index 0000000..3ef4a27
--- /dev/null
+++ b/test/recipes/70-test_verify_extra.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_verify_extra", "verify_extra_test");
diff --git a/test/recipes/80-test_ca.t b/test/recipes/80-test_ca.t
new file mode 100644
index 0000000..f57fb3c
--- /dev/null
+++ b/test/recipes/80-test_ca.t
@@ -0,0 +1,54 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use POSIX;
+use File::Spec::Functions qw/splitdir curdir catfile devnull/;
+use File::Path 2.00 qw/remove_tree/;
+use OpenSSL::Test qw/:DEFAULT cmdstr top_file quotify/;
+
+setup("test_ca");
+
+my $perl = $^X;
+$ENV{OPENSSL} = cmdstr(app(["openssl"]));
+my $CA_pl = top_file("apps", "CA.pl");
+my $std_openssl_cnf = top_file("apps", "openssl.cnf");
+
+($perl) = quotify($perl) unless $^O eq "VMS"; # never quotify a command on VMS. Ever!
+
+remove_tree("demoCA", { safe => 0 });
+
+plan tests => 4;
+ SKIP: {
+     $ENV{SSLEAY_CONFIG} = "-config ".top_file("test", "CAss.cnf");
+     skip "failed creating CA structure", 3
+	 if !is(system("$perl ".$CA_pl." -newca < ".devnull()." 2>&1"), 0,
+		'creating CA structure');
+
+     $ENV{SSLEAY_CONFIG} = "-config ".top_file("test", "Uss.cnf");
+     skip "failed creating new certificate request", 2
+	 if !is(system("$perl ".$CA_pl." -newreq 2>&1"), 0,
+		'creating new certificate request');
+
+     $ENV{SSLEAY_CONFIG} = "-config ".$std_openssl_cnf;
+     skip "failed to sign certificate request", 1
+	 if !is(yes("$perl ".$CA_pl." -sign 2>&1"), 0,
+		'signing certificate request');
+
+     is(system("$perl ".$CA_pl." -verify newcert.pem 2>&1"), 0,
+	'verifying new certificate');
+}
+
+
+remove_tree("demoCA", { safe => 0 });
+unlink "newcert.pem", "newreq.pem";
+
+
+sub yes {
+    open(PIPE, "|-", join(" ", at _));
+    local $SIG{PIPE} = "IGNORE";
+    1 while print PIPE "y\n";
+    close PIPE;
+    return 0;
+}
diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t
new file mode 100644
index 0000000..cc2786f
--- /dev/null
+++ b/test/recipes/80-test_cms.t
@@ -0,0 +1,476 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use POSIX;
+use File::Spec::Functions qw/catfile/;
+use File::Compare qw/compare_text/;
+use OpenSSL::Test qw/:DEFAULT top_dir top_file/;
+
+setup("test_cms");
+
+my $smdir    = top_dir("test", "smime-certs");
+my $smcont   = top_file("test", "smcont.txt");
+my $no_ec    = run(app(["openssl", "no-ec"], stdout => undef));
+my $no_ec2m  = run(app(["openssl", "no-ec2m"], stdout => undef));
+my $no_ecdh  = run(app(["openssl", "no-ecdh"], stdout => undef));
+
+plan tests => 4;
+
+my @smime_pkcs7_tests = (
+
+    [ "signed content DER format, RSA key",
+      [ "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+	"-certfile", catfile($smdir, "smroot.pem"),
+	"-signer", catfile($smdir, "smrsa1.pem"), "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed detached content DER format, RSA key",
+      [ "-sign", "-in", $smcont, "-outform", "DER",
+	"-signer", catfile($smdir, "smrsa1.pem"), "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt",
+	"-content", $smcont ]
+    ],
+
+    [ "signed content test streaming BER format, RSA",
+      [ "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+	"-stream",
+	"-signer", catfile($smdir, "smrsa1.pem"), "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content DER format, DSA key",
+      [ "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+	"-signer", catfile($smdir, "smdsa1.pem"), "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed detached content DER format, DSA key",
+      [ "-sign", "-in", $smcont, "-outform", "DER",
+	"-signer", catfile($smdir, "smdsa1.pem"), "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt",
+	"-content", $smcont ]
+    ],
+
+    [ "signed detached content DER format, add RSA signer",
+      [ "-resign", "-inform", "DER", "-in", "test.cms", "-outform", "DER",
+	"-signer", catfile($smdir, "smrsa1.pem"), "-out", "test2.cms" ],
+      [ "-verify", "-in", "test2.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt",
+	"-content", $smcont ]
+    ],
+
+    [ "signed content test streaming BER format, DSA key",
+      [ "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+	"-stream",
+	"-signer", catfile($smdir, "smdsa1.pem"), "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys",
+      [ "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+	"-signer", catfile($smdir, "smrsa1.pem"),
+	"-signer", catfile($smdir, "smrsa2.pem"),
+	"-signer", catfile($smdir, "smdsa1.pem"),
+	"-signer", catfile($smdir, "smdsa2.pem"),
+	"-stream", "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, no attributes",
+      [ "-sign", "-in", $smcont, "-outform", "DER", "-noattr", "-nodetach",
+	"-signer", catfile($smdir, "smrsa1.pem"),
+	"-signer", catfile($smdir, "smrsa2.pem"),
+	"-signer", catfile($smdir, "smdsa1.pem"),
+	"-signer", catfile($smdir, "smdsa2.pem"),
+	"-stream", "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content test streaming S/MIME format, 2 DSA and 2 RSA keys",
+      [ "-sign", "-in", $smcont, "-nodetach",
+	"-signer", catfile($smdir, "smrsa1.pem"),
+	"-signer", catfile($smdir, "smrsa2.pem"),
+	"-signer", catfile($smdir, "smdsa1.pem"),
+	"-signer", catfile($smdir, "smdsa2.pem"),
+	"-stream", "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content test streaming multipart S/MIME format, 2 DSA and 2 RSA keys",
+      [ "-sign", "-in", $smcont,
+	"-signer", catfile($smdir, "smrsa1.pem"),
+	"-signer", catfile($smdir, "smrsa2.pem"),
+	"-signer", catfile($smdir, "smdsa1.pem"),
+	"-signer", catfile($smdir, "smdsa2.pem"),
+	"-stream", "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, 3 recipients",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	catfile($smdir, "smrsa1.pem"),
+	catfile($smdir, "smrsa2.pem"),
+	catfile($smdir, "smrsa3.pem") ],
+      [ "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, 3 recipients, 3rd used",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	catfile($smdir, "smrsa1.pem"),
+	catfile($smdir, "smrsa2.pem"),
+	catfile($smdir, "smrsa3.pem") ],
+      [ "-decrypt", "-recip", catfile($smdir, "smrsa3.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, 3 recipients, key only used",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	catfile($smdir, "smrsa1.pem"),
+	catfile($smdir, "smrsa2.pem"),
+	catfile($smdir, "smrsa3.pem") ],
+      [ "-decrypt", "-inkey", catfile($smdir, "smrsa3.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, AES-256 cipher, 3 recipients",
+      [ "-encrypt", "-in", $smcont,
+	"-aes256", "-stream", "-out", "test.cms",
+	catfile($smdir, "smrsa1.pem"),
+	catfile($smdir, "smrsa2.pem"),
+	catfile($smdir, "smrsa3.pem") ],
+      [ "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+);
+
+my @smime_cms_tests = (
+
+    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, keyid",
+      [ "-sign", "-in", $smcont, "-outform", "DER", "-nodetach", "-keyid",
+	"-signer", catfile($smdir, "smrsa1.pem"),
+	"-signer", catfile($smdir, "smrsa2.pem"),
+	"-signer", catfile($smdir, "smdsa1.pem"),
+	"-signer", catfile($smdir, "smdsa2.pem"),
+	"-stream", "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "DER",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content test streaming PEM format, 2 DSA and 2 RSA keys",
+      [ "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+	"-signer", catfile($smdir, "smrsa1.pem"),
+	"-signer", catfile($smdir, "smrsa2.pem"),
+	"-signer", catfile($smdir, "smdsa1.pem"),
+	"-signer", catfile($smdir, "smdsa2.pem"),
+	"-stream", "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "PEM",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content MIME format, RSA key, signed receipt request",
+      [ "-sign", "-in", $smcont, "-signer", catfile($smdir, "smrsa1.pem"), "-nodetach",
+	"-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
+	"-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed receipt MIME format, RSA key",
+      [ "-sign_receipt", "-in", "test.cms",
+	"-signer", catfile($smdir, "smrsa2.pem"),
+	"-out", "test2.cms" ],
+      [ "-verify_receipt", "test2.cms", "-in", "test.cms",
+	"-CAfile", catfile($smdir, "smroot.pem") ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, 3 recipients, keyid",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms", "-keyid",
+	catfile($smdir, "smrsa1.pem"),
+	catfile($smdir, "smrsa2.pem"),
+	catfile($smdir, "smrsa3.pem") ],
+      [ "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming PEM format, KEK",
+      [ "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
+	"-stream", "-out", "test.cms",
+	"-secretkey", "000102030405060708090A0B0C0D0E0F",
+	"-secretkeyid", "C0FEE0" ],
+      [ "-decrypt", "-in", "test.cms", "-out", "smtst.txt", "-inform", "PEM",
+	"-secretkey", "000102030405060708090A0B0C0D0E0F",
+	"-secretkeyid", "C0FEE0" ]
+    ],
+
+    [ "enveloped content test streaming PEM format, KEK, key only",
+      [ "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
+	"-stream", "-out", "test.cms",
+	"-secretkey", "000102030405060708090A0B0C0D0E0F",
+	"-secretkeyid", "C0FEE0" ],
+      [ "-decrypt", "-in", "test.cms", "-out", "smtst.txt", "-inform", "PEM",
+	"-secretkey", "000102030405060708090A0B0C0D0E0F" ]
+    ],
+
+    [ "data content test streaming PEM format",
+      [ "-data_create", "-in", $smcont, "-outform", "PEM", "-nodetach",
+	"-stream", "-out", "test.cms" ],
+      [ "-data_out", "-in", "test.cms", "-inform", "PEM", "-out", "smtst.txt" ]
+    ],
+
+    [ "encrypted content test streaming PEM format, 128 bit RC2 key",
+      [ "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
+	"-rc2", "-secretkey", "000102030405060708090A0B0C0D0E0F",
+	"-stream", "-out", "test.cms" ],
+      [ "-EncryptedData_decrypt", "-in", "test.cms", "-inform", "PEM",
+	"-secretkey", "000102030405060708090A0B0C0D0E0F", "-out", "smtst.txt" ]
+    ],
+
+    [ "encrypted content test streaming PEM format, 40 bit RC2 key",
+      [ "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
+	"-rc2", "-secretkey", "0001020304",
+	"-stream", "-out", "test.cms" ],
+      [ "-EncryptedData_decrypt", "-in", "test.cms", "-inform", "PEM",
+	"-secretkey", "0001020304", "-out", "smtst.txt" ]
+    ],
+
+    [ "encrypted content test streaming PEM format, triple DES key",
+      [ "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
+	"-des3", "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
+	"-stream", "-out", "test.cms" ],
+      [ "-EncryptedData_decrypt", "-in", "test.cms", "-inform", "PEM",
+	"-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
+	"-out", "smtst.txt" ]
+    ],
+
+    [ "encrypted content test streaming PEM format, 128 bit AES key",
+      [ "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
+	"-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
+	"-stream", "-out", "test.cms" ],
+      [ "-EncryptedData_decrypt", "-in", "test.cms", "-inform", "PEM",
+	"-secretkey", "000102030405060708090A0B0C0D0E0F", "-out", "smtst.txt" ]
+    ],
+
+);
+
+my @smime_cms_comp_tests = (
+
+    [ "compressed content test streaming PEM format",
+      [ "-compress", "-in", $smcont, "-outform", "PEM", "-nodetach",
+	"-stream", "-out", "test.cms" ],
+      [ "-uncompress", "-in", "test.cms", "-inform", "PEM", "-out", "smtst.txt" ]
+    ]
+
+);
+
+my @smime_cms_param_tests = (
+    [ "signed content test streaming PEM format, RSA keys, PSS signature",
+      [ "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+	"-signer", catfile($smdir, "smrsa1.pem"), "-keyopt", "rsa_padding_mode:pss",
+	"-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "PEM",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content test streaming PEM format, RSA keys, PSS signature, no attributes",
+      [ "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach", "-noattr",
+	"-signer", catfile($smdir, "smrsa1.pem"), "-keyopt", "rsa_padding_mode:pss",
+	"-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "PEM",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "signed content test streaming PEM format, RSA keys, PSS signature, SHA384 MGF1",
+      [ "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+	"-signer", catfile($smdir, "smrsa1.pem"), "-keyopt", "rsa_padding_mode:pss",
+	"-keyopt", "rsa_mgf1_md:sha384", "-out", "test.cms" ],
+      [ "-verify", "-in", "test.cms", "-inform", "PEM",
+	"-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, OAEP default parameters",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	"-recip", catfile($smdir, "smrsa1.pem"), "-keyopt", "rsa_padding_mode:oaep" ],
+      [ "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, OAEP SHA256",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	"-recip", catfile($smdir, "smrsa1.pem"), "-keyopt", "rsa_padding_mode:oaep",
+	"-keyopt", "rsa_oaep_md:sha256" ],
+      [ "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, ECDH",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	"-recip", catfile($smdir, "smec1.pem") ],
+      [ "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, ECDH, key identifier",
+      [ "-encrypt", "-keyid", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	"-recip", catfile($smdir, "smec1.pem") ],
+      [ "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, ECDH, AES128, SHA256 KDF",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	"-recip", catfile($smdir, "smec1.pem"), "-aes128", "-keyopt", "ecdh_kdf_md:sha256" ],
+      [ "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, ECDH, K-283, cofactor DH",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	"-recip", catfile($smdir, "smec2.pem"), "-aes128",
+	"-keyopt", "ecdh_kdf_md:sha256", "-keyopt", "ecdh_cofactor_mode:1" ],
+      [ "-decrypt", "-recip", catfile($smdir, "smec2.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ],
+
+    [ "enveloped content test streaming S/MIME format, X9.42 DH",
+      [ "-encrypt", "-in", $smcont,
+	"-stream", "-out", "test.cms",
+	"-recip", catfile($smdir, "smdh.pem"), "-aes128" ],
+      [ "-decrypt", "-recip", catfile($smdir, "smdh.pem"),
+	"-in", "test.cms", "-out", "smtst.txt" ]
+    ]
+    );
+
+subtest "CMS => PKCS#7 compatibility tests\n" => sub {
+    plan tests => scalar @smime_pkcs7_tests;
+
+    foreach (@smime_pkcs7_tests) {
+      SKIP: {
+	  my $skip_reason = check_availability($$_[0]);
+	  skip $skip_reason, 1 if $skip_reason;
+
+	  ok(run(app(["openssl", "cms", @{$$_[1]}]))
+	     && run(app(["openssl", "smime", @{$$_[2]}]))
+	     && compare_text($smcont, "smtst.txt") == 0,
+	     $$_[0]);
+	}
+    }
+};
+subtest "CMS <= PKCS#7 compatibility tests\n" => sub {
+    plan tests => scalar @smime_pkcs7_tests;
+
+    foreach (@smime_pkcs7_tests) {
+      SKIP: {
+	  my $skip_reason = check_availability($$_[0]);
+	  skip $skip_reason, 1 if $skip_reason;
+
+	  ok(run(app(["openssl", "smime", @{$$_[1]}]))
+	     && run(app(["openssl", "cms", @{$$_[2]}]))
+	     && compare_text($smcont, "smtst.txt") == 0,
+	     $$_[0]);
+	}
+    }
+};
+
+subtest "CMS <=> CMS consistency tests\n" => sub {
+    plan tests => (scalar @smime_pkcs7_tests) + (scalar @smime_cms_tests);
+
+    foreach (@smime_pkcs7_tests) {
+      SKIP: {
+	  my $skip_reason = check_availability($$_[0]);
+	  skip $skip_reason, 1 if $skip_reason;
+
+	  ok(run(app(["openssl", "cms", @{$$_[1]}]))
+	     && run(app(["openssl", "cms", @{$$_[2]}]))
+	     && compare_text($smcont, "smtst.txt") == 0,
+	     $$_[0]);
+	}
+    }
+    foreach (@smime_cms_tests) {
+      SKIP: {
+	  my $skip_reason = check_availability($$_[0]);
+	  skip $skip_reason, 1 if $skip_reason;
+
+	  ok(run(app(["openssl", "cms", @{$$_[1]}]))
+	     && run(app(["openssl", "cms", @{$$_[2]}]))
+	     && compare_text($smcont, "smtst.txt") == 0,
+	     $$_[0]);
+	}
+    }
+};
+
+subtest "CMS <=> CMS consistency tests, modified key parameters\n" => sub {
+    plan tests =>
+	(scalar @smime_cms_param_tests) + (scalar @smime_cms_comp_tests);
+
+    foreach (@smime_cms_param_tests) {
+      SKIP: {
+	  my $skip_reason = check_availability($$_[0]);
+	  skip $skip_reason, 1 if $skip_reason;
+
+	  ok(run(app(["openssl", "cms", @{$$_[1]}]))
+	     && run(app(["openssl", "cms", @{$$_[2]}]))
+	     && compare_text($smcont, "smtst.txt") == 0,
+	     $$_[0]);
+	}
+    }
+
+  SKIP: {
+      skip("Zlib not supported: compression tests skipped",
+	   scalar @smime_cms_comp_tests)
+	  unless grep /ZLIB/, run(app(["openssl", "version", "-f"]),
+				  capture => 1);
+
+      foreach (@smime_cms_param_tests) {
+	SKIP: {
+	    my $skip_reason = check_availability($$_[0]);
+	    skip $skip_reason, 1 if $skip_reason;
+
+	    ok(run(app(["openssl", "cms", @{$$_[1]}]))
+	       && run(app(["openssl", "cms", @{$$_[2]}]))
+	       && compare_text($smcont, "smtst.txt") == 0,
+	       $$_[0]);
+	  }
+      }
+    }
+};
+
+unlink "test.cms";
+unlink "test2.cms";
+unlink "smtst.txt";
+
+sub check_availability {
+    my $tnam = shift;
+
+    return "$tnam: skipped, EC disabled\n"
+	if ($no_ec && $tnam =~ /ECDH/);
+    return "$tnam: skipped, ECDH disabled\n"
+	if ($no_ecdh && $tnam =~ /ECDH/);
+    return "$tnam: skipped, EC2M disabled\n"
+	if ($no_ec2m && $tnam =~ /K-283/);
+    return "";
+}
diff --git a/test/recipes/80-test_ocsp.t b/test/recipes/80-test_ocsp.t
new file mode 100644
index 0000000..7d7c96e
--- /dev/null
+++ b/test/recipes/80-test_ocsp.t
@@ -0,0 +1,193 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use POSIX;
+use File::Spec::Functions qw/devnull catfile/;
+use File::Copy;
+use OpenSSL::Test qw/:DEFAULT with pipe top_dir/;
+
+setup("test_ocsp");
+
+my $ocspdir=top_dir("test", "ocsp-tests");
+# 17 December 2012 so we don't get certificate expiry errors.
+my @check_time=("-attime", "1355875200");
+
+sub test_ocsp {
+    my $title = shift;
+    my $inputfile = shift;
+    my $CAfile = shift;
+    my $expected_exit = shift;
+
+    with({ exit_checker => sub { return shift == $expected_exit; } },
+	 sub { ok(run(pipe(app(["openssl", "base64", "-d",
+				"-in", catfile($ocspdir,$inputfile)]),
+			   app(["openssl", "ocsp", "-respin", "-",
+				"-partial_chain", @check_time,
+				"-CAfile", catfile($ocspdir, $CAfile),
+				"-verify_other", catfile($ocspdir, $CAfile),
+				"-CApath", devnull()]))),
+		  $title); });
+}
+
+plan tests => 10;
+
+subtest "=== VALID OCSP RESPONSES ===" => sub {
+    plan tests => 6;
+
+    test_ocsp("NON-DELEGATED; Intermediate CA -> EE",
+	      "ND1.ors", "ND1_Issuer_ICA.pem", 0);
+    test_ocsp("NON-DELEGATED; Root CA -> Intermediate CA",
+	      "ND2.ors", "ND2_Issuer_Root.pem", 0);
+    test_ocsp("NON-DELEGATED; Root CA -> EE",
+	      "ND3.ors", "ND3_Issuer_Root.pem", 0);
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "D1.ors", "D1_Issuer_ICA.pem", 0);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "D2.ors", "D2_Issuer_Root.pem", 0);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "D3.ors", "D3_Issuer_Root.pem", 0);
+};
+
+subtest "=== INVALID SIGNATURE on the OCSP RESPONSE ===" => sub {
+    plan tests => 6;
+
+    test_ocsp("NON-DELEGATED; Intermediate CA -> EE",
+	      "ISOP_ND1.ors", "ND1_Issuer_ICA.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> Intermediate CA",
+	      "ISOP_ND2.ors", "ND2_Issuer_Root.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> EE",
+	      "ISOP_ND3.ors", "ND3_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "ISOP_D1.ors", "D1_Issuer_ICA.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "ISOP_D2.ors", "D2_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "ISOP_D3.ors", "D3_Issuer_Root.pem", 1);
+};
+
+subtest "=== WRONG RESPONDERID in the OCSP RESPONSE ===" => sub {
+    plan tests => 6;
+
+    test_ocsp("NON-DELEGATED; Intermediate CA -> EE",
+	      "WRID_ND1.ors", "ND1_Issuer_ICA.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> Intermediate CA",
+	      "WRID_ND2.ors", "ND2_Issuer_Root.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> EE",
+	      "WRID_ND3.ors", "ND3_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "WRID_D1.ors", "D1_Issuer_ICA.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "WRID_D2.ors", "D2_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "WRID_D3.ors", "D3_Issuer_Root.pem", 1);
+};
+
+subtest "=== WRONG ISSUERNAMEHASH in the OCSP RESPONSE ===" => sub {
+    plan tests => 6;
+
+    test_ocsp("NON-DELEGATED; Intermediate CA -> EE",
+	      "WINH_ND1.ors", "ND1_Issuer_ICA.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> Intermediate CA",
+	      "WINH_ND2.ors", "ND2_Issuer_Root.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> EE",
+	      "WINH_ND3.ors", "ND3_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "WINH_D1.ors", "D1_Issuer_ICA.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "WINH_D2.ors", "D2_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "WINH_D3.ors", "D3_Issuer_Root.pem", 1);
+};
+
+subtest "=== WRONG ISSUERKEYHASH in the OCSP RESPONSE ===" => sub {
+    plan tests => 6;
+
+    test_ocsp("NON-DELEGATED; Intermediate CA -> EE",
+	      "WIKH_ND1.ors", "ND1_Issuer_ICA.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> Intermediate CA",
+	      "WIKH_ND2.ors", "ND2_Issuer_Root.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> EE",
+	      "WIKH_ND3.ors", "ND3_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "WIKH_D1.ors", "D1_Issuer_ICA.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "WIKH_D2.ors", "D2_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "WIKH_D3.ors", "D3_Issuer_Root.pem", 1);
+};
+
+subtest "=== WRONG KEY in the DELEGATED OCSP SIGNING CERTIFICATE ===" => sub {
+    plan tests => 3;
+
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "WKDOSC_D1.ors", "D1_Issuer_ICA.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "WKDOSC_D2.ors", "D2_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "WKDOSC_D3.ors", "D3_Issuer_Root.pem", 1);
+};
+
+subtest "=== INVALID SIGNATURE on the DELEGATED OCSP SIGNING CERTIFICATE ===" => sub {
+    plan tests => 3;
+
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "ISDOSC_D1.ors", "D1_Issuer_ICA.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "ISDOSC_D2.ors", "D2_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "ISDOSC_D3.ors", "D3_Issuer_Root.pem", 1);
+};
+
+subtest "=== WRONG SUBJECT NAME in the ISSUER CERTIFICATE ===" => sub {
+    plan tests => 6;
+
+    test_ocsp("NON-DELEGATED; Intermediate CA -> EE",
+	      "ND1.ors", "WSNIC_ND1_Issuer_ICA.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> Intermediate CA",
+	      "ND2.ors", "WSNIC_ND2_Issuer_Root.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> EE",
+	      "ND3.ors", "WSNIC_ND3_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "D1.ors", "WSNIC_D1_Issuer_ICA.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "D2.ors", "WSNIC_D2_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "D3.ors", "WSNIC_D3_Issuer_Root.pem", 1);
+};
+
+subtest "=== WRONG KEY in the ISSUER CERTIFICATE ===" => sub {
+    plan tests => 6;
+
+    test_ocsp("NON-DELEGATED; Intermediate CA -> EE",
+	      "ND1.ors", "WKIC_ND1_Issuer_ICA.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> Intermediate CA",
+	      "ND2.ors", "WKIC_ND2_Issuer_Root.pem", 1);
+    test_ocsp("NON-DELEGATED; Root CA -> EE",
+	      "ND3.ors", "WKIC_ND3_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "D1.ors", "WKIC_D1_Issuer_ICA.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "D2.ors", "WKIC_D2_Issuer_Root.pem", 1);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "D3.ors", "WKIC_D3_Issuer_Root.pem", 1);
+};
+
+subtest "=== INVALID SIGNATURE on the ISSUER CERTIFICATE ===" => sub {
+    plan tests => 6;
+
+    # Expect success, because we're explicitly trusting the issuer certificate.
+    test_ocsp("NON-DELEGATED; Intermediate CA -> EE",
+	      "ND1.ors", "ISIC_ND1_Issuer_ICA.pem", 0);
+    test_ocsp("NON-DELEGATED; Root CA -> Intermediate CA",
+	      "ND2.ors", "ISIC_ND2_Issuer_Root.pem", 0);
+    test_ocsp("NON-DELEGATED; Root CA -> EE",
+	      "ND3.ors", "ISIC_ND3_Issuer_Root.pem", 0);
+    test_ocsp("DELEGATED; Intermediate CA -> EE",
+	      "D1.ors", "ISIC_D1_Issuer_ICA.pem", 0);
+    test_ocsp("DELEGATED; Root CA -> Intermediate CA",
+	      "D2.ors", "ISIC_D2_Issuer_Root.pem", 0);
+    test_ocsp("DELEGATED; Root CA -> EE",
+	      "D3.ors", "ISIC_D3_Issuer_Root.pem", 0);
+};
diff --git a/test/recipes/80-test_ssl.t b/test/recipes/80-test_ssl.t
new file mode 100644
index 0000000..409e68f
--- /dev/null
+++ b/test/recipes/80-test_ssl.t
@@ -0,0 +1,627 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use POSIX;
+use File::Spec;
+use File::Copy;
+use OpenSSL::Test qw/:DEFAULT with top_file cmdstr/;
+
+setup("test_ssl");
+
+my $digest = "-sha1";
+my @reqcmd = ("openssl", "req");
+my @x509cmd = ("openssl", "x509", $digest);
+my @verifycmd = ("openssl", "verify");
+my $dummycnf = top_file("apps", "openssl.cnf");
+
+my $CAkey = "keyCA.ss";
+my $CAcert="certCA.ss";
+my $CAserial="certCA.srl";
+my $CAreq="reqCA.ss";
+my $CAconf=top_file("test","CAss.cnf");
+my $CAreq2="req2CA.ss";	# temp
+
+my $Uconf=top_file("test","Uss.cnf");
+my $Ukey="keyU.ss";
+my $Ureq="reqU.ss";
+my $Ucert="certU.ss";
+
+my $Dkey="keyD.ss";
+my $Dreq="reqD.ss";
+my $Dcert="certD.ss";
+
+my $Ekey="keyE.ss";
+my $Ereq="reqE.ss";
+my $Ecert="certE.ss";
+
+my $P1conf=top_file("test","P1ss.cnf");
+my $P1key="keyP1.ss";
+my $P1req="reqP1.ss";
+my $P1cert="certP1.ss";
+my $P1intermediate="tmp_intP1.ss";
+
+my $P2conf=top_file("test","P2ss.cnf");
+my $P2key="keyP2.ss";
+my $P2req="reqP2.ss";
+my $P2cert="certP2.ss";
+my $P2intermediate="tmp_intP2.ss";
+
+plan tests =>
+    1				# For testss
+    + 1				# For ssltest -test_cipherlist
+    + 8				# For the first testssl
+    + 16			# For the first testsslproxy
+    + 16			# For the second testsslproxy
+    ;
+
+subtest 'test_ss' => sub {
+    if (testss()) {
+	open OUT, ">", "intP1.ss";
+	copy($CAcert, \*OUT); copy($Ucert, \*OUT);
+	close OUT;
+
+	open OUT, ">", "intP2.ss";
+	copy($CAcert, \*OUT); copy($Ucert, \*OUT); copy($P1cert, \*OUT);
+	close OUT;
+    }
+};
+
+my $check = ok(run(test(["ssltest","-test_cipherlist"])), "running ssltest");
+
+  SKIP: {
+      skip "ssltest ended with error, skipping the rest", 3
+	  if !$check;
+
+      note('test_ssl -- key U');
+      testssl("keyU.ss", $Ucert, $CAcert);
+
+      note('test_ssl -- key P1');
+      testsslproxy("keyP1.ss", "certP1.ss", "intP1.ss", "AB");
+
+      note('test_ssl -- key P2');
+      testsslproxy("keyP2.ss", "certP2.ss", "intP2.ss", "BC");
+    }
+
+# -----------
+# subtest functions
+sub testss {
+    open RND, ">>", ".rnd";
+    print RND "string to make the random number generator think it has entropy";
+    close RND;
+
+    my @req_dsa = ("-newkey",
+                   "dsa:".File::Spec->catfile("..", "apps", "dsa1024.pem"));;
+    my @req_new;
+    if (run(app(["openssl", "no-rsa"], stdout => undef))) {
+	@req_new = @req_dsa;
+    } else {
+	@req_new = ("-new");
+    }
+
+    plan tests => 17;
+
+  SKIP: {
+      skip 'failure', 16 unless
+	  ok(run(app([@reqcmd, "-config", $CAconf,
+		      "-out", $CAreq, "-keyout", $CAkey,
+		      @req_new])),
+	     'make cert request');
+
+      skip 'failure', 15 unless
+	  ok(run(app([@x509cmd, "-CAcreateserial", "-in", $CAreq, "-days", "30",
+		      "-req", "-out", $CAcert, "-signkey", $CAkey,
+		      "-extfile", $CAconf, "-extensions", "v3_ca"],
+		     stdout => "err.ss")),
+	     'convert request into self-signed cert');
+
+      skip 'failure', 14 unless
+	  ok(run(app([@x509cmd, "-in", $CAcert,
+		      "-x509toreq", "-signkey", $CAkey, "-out", $CAreq2],
+		     stdout => "err.ss")),
+	     'convert cert into a cert request');
+
+      skip 'failure', 13 unless
+	  ok(run(app([@reqcmd, "-config", $dummycnf,
+		      "-verify", "-in", $CAreq, "-noout"])),
+	     'verify request 1');
+
+
+      skip 'failure', 12 unless
+	  ok(run(app([@reqcmd, "-config", $dummycnf,
+		      "-verify", "-in", $CAreq2, "-noout"])),
+	     'verify request 2');
+
+      skip 'failure', 11 unless
+	  ok(run(app([@verifycmd, "-CAfile", $CAcert, $CAcert])),
+	     'verify signature');
+
+      skip 'failure', 10 unless
+	  ok(run(app([@reqcmd, "-config", $Uconf,
+		      "-out", $Ureq, "-keyout", $Ukey, @req_new],
+		     stdout => "err.ss")),
+	     'make a user cert request');
+
+      skip 'failure', 9 unless
+	  ok(run(app([@x509cmd, "-CAcreateserial", "-in", $Ureq, "-days", "30",
+		      "-req", "-out", $Ucert,
+		      "-CA", $CAcert, "-CAkey", $CAkey, "-CAserial", $CAserial,
+		      "-extfile", $Uconf, "-extensions", "v3_ee"],
+		     stdout => "err.ss"))
+	     && run(app([@verifycmd, "-CAfile", $CAcert, $Ucert])),
+	     'sign user cert request');
+
+      skip 'failure', 8 unless
+	  ok(run(app([@x509cmd,
+		      "-subject", "-issuer", "-startdate", "-enddate",
+		      "-noout", "-in", $Ucert])),
+	     'Certificate details');
+
+      skip 'failure', 7 unless
+          subtest 'DSA certificate creation' => sub {
+              plan skip_all => "skipping DSA certificate creation"
+                  if run(app(["openssl", "no-dsa"], stdout => undef));
+
+              plan tests => 4;
+
+            SKIP: {
+                $ENV{CN2} = "DSA Certificate";
+                skip 'failure', 3 unless
+                    ok(run(app([@reqcmd, "-config", $Uconf,
+                                "-out", $Dreq, "-keyout", $Dkey,
+                                @req_dsa],
+                               stdout => "err.ss")),
+                       "make a DSA user cert request");
+                skip 'failure', 2 unless
+                    ok(run(app([@x509cmd, "-CAcreateserial",
+                                "-in", $Dreq,
+                                "-days", "30",
+                                "-req",
+                                "-out", $Dcert,
+                                "-CA", $CAcert, "-CAkey", $CAkey,
+                                "-CAserial", $CAserial,
+                                "-extfile", $Uconf,
+                                "-extensions", "v3_ee_dsa"],
+                               stdout => "err.ss")),
+                       "sign DSA user cert request");
+                skip 'failure', 1 unless
+                    ok(run(app([@verifycmd, "-CAfile", $CAcert, $Dcert])),
+                       "verify DSA user cert");
+                skip 'failure', 0 unless
+                    ok(run(app([@x509cmd,
+                                "-subject", "-issuer",
+                                "-startdate", "-enddate", "-noout",
+                                "-in", $Dcert])),
+                       "DSA Certificate details");
+              }
+      };
+
+      skip 'failure', 6 unless
+          subtest 'ECDSA/ECDH certificate creation' => sub {
+              plan skip_all => "skipping ECDSA/ECDH certificate creation"
+                  if run(app(["openssl", "no-ec"], stdout => undef));
+
+              plan tests => 5;
+
+            SKIP: {
+                $ENV{CN2} = "ECDSA Certificate";
+                skip 'failure', 4 unless
+                    ok(run(app(["openssl", "ecparam", "-name", "P-256",
+                                "-out", "ecp.ss"])),
+                       "make EC parameters");
+                skip 'failure', 3 unless
+                    ok(run(app([@reqcmd, "-config", $Uconf,
+                                "-out", $Ereq, "-keyout", $Ekey,
+                                "-newkey", "ec:ecp.ss"],
+                               stdout => "err.ss")),
+                       "make a ECDSA/ECDH user cert request");
+                skip 'failure', 2 unless
+                    ok(run(app([@x509cmd, "-CAcreateserial",
+                                "-in", $Ereq,
+                                "-days", "30",
+                                "-req",
+                                "-out", $Ecert,
+                                "-CA", $CAcert, "-CAkey", $CAkey,
+                                "-CAserial", $CAserial,
+                                "-extfile", $Uconf,
+                                "-extensions", "v3_ee_ec"],
+                               stdout => "err.ss")),
+                       "sign ECDSA/ECDH user cert request");
+                skip 'failure', 1 unless
+                    ok(run(app([@verifycmd, "-CAfile", $CAcert, $Ecert])),
+                       "verify ECDSA/ECDH user cert");
+                skip 'failure', 0 unless
+                    ok(run(app([@x509cmd,
+                                "-subject", "-issuer",
+                                "-startdate", "-enddate", "-noout",
+                                "-in", $Ecert])),
+                       "ECDSA Certificate details");
+              }
+      };
+
+      skip 'failure', 5 unless
+	  ok(run(app([@reqcmd, "-config", $P1conf,
+		      "-out", $P1req, "-keyout", $P1key, @req_new],
+		     stdout => "err.ss")),
+	     'make a proxy cert request');
+
+
+      skip 'failure', 4 unless
+	  ok(run(app([@x509cmd, "-CAcreateserial", "-in", $P1req, "-days", "30",
+		      "-req", "-out", $P1cert,
+		      "-CA", $Ucert, "-CAkey", $Ukey,
+		      "-extfile", $P1conf, "-extensions", "v3_proxy"],
+		     stdout => "err.ss")),
+	     'sign proxy with user cert');
+
+      copy($Ucert, $P1intermediate);
+      run(app([@verifycmd, "-CAfile", $CAcert,
+	       "-untrusted", $P1intermediate, $P1cert]));
+      ok(run(app([@x509cmd,
+		  "-subject", "-issuer", "-startdate", "-enddate",
+		  "-noout", "-in", $P1cert])),
+	 'Certificate details');
+
+      skip 'failure', 2 unless
+	  ok(run(app([@reqcmd, "-config", $P2conf,
+		      "-out", $P2req, "-keyout", $P2key,
+		      @req_new],
+		     stdout => "err.ss")),
+	     'make another proxy cert request');
+
+
+      skip 'failure', 1 unless
+	  ok(run(app([@x509cmd, "-CAcreateserial", "-in", $P2req, "-days", "30",
+		      "-req", "-out", $P2cert,
+		      "-CA", $P1cert, "-CAkey", $P1key,
+		      "-extfile", $P2conf, "-extensions", "v3_proxy"],
+		     stdout => "err.ss")),
+	     'sign second proxy cert request with the first proxy cert');
+
+
+      open OUT, ">", $P2intermediate;
+      copy($Ucert, \*OUT); copy($P1cert, \*OUT);
+      close OUT;
+      run(app([@verifycmd, "-CAfile", $CAcert,
+	       "-untrusted", $P2intermediate, $P2cert]));
+      ok(run(app([@x509cmd,
+		  "-subject", "-issuer", "-startdate", "-enddate",
+		  "-noout", "-in", $P2cert])),
+	 'Certificate details');
+    }
+}
+
+sub testssl {
+    my $key = shift || top_file("apps","server.pem");
+    my $cert = shift || top_file("apps","server.pem");
+    my $CAtmp = shift;
+    my @CA = $CAtmp ? ("-CAfile", $CAtmp) : ("-CApath", top_dir("certs"));
+    my @extra = @_;
+
+    my @ssltest = ("ssltest",
+		   "-s_key", $key, "-s_cert", $cert,
+		   "-c_key", $key, "-c_cert", $cert);
+
+    my $serverinfo = top_file("test","serverinfo.pem");
+
+    my $dsa_cert = 0;
+    if (grep /DSA Public Key/, run(app(["openssl", "x509", "-in", $cert,
+					"-text", "-noout"]), capture => 1)) {
+	$dsa_cert = 1;
+    }
+
+
+    # plan tests => 7;
+
+    subtest 'standard SSL tests' => sub {
+	######################################################################
+	plan tests => 27;
+
+	ok(run(test([@ssltest, "-ssl3", @extra])),
+	   'test sslv3');
+	ok(run(test([@ssltest, "-ssl3", "-server_auth", @CA, @extra])),
+	   'test sslv3 with server authentication');
+	ok(run(test([@ssltest, "-ssl3", "-client_auth", @CA, @extra])),
+	   'test sslv3 with client authentication');
+	ok(run(test([@ssltest, "-ssl3", "-server_auth", "-client_auth", @CA, @extra])),
+	   'test sslv3 with both server and client authentication');
+	ok(run(test([@ssltest, @extra])),
+	   'test sslv2/sslv3');
+	ok(run(test([@ssltest, "-server_auth", @CA, @extra])),
+	   'test sslv2/sslv3 with server authentication');
+	ok(run(test([@ssltest, "-client_auth", @CA, @extra])),
+	   'test sslv2/sslv3 with client authentication');
+	ok(run(test([@ssltest, "-server_auth", "-client_auth", @CA, @extra])),
+	   'test sslv2/sslv3 with both server and client authentication');
+	ok(run(test([@ssltest, "-bio_pair", "-ssl3", @extra])),
+	   'test sslv3 via BIO pair');
+	ok(run(test([@ssltest, "-bio_pair", "-ssl3", "-server_auth", @CA, @extra])),
+	   'test sslv3 with server authentication via BIO pair');
+	ok(run(test([@ssltest, "-bio_pair", "-ssl3", "-client_auth", @CA, @extra])),
+	   'test sslv3 with client authentication via BIO pair');
+	ok(run(test([@ssltest, "-bio_pair", "-ssl3", "-server_auth", "-client_auth", @CA, @extra])),
+	   'test sslv3 with both server and client authentication via BIO pair');
+	ok(run(test([@ssltest, "-bio_pair", @extra])),
+	   'test sslv2/sslv3 via BIO pair');
+	ok(run(test([@ssltest, "-dtls1", @extra])),
+	   'test dtlsv1');
+	ok(run(test([@ssltest, "-dtls1", "-server_auth", @CA, @extra])),
+	   'test dtlsv1 with server authentication');
+	ok(run(test([@ssltest, "-dtls1", "-client_auth", @CA, @extra])),
+	   'test dtlsv1 with client authentication');
+	ok(run(test([@ssltest, "-dtls1", "-server_auth", "-client_auth", @CA, @extra])),
+	   'test dtlsv1 with both server and client authentication');
+	ok(run(test([@ssltest, "-dtls12", @extra])),
+	   'test dtlsv1.2');
+	ok(run(test([@ssltest, "-dtls12", "-server_auth", @CA, @extra])),
+	   'test dtlsv1.2 with server authentication');
+	ok(run(test([@ssltest, "-dtls12", "-client_auth", @CA, @extra])),
+	   'test dtlsv1.2 with client authentication');
+	ok(run(test([@ssltest, "-dtls12", "-server_auth", "-client_auth", @CA, @extra])),
+	   'test dtlsv1.2 with both server and client authentication');
+	{
+	  SKIP: {
+	      skip "skipping test of sslv2/sslv3 w/o (EC)DHE test", 1 if $dsa_cert;
+
+	      ok(run(test([@ssltest, "-bio_pair", "-no_dhe", "-no_ecdhe", @extra])),
+		 'test sslv2/sslv3 w/o (EC)DHE via BIO pair');
+	    }
+	}
+	ok(run(test([@ssltest, "-bio_pair", "-dhe1024dsa", "-v", @extra])),
+	   'test sslv2/sslv3 with 1024bit DHE via BIO pair');
+	ok(run(test([@ssltest, "-bio_pair", "-server_auth", @CA, @extra])),
+	   'test sslv2/sslv3 with server authentication');
+	ok(run(test([@ssltest, "-bio_pair", "-client_auth", @CA, @extra])),
+	   'test sslv2/sslv3 with client authentication via BIO pair');
+	ok(run(test([@ssltest, "-bio_pair", "-server_auth", "-client_auth", @CA, @extra])),
+	   'test sslv2/sslv3 with both client and server authentication via BIO pair');
+	ok(run(test([@ssltest, "-bio_pair", "-server_auth", "-client_auth", "-app_verify", @CA, @extra])),
+	   'test sslv2/sslv3 with both client and server authentication via BIO pair and app verify');
+    };
+
+    subtest "Testing ciphersuites" => sub {
+
+        my @exkeys = ();
+        my $ciphers = "-EXP:-PSK:-SRP:-kDH:-kECDHe";
+
+        if (run(app(["openssl", "no-dhparam"], stdout => undef))) {
+            note "skipping DHE tests\n";
+            $ciphers .= ":-kDHE";
+        }
+        if (run(app(["openssl", "no-dsa"], stdout => undef))) {
+            note "skipping DSA tests\n";
+            $ciphers .= ":-aDSA";
+        } else {
+            push @exkeys, "-s_cert", "certD.ss", "-s_key", "keyD.ss";
+        }
+
+        if (run(app(["openssl", "no-ec"], stdout => undef))) {
+            note "skipping EC tests\n";
+            $ciphers .= ":!aECDSA:!kECDH";
+        } else {
+            push @exkeys, "-s_cert", "certE.ss", "-s_key", "keyE.ss";
+        }
+
+	my @protocols = ("TLSv1.2", "SSLv3");
+	my $protocolciphersuitcount = 0;
+	my %ciphersuites =
+	    map { my @c =
+		      map { split(/:/, $_) }
+		      run(app(["openssl", "ciphers", "${_}:$ciphers"]),
+                          capture => 1);
+		  chomp @c;
+		  $protocolciphersuitcount += scalar @c;
+		  $_ => [ @c ] } @protocols;
+
+        # The count of protocols is because in addition to the ciphersuits
+        # we got above, we're running a weak DH test for each protocol
+	plan tests => $protocolciphersuitcount + scalar(@protocols);
+
+	foreach my $protocol (@protocols) {
+	    note "Testing ciphersuites for $protocol";
+	    foreach my $cipher (@{$ciphersuites{$protocol}}) {
+		ok(run(test([@ssltest, @exkeys, "-cipher", $cipher,
+			     $protocol eq "SSLv3" ? ("-ssl3") : ()])),
+		   "Testing $cipher");
+	    }
+            is(run(test([@ssltest,
+                         "-s_cipher", "EDH",
+                         "-c_cipher", 'EDH:@SECLEVEL=1',
+                         "-dhe512",
+                         $protocol eq "SSLv3" ? ("-ssl3") : ()])), 0,
+               "testing connection with weak DH, expecting failure");
+	}
+    };
+
+    subtest 'RSA/(EC)DHE/PSK tests' => sub {
+	######################################################################
+
+	plan tests => 5;
+
+	{
+	  SKIP: {
+	      skip "skipping anonymous DH tests", 1
+		  if (run(app(["openssl", "no-dhparam"], stdout => undef)));
+
+	      ok(run(test([@ssltest, "-v", "-bio_pair", "-tls1", "-cipher", "ADH", "-dhe1024dsa", "-num", "10", "-f", "-time", @extra])),
+		 'test tlsv1 with 1024bit anonymous DH, multiple handshakes');
+	    }
+	}
+
+	{
+	  SKIP: {
+	      skip "skipping RSA tests", 2
+		  if (run(app(["openssl", "no-rsa"], stdout => undef)));
+
+	      ok(run(test(["ssltest", "-v", "-bio_pair", "-tls1", "-s_cert", top_file("apps","server2.pem"), "-no_dhe", "-no_ecdhe", "-num", "10", "-f", "-time", @extra])),
+		 'test tlsv1 with 1024bit RSA, no (EC)DHE, multiple handshakes');
+
+	      skip "skipping RSA+DHE tests", 1
+		  if (run(app(["openssl", "no-dhparam"], stdout => undef)));
+
+	      ok(run(test(["ssltest", "-v", "-bio_pair", "-tls1", "-s_cert", top_file("apps","server2.pem"), "-dhe1024dsa", "-num", "10", "-f", "-time", @extra])),
+		 'test tlsv1 with 1024bit RSA, 1024bit DHE, multiple handshakes');
+	    }
+	}
+	ok(run(test([@ssltest, "-tls1", "-cipher", "PSK", "-psk", "abc123", @extra])),
+	   'test tls1 with PSK');
+
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-cipher", "PSK", "-psk", "abc123", @extra])),
+	   'test tls1 with PSK via BIO pair');
+    };
+
+    subtest 'Next Protocol Negotiation Tests' => sub {
+	######################################################################
+
+	plan tests => 7;
+
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-npn_client"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-npn_server"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-npn_server_reject"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-npn_client", "-npn_server_reject"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-npn_client", "-npn_server"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-npn_client", "-npn_server", "-num", "2"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-npn_client", "-npn_server", "-num", "2", "-reuse"])));
+    };
+
+    subtest 'Custom Extension tests' => sub {
+	######################################################################
+
+	plan tests => 1;
+
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-custom_ext"])),
+	   'test tls1 with custom extensions');
+    };
+
+    subtest 'Serverinfo tests' => sub {
+	######################################################################
+
+	plan tests => 5;
+
+	note('echo test tls1 with serverinfo');
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-serverinfo_file", $serverinfo])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-serverinfo_file", $serverinfo, "-serverinfo_sct"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-serverinfo_file", $serverinfo, "-serverinfo_tack"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-serverinfo_file", $serverinfo, "-serverinfo_sct", "-serverinfo_tack"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-custom_ext", "-serverinfo_file", $serverinfo, "-serverinfo_sct", "-serverinfo_tack"])));
+    };
+
+    subtest 'ALPN tests' => sub {
+	######################################################################
+
+	plan tests => 12;
+
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-alpn_client", "foo", "-alpn_server", "bar"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-alpn_client", "foo", "-alpn_server", "foo", "-alpn_expected", "foo"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-alpn_client", "foo,bar", "-alpn_server", "foo", "-alpn_expected", "foo"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-alpn_client", "bar,foo", "-alpn_server", "foo", "-alpn_expected", "foo"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-alpn_client", "bar,foo", "-alpn_server", "foo,bar", "-alpn_expected", "foo"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-alpn_client", "bar,foo", "-alpn_server", "bar,foo", "-alpn_expected", "bar"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-alpn_client", "foo,bar", "-alpn_server", "bar,foo", "-alpn_expected", "bar"])));
+	ok(run(test([@ssltest, "-bio_pair", "-tls1", "-alpn_client", "baz", "-alpn_server", "bar,foo"])));
+
+	{
+	  SKIP: {
+	      skip "skipping SRP tests", 4
+		  if run(app(["openssl", "no-srp"], stdout => undef));
+
+	      ok(run(test([@ssltest, "-tls1", "-cipher", "SRP", "-srpuser", "test", "-srppass", "abc123"])),
+		 'test tls1 with SRP');
+
+	      ok(run(test([@ssltest, "-bio_pair", "-tls1", "-cipher", "SRP", "-srpuser", "test", "-srppass", "abc123"])),
+		 'test tls1 with SRP via BIO pair');
+
+	      ok(run(test([@ssltest, "-tls1", "-cipher", "aSRP", "-srpuser", "test", "-srppass", "abc123"])),
+		 'test tls1 with SRP auth');
+
+	      ok(run(test([@ssltest, "-bio_pair", "-tls1", "-cipher", "aSRP", "-srpuser", "test", "-srppass", "abc123"])),
+		 'test tls1 with SRP auth via BIO pair');
+	    }
+	}
+    };
+
+    subtest 'Multi-buffer tests' => sub {
+	######################################################################
+
+	plan tests => 2;
+
+	{
+	  SKIP: {
+	      skip "skipping multi-buffer tests", 2
+		  if @extra || (POSIX::uname())[4] ne "x86_64";
+	      ok(run(test([@ssltest, "-cipher", "AES128-SHA",    "-bytes", "8m"])));
+	      ok(run(test([@ssltest, "-cipher", "AES128-SHA256", "-bytes", "8m"])));
+	    }
+	}
+    };
+}
+
+sub testsslproxy {
+    my $key = shift || top_file("apps","server.pem");
+    my $cert = shift || top_file("apps","server.pem");
+    my $CAtmp = shift;
+    my @CA = $CAtmp ? ("-CAfile", $CAtmp) : ("-CApath", top_dir("certs"));
+    my @extra = @_;
+
+    my @ssltest = ("ssltest",
+		   "-s_key", $key, "-s_cert", $cert,
+		   "-c_key", $key, "-c_cert", $cert);
+
+    # plan tests => 16;
+
+    note('Testing a lot of proxy conditions.');
+
+    # We happen to know that certP1.ss has policy letters "AB" and
+    # certP2.ss has policy letters "BC".  However, because certP2.ss
+    # has certP1.ss as issuer, when it's used, both their policy
+    # letters get combined into just "B".
+    # The policy letter(s) then get filtered with the given auth letter
+    # in the table below, and the result gets tested with the given
+    # condition.  For details, read ssltest.c
+    #
+    # certfilename => [ [ auth, cond, expected result ] ... ]
+    my %expected = ( "certP1.ss" => [ [ [ 'A',  'A'      ], 1 ],
+                                      [ [ 'A',  'B'      ], 0 ],
+                                      [ [ 'A',  'C'      ], 0 ],
+                                      [ [ 'A',  'A|B&!C' ], 1 ],
+                                      [ [ 'B',  'A'      ], 0 ],
+                                      [ [ 'B',  'B'      ], 1 ],
+                                      [ [ 'B',  'C'      ], 0 ],
+                                      [ [ 'B',  'A|B&!C' ], 1 ],
+                                      [ [ 'C',  'A'      ], 0 ],
+                                      [ [ 'C',  'B'      ], 0 ],
+                                      [ [ 'C',  'C'      ], 0 ],
+                                      [ [ 'C',  'A|B&!C' ], 0 ],
+                                      [ [ 'BC', 'A'      ], 0 ],
+                                      [ [ 'BC', 'B'      ], 1 ],
+                                      [ [ 'BC', 'C'      ], 0 ],
+                                      [ [ 'BC', 'A|B&!C' ], 1 ] ],
+                     "certP2.ss" => [ [ [ 'A',  'A'      ], 0 ],
+                                      [ [ 'A',  'B'      ], 0 ],
+                                      [ [ 'A',  'C'      ], 0 ],
+                                      [ [ 'A',  'A|B&!C' ], 0 ],
+                                      [ [ 'B',  'A'      ], 0 ],
+                                      [ [ 'B',  'B'      ], 1 ],
+                                      [ [ 'B',  'C'      ], 0 ],
+                                      [ [ 'B',  'A|B&!C' ], 1 ],
+                                      [ [ 'C',  'A'      ], 0 ],
+                                      [ [ 'C',  'B'      ], 0 ],
+                                      [ [ 'C',  'C'      ], 0 ],
+                                      [ [ 'C',  'A|B&!C' ], 0 ],
+                                      [ [ 'BC', 'A'      ], 0 ],
+                                      [ [ 'BC', 'B'      ], 1 ],
+                                      [ [ 'BC', 'C'      ], 0 ],
+                                      [ [ 'BC', 'A|B&!C' ], 1 ] ] );
+
+    foreach (@{$expected{$cert}}) {
+        my $auth = $_->[0]->[0];
+        my $cond = $_->[0]->[1];
+        my $res  = $_->[1];
+	is(run(test([@ssltest, "-ssl3", "-server_auth", @CA,
+                     "-proxy", "-proxy_auth", $auth,
+                     "-proxy_cond", $cond])), $res,
+	   "test tlsv1, server auth, proxy auth $auth and cond $cond (expect "
+           .($res ? "success" : "failure").")");
+    }
+}
diff --git a/test/recipes/80-test_tsa.t b/test/recipes/80-test_tsa.t
new file mode 100644
index 0000000..171592a
--- /dev/null
+++ b/test/recipes/80-test_tsa.t
@@ -0,0 +1,192 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use POSIX;
+use File::Spec::Functions qw/splitdir curdir catfile/;
+use File::Compare;
+use OpenSSL::Test qw/:DEFAULT cmdstr top_file/;
+
+setup("test_tsa");
+
+# All these are modified inside indir further down. They need to exist
+# here, however, to be available in all subroutines.
+my $testtsa;
+my $CAtsa;
+my @RUN = ("openssl", "ts");
+
+sub create_tsa_cert {
+    my $INDEX = shift;
+    my $EXT = shift;
+    my $r = 1;
+    $ENV{TSDNSECT} = "ts_cert_dn";
+
+    ok(run(app(["openssl", "req", "-new",
+                "-out", "tsa_req${INDEX}.pem",
+                "-keyout", "tsa_key${INDEX}.pem"])));
+    note "using extension $EXT";
+    ok(run(app(["openssl", "x509", "-req",
+                "-in", "tsa_req${INDEX}.pem",
+                "-out", "tsa_cert${INDEX}.pem",
+                "-CA", "tsaca.pem", "-CAkey", "tsacakey.pem",
+                "-CAcreateserial",
+                "-extfile", $ENV{OPENSSL_CONF}, "-extensions", $EXT])));
+}
+
+sub create_time_stamp_response {
+    my $queryfile = shift;
+    my $outputfile = shift;
+    my $datafile = shift;
+
+    ok(run(app([@RUN, "-reply", "-section", "$datafile",
+                "-queryfile", "$queryfile", "-out", "$outputfile"])));
+}
+
+sub verify_time_stamp_response {
+    my $queryfile = shift;
+    my $inputfile = shift;
+    my $datafile = shift;
+
+    ok(run(app([@RUN, "-verify", "-queryfile", "$queryfile",
+                "-in", "$inputfile", "-CAfile", "tsaca.pem",
+                "-untrusted", "tsa_cert1.pem"])));
+    ok(run(app([@RUN, "-verify", "-data", "$datafile",
+                "-in", "$inputfile", "-CAfile", "tsaca.pem",
+                "-untrusted", "tsa_cert1.pem"])));
+}
+
+sub verify_time_stamp_response_fail {
+    my $queryfile = shift;
+    my $inputfile = shift;
+
+    ok(!run(app([@RUN, "-verify", "-queryfile", "$queryfile",
+                 "-in", "$inputfile", "-CAfile", "tsaca.pem",
+                 "-untrusted", "tsa_cert1.pem"])));
+}
+
+# main functions
+
+plan tests => 20;
+
+note "setting up TSA test directory";
+indir "tsa" => sub
+{
+    $ENV{OPENSSL_CONF} = top_file("test", "CAtsa.cnf");
+    # Because that's what ../apps/CA.pl really looks at
+    $ENV{SSLEAY_CONFIG} = "-config ".$ENV{OPENSSL_CONF};
+    $ENV{OPENSSL} = cmdstr(app(["openssl"]));
+    $testtsa = top_file("test", "recipes", "80-test_tsa.t");
+    $CAtsa = top_file("test", "CAtsa.cnf");
+
+ SKIP: {
+     $ENV{TSDNSECT} = "ts_ca_dn";
+     skip "failed", 19
+         unless ok(run(app(["openssl", "req", "-new", "-x509", "-nodes",
+                            "-out", "tsaca.pem", "-keyout", "tsacakey.pem"])),
+                   'creating a new CA for the TSA tests');
+
+     skip "failed", 18
+         unless subtest 'creating tsa_cert1.pem TSA server cert' => sub {
+             create_tsa_cert("1", "tsa_cert")
+     };
+
+     skip "failed", 17
+         unless subtest 'creating tsa_cert2.pem non-TSA server cert' => sub {
+             create_tsa_cert("2", "non_tsa_cert")
+     };
+
+     skip "failed", 16
+         unless ok(run(app([@RUN, "-query", "-data", $testtsa,
+                            "-policy", "tsa_policy1", "-cert",
+                            "-out", "req1.tsq"])),
+                   'creating req1.req time stamp request for file testtsa');
+
+     ok(run(app([@RUN, "-query", "-in", "req1.tsq", "-text"])),
+        'printing req1.req');
+
+     subtest 'generating valid response for req1.req' => sub {
+         create_time_stamp_response("req1.tsq", "resp1.tsr", "tsa_config1")
+     };
+
+     ok(run(app([@RUN, "-reply", "-in", "resp1.tsr", "-text"])),
+        'printing response');
+
+     subtest 'verifying valid response' => sub {
+         verify_time_stamp_response("req1.tsq", "resp1.tsr", $testtsa)
+     };
+
+     skip "failed", 11
+         unless subtest 'verifying valid token' => sub {
+             ok(run(app([@RUN, "-reply", "-in", "resp1.tsr",
+                         "-out", "resp1.tsr.token", "-token_out"])));
+             ok(run(app([@RUN, "-verify", "-queryfile", "req1.tsq",
+                         "-in", "resp1.tsr.token", "-token_in",
+                         "-CAfile", "tsaca.pem",
+                         "-untrusted", "tsa_cert1.pem"])));
+             ok(run(app([@RUN, "-verify", "-data", $testtsa,
+                         "-in", "resp1.tsr.token", "-token_in",
+                         "-CAfile", "tsaca.pem",
+                         "-untrusted", "tsa_cert1.pem"])));
+     };
+
+     skip "failed", 10
+         unless ok(run(app([@RUN, "-query", "-data", $testtsa,
+                            "-policy", "tsa_policy2", "-no_nonce",
+                            "-out", "req2.tsq"])),
+                   'creating req2.req time stamp request for file testtsa');
+
+     ok(run(app([@RUN, "-query", "-in", "req2.tsq", "-text"])),
+        'printing req2.req');
+
+     skip "failed", 8
+         unless subtest 'generating valid response for req2.req' => sub {
+             create_time_stamp_response("req2.tsq", "resp2.tsr", "tsa_config1")
+     };
+
+     skip "failed", 7
+         unless subtest 'checking -token_in and -token_out options with -reply' => sub {
+             my $RESPONSE2="resp2.tsr.copy.tsr";
+             my $TOKEN_DER="resp2.tsr.token.der";
+
+             ok(run(app([@RUN, "-reply", "-in", "resp2.tsr",
+                         "-out", "$TOKEN_DER", "-token_out"])));
+             ok(run(app([@RUN, "-reply", "-in", "$TOKEN_DER",
+                         "-token_in", "-out", "$RESPONSE2"])));
+             is(compare($RESPONSE2, "resp2.tsr"), 0);
+             ok(run(app([@RUN, "-reply", "-in", "resp2.tsr",
+                         "-text", "-token_out"])));
+             ok(run(app([@RUN, "-reply", "-in", "$TOKEN_DER",
+                         "-token_in", "-text", "-token_out"])));
+             ok(run(app([@RUN, "-reply", "-queryfile", "req2.tsq",
+                         "-text", "-token_out"])));
+     };
+
+     ok(run(app([@RUN, "-reply", "-in", "resp2.tsr", "-text"])),
+        'printing response');
+
+     subtest 'verifying valid response' => sub {
+         verify_time_stamp_response("req2.tsq", "resp2.tsr", $testtsa)
+     };
+
+     subtest 'verifying response against wrong request, it should fail' => sub {
+         verify_time_stamp_response_fail("req1.tsq", "resp2.tsr")
+     };
+
+     subtest 'verifying response against wrong request, it should fail' => sub {
+         verify_time_stamp_response_fail("req2.tsq", "resp1.tsr")
+     };
+
+     skip "failure", 2
+         unless ok(run(app([@RUN, "-query", "-data", $CAtsa,
+                            "-no_nonce", "-out", "req3.tsq"])),
+                   "creating req3.req time stamp request for file CAtsa.cnf");
+
+     ok(run(app([@RUN, "-query", "-in", "req3.tsq", "-text"])),
+        'printing req3.req');
+
+     subtest 'verifying response against wrong request, it should fail' => sub {
+         verify_time_stamp_response_fail("req3.tsq", "resp1.tsr")
+     };
+    }
+}, create => 1, cleanup => 1
diff --git a/test/recipes/90-test_constant_time.t b/test/recipes/90-test_constant_time.t
new file mode 100644
index 0000000..cfdb578
--- /dev/null
+++ b/test/recipes/90-test_constant_time.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_constant_time", "constant_time_test");
diff --git a/test/recipes/90-test_gmdiff.t b/test/recipes/90-test_gmdiff.t
new file mode 100644
index 0000000..115445e
--- /dev/null
+++ b/test/recipes/90-test_gmdiff.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_gmdiff", "gmdifftest");
diff --git a/test/recipes/90-test_gost2814789.t b/test/recipes/90-test_gost2814789.t
new file mode 100644
index 0000000..e97128f
--- /dev/null
+++ b/test/recipes/90-test_gost2814789.t
@@ -0,0 +1,13 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use OpenSSL::Test qw/:DEFAULT top_dir/;
+
+setup("test_gost2814789");
+
+$ENV{OPENSSL_ENGINES} =
+    $ENV{BIN_D} ? top_dir($ENV{BIN_D}) : top_dir("engines", "ccgost");
+
+plan tests => 1;
+ok(run(test(["gost2814789test"])), 'running gost2814789test');
diff --git a/test/recipes/90-test_heartbeat.t b/test/recipes/90-test_heartbeat.t
new file mode 100644
index 0000000..660f630
--- /dev/null
+++ b/test/recipes/90-test_heartbeat.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_heartbeat", "heartbeat_test");
diff --git a/test/recipes/90-test_ige.t b/test/recipes/90-test_ige.t
new file mode 100644
index 0000000..f008350
--- /dev/null
+++ b/test/recipes/90-test_ige.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_ige", "igetest");
diff --git a/test/recipes/90-test_jpake.t b/test/recipes/90-test_jpake.t
new file mode 100644
index 0000000..fa1292a
--- /dev/null
+++ b/test/recipes/90-test_jpake.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_jpake", "jpaketest");
diff --git a/test/recipes/90-test_np.t b/test/recipes/90-test_np.t
new file mode 100644
index 0000000..a0d8b4b
--- /dev/null
+++ b/test/recipes/90-test_np.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_np", "nptest");
diff --git a/test/recipes/90-test_p5_crpt2.t b/test/recipes/90-test_p5_crpt2.t
new file mode 100644
index 0000000..838e0d7
--- /dev/null
+++ b/test/recipes/90-test_p5_crpt2.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_p5_crpt2", "p5_crpt2_test");
diff --git a/test/recipes/90-test_secmem.t b/test/recipes/90-test_secmem.t
new file mode 100644
index 0000000..59f3bdd
--- /dev/null
+++ b/test/recipes/90-test_secmem.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_secmem", "secmemtest");
diff --git a/test/recipes/90-test_srp.t b/test/recipes/90-test_srp.t
new file mode 100644
index 0000000..6be2c39
--- /dev/null
+++ b/test/recipes/90-test_srp.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_srp", "srptest");
diff --git a/test/recipes/90-test_v3name.t b/test/recipes/90-test_v3name.t
new file mode 100644
index 0000000..2a8a472
--- /dev/null
+++ b/test/recipes/90-test_v3name.t
@@ -0,0 +1,5 @@
+#! /usr/bin/perl
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_v3name", "v3nametest");
diff --git a/test/recipes/bc.pl b/test/recipes/bc.pl
new file mode 100644
index 0000000..29a4a8a
--- /dev/null
+++ b/test/recipes/bc.pl
@@ -0,0 +1,97 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use Math::BigInt;
+
+sub calc {
+    @_ = __adder(@_);
+    if (scalar @_ != 1) { return "NaN"; }
+    return shift;
+}
+
+sub __canonhex {
+    my ($sign, $hex) = (shift =~ /^([+\-]?)(.*)$/);
+    $hex = "0x".$hex if $hex !~ /^0x/;
+    return $sign.$hex;
+}
+
+sub __adder {
+    @_ = __multiplier(@_);
+    while (scalar @_ > 1 && $_[1] =~ /^[\+\-]$/) {
+	my $operand1 = Math::BigInt->from_hex(__canonhex(shift));
+	my $operator = shift;
+	@_ = __multiplier(@_);
+	my $operand2 = Math::BigInt->from_hex(__canonhex(shift));
+	if ($operator eq "+") {
+	    $operand1->badd($operand2);
+	} elsif ($operator eq "-") {
+	    $operand1->bsub($operand2);
+	} else {
+	    die "SOMETHING WENT AWFULLY WRONG";
+	}
+	unshift @_, $operand1->as_hex();
+    }
+    return @_;
+}
+
+sub __multiplier {
+    @_ = __power(@_);
+    while (scalar @_ > 1 && $_[1] =~ /^[\*\/%]$/) {
+	my $operand1 = Math::BigInt->from_hex(__canonhex(shift));
+	my $operator = shift;
+	@_ = __power(@_);
+	my $operand2 = Math::BigInt->from_hex(__canonhex(shift));
+	if ($operator eq "*") {
+	    $operand1->bmul($operand2);
+	} elsif ($operator eq "/") {
+	    $operand1->bdiv($operand2);
+	} elsif ($operator eq "%") {
+	    # Here's a bit of a quirk...
+	    # With OpenSSL's BN, as well as bc, the result of -10 % 3 is -1
+	    # while Math::BigInt, the result is 2.
+	    # The latter is mathematically more correct, but...
+	    my $o1isneg = $operand1->is_neg();
+	    $operand1->babs();
+	    # Math::BigInt does something different with a negative modulus,
+	    # while OpenSSL's BN and bc treat it like a positive number...
+	    $operand2->babs();
+	    $operand1->bmod($operand2);
+	    if ($o1isneg) { $operand1->bneg(); }
+	} else {
+	    die "SOMETHING WENT AWFULLY WRONG";
+	}
+	unshift @_, $operand1->as_hex();
+    }
+    return @_;
+}
+
+sub __power {
+    @_ = __paren(@_);
+    while (scalar @_ > 1 && $_[1] eq "^") {
+	my $operand1 = Math::BigInt->from_hex(__canonhex(shift));
+	shift;
+	@_ = __paren(@_);
+	my $operand2 = Math::BigInt->from_hex(__canonhex(shift));
+	$operand1->bpow($operand2);
+	unshift @_, $operand1->as_hex();
+    }
+    return @_;
+}
+
+# returns array ( $result, @remaining )
+sub __paren {
+    if (scalar @_ > 0 && $_[0] eq "(") {
+	shift;
+	my @result = __adder(@_);
+	if (scalar @_ == 0 || $_[0] ne ")") {
+	    return ("NaN");
+	}
+	shift;
+	return @result;
+    }
+    return @_;
+}
+
+1;
diff --git a/test/recipes/tconversion.pl b/test/recipes/tconversion.pl
new file mode 100644
index 0000000..011dcbf
--- /dev/null
+++ b/test/recipes/tconversion.pl
@@ -0,0 +1,88 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Compare qw/compare_text/;
+use File::Copy;
+use lib 'testlib';
+use OpenSSL::Test qw/:DEFAULT top_file/;
+
+my %conversionforms = (
+    # Default conversion forms.  Other series may be added with
+    # specific test types as key.
+    "*"		=> [ "d", "p" ],
+    );
+sub tconversion {
+    my $testtype = shift;
+    my $t = shift;
+    my @conversionforms = 
+	defined($conversionforms{$testtype}) ?
+	@{$conversionforms{$testtype}} :
+	@{$conversionforms{"*"}};
+    my @openssl_args = @_;
+    if (!@openssl_args) { @openssl_args = ($testtype); }
+
+    my $n = scalar @conversionforms;
+    my $totaltests =
+	1			# for initializing
+	+ $n			# initial conversions from p to all forms (A)
+	+ $n*$n			# conversion from result of A to all forms (B)
+	+ 1			# comparing original test file to p form of A
+	+ $n*($n-1);		# comparing first conversion to each fom in A with B
+    $totaltests-- if ($testtype eq "p7d"); # no comparison of original test file
+    plan tests => $totaltests;
+
+    my @cmd = ("openssl", @openssl_args);
+
+    my $init;
+    if (scalar @openssl_args > 0 && $openssl_args[0] eq "pkey") {
+	$init = ok(run(app([@cmd, "-in", $t, "-out", "$testtype-fff.p"])),
+		   'initializing');
+    } else {
+	$init = ok(copy($t, "$testtype-fff.p"), 'initializing');
+    }
+    if (!$init) {
+	diag("Trying to copy $t to $testtype-fff.p : $!");
+    }
+
+  SKIP: {
+      skip "Not initialized, skipping...", 22 unless $init;
+
+      foreach my $to (@conversionforms) {
+	  ok(run(app([@cmd,
+		      "-in", "$testtype-fff.p",
+		      "-inform", "p",
+		      "-outform", $to],
+		     stdout => "$testtype-f.$to")), "p -> $to");
+      }
+
+      foreach my $to (@conversionforms) {
+	  foreach my $from (@conversionforms) {
+	      ok(run(app([@cmd,
+			  "-in", "$testtype-f.$from",
+			  "-inform", $from,
+			  "-outform", $to],
+			 stdout => "$testtype-ff.$from$to")), "$from -> $to");
+	  }
+      }
+
+      if ($testtype ne "p7d") {
+	  is(compare_text("$testtype-fff.p", "$testtype-f.p"), 0,
+	     'comparing orig to p');
+      }
+
+      foreach my $to (@conversionforms) {
+	  next if $to eq "d";
+	  foreach my $from (@conversionforms) {
+	      is(compare_text("$testtype-f.$to", "$testtype-ff.$from$to"), 0,
+		 "comparing $to to $from$to");
+	  }
+      }
+    }
+    unlink glob "$testtype-f.*";
+    unlink glob "$testtype-ff.*";
+    unlink glob "$testtype-fff.*";
+}
+
+1;
diff --git a/test/run_tests.pl b/test/run_tests.pl
new file mode 100644
index 0000000..7e61282
--- /dev/null
+++ b/test/run_tests.pl
@@ -0,0 +1,45 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Spec::Functions qw/catdir catfile curdir abs2rel rel2abs/;
+use File::Basename;
+use Test::Harness qw/runtests $switches/;
+
+my $top = $ENV{TOP};
+my $recipesdir = catdir($top, "test", "recipes");
+my $testlib = catdir($top, "test", "testlib");
+my $utillib = catdir($top, "util");
+
+# It seems that $switches is getting interpretted with 'eval' or something
+# like that, and that we need to take care of backslashes or they will
+# disappear along the way.
+$testlib =~ s|\\|\\\\|g if $^O eq "MSWin32";
+$utillib =~ s|\\|\\\\|g if $^O eq "MSWin32";
+
+# Test::Harness provides the variable $switches to give it
+# switches to be used when it calls our recipes.
+$switches = "-w \"-I$testlib\" \"-I$utillib\"";
+
+my @tests = ( "alltests" );
+if (@ARGV) {
+    @tests = @ARGV;
+}
+if (grep /^alltests$/, @tests) {
+    @tests = grep {
+	basename($_) =~ /^[0-9][0-9]-[^\.]*\.t$/
+    } glob(catfile($recipesdir,"*.t"));
+} else {
+    my @t = ();
+    foreach (@tests) {
+	push @t, grep {
+	    basename($_) =~ /^[0-9][0-9]-[^\.]*\.t$/
+	} glob(catfile($recipesdir,"*-$_.t"));
+    }
+    @tests = @t;
+}
+
+ at tests = map { abs2rel($_, rel2abs(curdir())); } @tests;
+
+runtests(sort @tests);
diff --git a/test/testlib/OpenSSL/Test.pm b/test/testlib/OpenSSL/Test.pm
new file mode 100644
index 0000000..f378351
--- /dev/null
+++ b/test/testlib/OpenSSL/Test.pm
@@ -0,0 +1,741 @@
+package OpenSSL::Test;
+
+use strict;
+use warnings;
+
+use Test::More 0.96;
+
+use Exporter;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+$VERSION = "0.7";
+ at ISA = qw(Exporter);
+ at EXPORT = (@Test::More::EXPORT, qw(setup indir app test run));
+ at EXPORT_OK = (@Test::More::EXPORT_OK, qw(top_dir top_file pipe with cmdstr
+                                         quotify));
+
+=head1 NAME
+
+OpenSSL::Test - a private extension of Test::More
+
+=head1 SYNOPSIS
+
+  use OpenSSL::Test;
+
+  setup("my_test_name");
+
+  ok(run(app(["openssl", "version"])), "check for openssl presence");
+
+  indir "subdir" => sub {
+    ok(run(test(["sometest", "arg1"], stdout => "foo.txt")),
+       "run sometest with output to foo.txt");
+  };
+
+=head1 DESCRIPTION
+
+This module is a private extension of L<Test::More> for testing OpenSSL.
+In addition to the Test::More functions, it also provides functions that
+easily find the diverse programs within a OpenSSL build tree, as well as
+some other useful functions.
+
+This module I<depends> on the environment variable C<$TOP>.  Without it,
+it refuses to work.  See L</ENVIRONMENT> below.
+
+=cut
+
+use File::Copy;
+use File::Spec::Functions qw/file_name_is_absolute curdir canonpath splitdir
+                             catdir catfile splitpath catpath devnull abs2rel
+                             rel2abs/;
+use File::Path 2.00 qw/remove_tree mkpath/;
+
+
+# The name of the test.  This is set by setup() and is used in the other
+# functions to verify that setup() has been used.
+my $test_name = undef;
+
+# Directories we want to keep track of TOP, APPS, TEST and RESULTS are the
+# ones we're interested in, corresponding to the environment variables TOP
+# (mandatory), BIN_D, TEST_D and RESULT_D.
+my %directories = ();
+
+# A bool saying if we shall stop all testing if the current recipe has failing
+# tests or not.  This is set by setup() if the environment variable STOPTEST
+# is defined with a non-empty value.
+my $end_with_bailout = 0;
+
+# A set of hooks that is affected by with() and may be used in diverse places.
+# All hooks are expected to be CODE references.
+my %hooks = (
+
+    # exit_checker is used by run() directly after completion of a command.
+    # it receives the exit code from that command and is expected to return
+    # 1 (for success) or 0 (for failure).  This is the value that will be
+    # returned by run().
+    # NOTE: When run() gets the option 'capture => 1', this hook is ignored.
+    exit_checker => sub { return shift == 0 ? 1 : 0 },
+
+    );
+
+# Declare some utility functions that are defined at the end
+sub top_file;
+sub top_dir;
+sub quotify;
+
+# Declare some private functions that are defined at the end
+sub __env;
+sub __cwd;
+sub __apps_file;
+sub __results_file;
+sub __test_log;
+sub __cwd;
+sub __fixup_cmd;
+sub __build_cmd;
+
+=head2 Main functions
+
+The following functions are exported by default when using C<OpenSSL::Test>.
+
+=cut
+
+=over 4
+
+=item B<setup "NAME">
+
+C<setup> is used for initial setup, and it is mandatory that it's used.
+If it's not used in a OpenSSL test recipe, the rest of the recipe will
+most likely refuse to run.
+
+C<setup> checks for environment variables (see L</ENVIRONMENT> below),
+check that C<$TOP/Configure> exists, C<chdir> into the results directory
+(defined by the C<$RESULT_D> environment variable if defined, otherwise
+C<$TEST_D> if defined, otherwise C<$TOP/test>).
+
+=back
+
+=cut
+
+sub setup {
+    $test_name = shift;
+
+    BAIL_OUT("setup() must receive a name") unless $test_name;
+    BAIL_OUT("setup() needs \$TOP to be defined") unless $ENV{TOP};
+
+    __env();
+
+    BAIL_OUT("setup() expects the file Configure in the \$TOP directory")
+	unless -f top_file("Configure");
+
+    __cwd($directories{RESULTS});
+
+    # Loop in case we're on a platform with more than one file generation
+    1 while unlink(__test_log());
+}
+
+=over 4
+
+=item B<indir "SUBDIR" =E<gt> sub BLOCK, OPTS>
+
+C<indir> is used to run a part of the recipe in a different directory than
+the one C<setup> moved into, usually a subdirectory, given by SUBDIR.
+The part of the recipe that's run there is given by the codeblock BLOCK.
+
+C<indir> takes some additional options OPTS that affect the subdirectory:
+
+=over 4
+
+=item B<create =E<gt> 0|1>
+
+When set to 1 (or any value that perl preceives as true), the subdirectory
+will be created if it doesn't already exist.  This happens before BLOCK
+is executed.
+
+=item B<cleanup =E<gt> 0|1>
+
+When set to 1 (or any value that perl preceives as true), the subdirectory
+will be cleaned out and removed.  This happens both before and after BLOCK
+is executed.
+
+=back
+
+An example:
+
+  indir "foo" => sub {
+      ok(run(app(["openssl", "version"]), stdout => "foo.txt"));
+      if (ok(open(RESULT, "foo.txt"), "reading foo.txt")) {
+          my $line = <RESULT>;
+          close RESULT;
+          is($line, qr/^OpenSSL 1\./,
+             "check that we're using OpenSSL 1.x.x");
+      }
+  }, create => 1, cleanup => 1;
+
+=back
+
+=cut
+
+sub indir {
+    my $subdir = shift;
+    my $codeblock = shift;
+    my %opts = @_;
+
+    my $reverse = __cwd($subdir,%opts);
+    BAIL_OUT("FAILURE: indir, \"$subdir\" wasn't possible to move into")
+	unless $reverse;
+
+    $codeblock->();
+
+    __cwd($reverse);
+
+    if ($opts{cleanup}) {
+	remove_tree($subdir, { safe => 0 });
+    }
+}
+
+=over 4
+
+=item B<app ARRAYREF, OPTS>
+
+=item B<test ARRAYREF, OPTS>
+
+Both of these functions take a reference to a list that is a command and
+its arguments, and some additional options (described further on).
+
+C<app> expects to find the given command (the first item in the given list
+reference) as an executable in C<$BIN_D> (if defined, otherwise C<$TOP/apps>).
+
+C<test> expects to find the given command (the first item in the given list
+reference) as an executable in C<$TEST_D> (if defined, otherwise C<$TOP/test>).
+
+Both return a CODEREF to be used by C<run>, C<pipe> or C<cmdstr>.
+
+The options that both C<app> and C<test> can take are in the form of hash
+values:
+
+=over 4
+
+=item B<stdin =E<gt> PATH>
+
+=item B<stdout =E<gt> PATH>
+
+=item B<stderr =E<gt> PATH>
+
+In all three cases, the corresponding standard input, output or error is
+redirected from (for stdin) or to (for the others) a file given by the
+string PATH, I<or>, if the value is C<undef>, C</dev/null> or similar.
+
+=back
+
+=back
+
+=cut
+
+sub app {
+    my $cmd = shift;
+    my %opts = @_;
+    return sub { my $num = shift;
+		 return __build_cmd($num, \&__apps_file, $cmd, %opts); }
+}
+
+sub test {
+    my $cmd = shift;
+    my %opts = @_;
+    return sub { my $num = shift;
+		 return __build_cmd($num, \&__test_file, $cmd, %opts); }
+}
+
+=over 4
+
+=item B<run CODEREF, OPTS>
+
+This CODEREF is expected to be the value return by C<app> or C<test>,
+anything else will most likely cause an error unless you know what you're
+doing.
+
+C<run> executes the command returned by CODEREF and return either the
+resulting output (if the option C<capture> is set true) or a boolean indicating
+if the command succeeded or not.
+
+The options that C<run> can take are in the form of hash values:
+
+=over 4
+
+=item B<capture =E<gt> 0|1>
+
+If true, the command will be executed with a perl backtick, and C<run> will
+return the resulting output as an array of lines.  If false or not given,
+the command will be executed with C<system()>, and C<run> will return 1 if
+the command was successful or 0 if it wasn't.
+
+=back
+
+For further discussion on what is considered a successful command or not, see
+the function C<with> further down.
+
+=back
+
+=cut
+
+sub run {
+    my ($cmd, $display_cmd, %errlogs) = shift->(0);
+    my %opts = @_;
+
+    return () if !$cmd;
+
+    my $prefix = "";
+    if ( $^O eq "VMS" ) {	# VMS
+	$prefix = "pipe ";
+    } elsif ($^O eq "MSWin32") { # MSYS
+	$prefix = "cmd /c ";
+    }
+
+    my @r = ();
+    my $r = 0;
+    my $e = 0;
+    if ($opts{capture}) {
+	@r = `$prefix$cmd`;
+	$e = $? >> 8;
+    } else {
+	system("$prefix$cmd");
+	$e = $? >> 8;
+	$r = $hooks{exit_checker}->($e);
+    }
+
+    # At this point, $? stops being interesting, and unfortunately,
+    # there are Test::More versions that get picky if we leave it
+    # non-zero.
+    $? = 0;
+
+    open ERR, ">>", __test_log();
+    { local $| = 1; print ERR "$display_cmd => $e\n"; }
+    foreach (keys %errlogs) {
+	copy($_,\*ERR);
+	copy($_,$errlogs{$_}) if defined($errlogs{$_});
+	unlink($_);
+    }
+    close ERR;
+
+    if ($opts{capture}) {
+	return @r;
+    } else {
+	return $r;
+    }
+}
+
+END {
+    my $tb = Test::More->builder;
+    my $failure = scalar(grep { $_ == 0; } $tb->summary);
+    if ($failure && $end_with_bailout) {
+	BAIL_OUT("Stoptest!");
+    }
+}
+
+=head2 Utility functions
+
+The following functions are exported on request when using C<OpenSSL::Test>.
+
+  # To only get the top_file function.
+  use OpenSSL::Test qw/top_file/;
+
+  # To only get the top_file function in addition to the default ones.
+  use OpenSSL::Test qw/:DEFAULT top_file/;
+
+=cut
+
+# Utility functions, exported on request
+
+=over 4
+
+=item B<top_dir LIST>
+
+LIST is a list of directories that make up a path from the top of the OpenSSL
+source directory (as indicated by the environment variable C<$TOP>).
+C<top_dir> returns the resulting directory as a string, adapted to the local
+operating system.
+
+=back
+
+=cut
+
+sub top_dir {
+    return __top_file(@_, "");	# This caters for operating systems that have
+				# a very distinct syntax for directories.
+}
+
+=over 4
+
+=item B<top_file LIST, FILENAME>
+
+LIST is a list of directories that make up a path from the top of the OpenSSL
+source directory (as indicated by the environment variable C<$TOP>) and
+FILENAME is the name of a file located in that directory path.
+C<top_file> returns the resulting file path as a string, adapted to the local
+operating system.
+
+=back
+
+=cut
+
+sub top_file {
+    return __top_file(@_);
+}
+
+=over 4
+
+=item B<pipe LIST>
+
+LIST is a list of CODEREFs returned by C<app> or C<test>, from which C<pipe>
+creates a new command composed of all the given commands put together in a
+pipe.  C<pipe> returns a new CODEREF in the same manner as C<app> or C<test>,
+to be passed to C<run> for execution.
+
+=back
+
+=cut
+
+sub pipe {
+    my @cmds = @_;
+    return
+	sub {
+	    my @cs  = ();
+	    my @dcs = ();
+	    my @els = ();
+	    my $counter = 0;
+	    foreach (@cmds) {
+		my ($c, $dc, @el) = $_->(++$counter);
+
+		return () if !$c;
+
+		push @cs, $c;
+		push @dcs, $dc;
+		push @els, @el;
+	    }
+	    return (
+		join(" | ", @cs),
+		join(" | ", @dcs),
+		@els
+		);
+    };
+}
+
+=over 4
+
+=item B<with HASHREF, CODEREF>
+
+C<with> will temporarly install hooks given by the HASHREF and then execute
+the given CODEREF.  Hooks are usually expected to have a coderef as value.
+
+The currently available hoosk are:
+
+=over 4
+
+=item B<exit_checker =E<gt> CODEREF>
+
+This hook is executed after C<run> has performed its given command.  The
+CODEREF receives the exit code as only argument and is expected to return
+1 (if the exit code indicated success) or 0 (if the exit code indicated
+failure).
+
+=back
+
+=back
+
+=cut
+
+sub with {
+    my $opts = shift;
+    my %opts = %{$opts};
+    my $codeblock = shift;
+
+    my %saved_hooks = ();
+
+    foreach (keys %opts) {
+	$saved_hooks{$_} = $hooks{$_}	if exists($hooks{$_});
+	$hooks{$_} = $opts{$_};
+    }
+
+    $codeblock->();
+
+    foreach (keys %saved_hooks) {
+	$hooks{$_} = $saved_hooks{$_};
+    }
+}
+
+=over 4
+
+=item B<cmdstr CODEREF>
+
+C<cmdstr> takes a CODEREF from C<app> or C<test> and simply returns the
+command as a string.
+
+=back
+
+=cut
+
+sub cmdstr {
+    my ($cmd, $display_cmd, %errlogs) = shift->(0);
+
+    return $display_cmd;
+}
+
+=over 4
+
+=item B<quotify LIST>
+
+LIST is a list of strings that are going to be used as arguments for a
+command, and makes sure to inject quotes and escapes as necessary depending
+on the content of each string.
+
+This can also be used to put quotes around the executable of a command.
+I<This must never ever be done on VMS.>
+
+=back
+
+=cut
+
+sub quotify {
+    # Unix setup (default if nothing else is mentioned)
+    my $arg_formatter =
+	sub { $_ = shift; /\s|[\{\}\\\$\[\]\*\?\|\&:;<>]/ ? "'$_'" : $_ };
+
+    if ( $^O eq "VMS") {	# VMS setup
+	$arg_formatter = sub {
+	    $_ = shift;
+	    if (/\s|["[:upper:]]/) {
+		s/"/""/g;
+		'"'.$_.'"';
+	    } else {
+		$_;
+	    }
+	};
+    } elsif ( $^O eq "MSWin32") { # MSWin setup
+	$arg_formatter = sub {
+	    $_ = shift;
+	    if (/\s|["\|\&\*\;<>]/) {
+		s/(["\\])/\\$1/g;
+		'"'.$_.'"';
+	    } else {
+		$_;
+	    }
+	};
+    }
+
+    return map { $arg_formatter->($_) } @_;
+}
+
+######################################################################
+# private functions.  These are never exported.
+
+=head1 ENVIRONMENT
+
+OpenSSL::Test depends on some environment variables.
+
+=over 4
+
+=item B<TOP>
+
+This environment variable is mandatory.  C<setup> will check that it's
+defined and that it's a directory that contains the file C<Configure>.
+If this isn't so, C<setup> will C<BAIL_OUT>.
+
+=item B<BIN_D>
+
+If defined, its value should be the directory where the openssl application
+is located.  Defaults to C<$TOP/apps> (adapted to the operating system).
+
+=item B<TEST_D>
+
+If defined, its value should be the directory where the test applications
+are located.  Defaults to C<$TOP/test> (adapted to the operating system).
+
+=item B<RESULT_D>
+
+If defined, its value should be the directory where the log files are
+located.  Defaults to C<$TEST_D>.
+
+=item B<STOPTEST>
+
+If defined, it puts testing in a different mode, where a recipe with
+failures will result in a C<BAIL_OUT> at the end of its run.
+
+=back
+
+=cut
+
+sub __env {
+    $directories{TOP}     = $ENV{TOP},
+    $directories{APPS}    = $ENV{BIN_D}    || catdir($directories{TOP},"apps");
+    $directories{TEST}    = $ENV{TEST_D}   || catdir($directories{TOP},"test");
+    $directories{RESULTS} = $ENV{RESULT_D} || $directories{TEST};
+
+    $end_with_bailout	  = $ENV{STOPTEST} ? 1 : 0;
+};
+
+sub __top_file {
+    BAIL_OUT("Must run setup() first") if (! $test_name);
+
+    my $f = pop;
+    return catfile($directories{TOP}, at _,$f);
+}
+
+sub __test_file {
+    BAIL_OUT("Must run setup() first") if (! $test_name);
+
+    my $f = pop;
+    return catfile($directories{TEST}, at _,$f);
+}
+
+sub __apps_file {
+    BAIL_OUT("Must run setup() first") if (! $test_name);
+
+    my $f = pop;
+    return catfile($directories{APPS}, at _,$f);
+}
+
+sub __results_file {
+    BAIL_OUT("Must run setup() first") if (! $test_name);
+
+    my $f = pop;
+    return catfile($directories{RESULTS}, at _,$f);
+}
+
+sub __test_log {
+    return __results_file("$test_name.log");
+}
+
+sub __cwd {
+    my $dir = shift;
+    my %opts = @_;
+    my $abscurdir = rel2abs(curdir());
+    my $absdir = rel2abs($dir);
+    my $reverse = abs2rel($abscurdir, $absdir);
+
+    # PARANOIA: if we're not moving anywhere, we do nothing more
+    if ($abscurdir eq $absdir) {
+	return $reverse;
+    }
+
+    # Do not support a move to a different volume for now.  Maybe later.
+    BAIL_OUT("FAILURE: \"$dir\" moves to a different volume, not supported")
+	if $reverse eq $abscurdir;
+
+    # If someone happened to give a directory that leads back to the current,
+    # it's extremely silly to do anything more, so just simulate that we did
+    # move.
+    # In this case, we won't even clean it out, for safety's sake.
+    return "." if $reverse eq "";
+
+    $dir = canonpath($dir);
+    if ($opts{create}) {
+	mkpath($dir);
+    }
+
+    # Should we just bail out here as well?  I'm unsure.
+    return undef unless chdir($dir);
+
+    if ($opts{cleanup}) {
+	remove_tree(".", { safe => 0, keep_root => 1 });
+    }
+
+    # For each of these directory variables, figure out where they are relative
+    # to the directory we want to move to if they aren't absolute (if they are,
+    # they don't change!)
+    my @dirtags = ("TOP", "TEST", "APPS", "RESULTS");
+    foreach (@dirtags) {
+	if (!file_name_is_absolute($directories{$_})) {
+	    my $newpath = abs2rel(rel2abs($directories{$_}), rel2abs($dir));
+	    $directories{$_} = $newpath;
+	}
+    }
+
+    if (0) {
+	print STDERR "DEBUG: __cwd(), directories and files:\n";
+	print STDERR "  \$directories{TEST}    = \"$directories{TEST}\"\n";
+	print STDERR "  \$directories{RESULTS} = \"$directories{RESULTS}\"\n";
+	print STDERR "  \$directories{APPS}    = \"$directories{APPS}\"\n";
+	print STDERR "  \$directories{TOP}     = \"$directories{TOP}\"\n";
+	print STDERR "  \$test_log             = \"",__test_log(),"\"\n";
+	print STDERR "\n";
+	print STDERR "  current directory is \"",curdir(),"\"\n";
+	print STDERR "  the way back is \"$reverse\"\n";
+    }
+
+    return $reverse;
+}
+
+sub __fixup_cmd {
+    my $prog = shift;
+
+    my $prefix = __top_file("util", "shlib_wrap.sh")." ";
+    my $ext = $ENV{"EXE_EXT"} || "";
+
+    if ( $^O eq "VMS" ) {	# VMS
+	$prefix = "mcr ";
+	$ext = ".exe";
+    } elsif ($^O eq "MSWin32") { # Windows
+	$prefix = "";
+	$ext = ".exe";
+    }
+
+    # We test both with and without extension.  The reason
+    # is that we might, for example, be passed a Perl script
+    # ending with .pl...
+    my $file = "$prog$ext";
+    if ( -x $file ) {
+	return $prefix.$file;
+    } elsif ( -f $prog ) {
+	return $prog;
+    }
+
+    print STDERR "$prog not found\n";
+    return undef;
+}
+
+sub __build_cmd {
+    BAIL_OUT("Must run setup() first") if (! $test_name);
+
+    my $num = shift;
+    my $path_builder = shift;
+    # Make a copy to not destroy the caller's array
+    my @cmdarray = ( @{$_[0]} ); shift;
+    my $cmd = __fixup_cmd($path_builder->(shift @cmdarray));
+    my @args = @cmdarray;
+    my %opts = @_;
+
+    return () if !$cmd;
+
+    my $arg_str = "";
+    my $null = devnull();
+
+
+    $arg_str = " ".join(" ", quotify @args) if @args;
+
+    my $fileornull = sub { $_[0] ? $_[0] : $null; };
+    my $stdin = "";
+    my $stdout = "";
+    my $stderr = "";
+    my $saved_stderr = undef;
+    $stdin = " < ".$fileornull->($opts{stdin})  if exists($opts{stdin});
+    $stdout= " > ".$fileornull->($opts{stdout}) if exists($opts{stdout});
+    $stderr=" 2> ".$fileornull->($opts{stderr}) if exists($opts{stderr});
+
+    $saved_stderr = $opts{stderr}		if defined($opts{stderr});
+
+    my $errlog = $num ? "$test_name.$num.tmp_err" : "$test_name.tmp_err";
+    my $display_cmd = "$cmd$arg_str$stdin$stdout$stderr";
+    $cmd .= "$arg_str$stdin$stdout 2> $errlog";
+
+    return ($cmd, $display_cmd, $errlog => $saved_stderr);
+}
+
+=head1 SEE ALSO
+
+L<Test::More>, L<Test::Harness>
+
+=head1 AUTHORS
+
+Richard Levitte E<lt>levitte at openssl.orgE<gt> with assitance and
+inspiration from Andy Polyakov E<lt>appro at openssl.org<gt>.
+
+=cut
+
+1;
diff --git a/test/testlib/OpenSSL/Test/Simple.pm b/test/testlib/OpenSSL/Test/Simple.pm
new file mode 100644
index 0000000..874a156
--- /dev/null
+++ b/test/testlib/OpenSSL/Test/Simple.pm
@@ -0,0 +1,78 @@
+package OpenSSL::Test::Simple;
+
+use strict;
+use warnings;
+
+use Exporter;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+$VERSION = "0.2";
+ at ISA = qw(Exporter);
+ at EXPORT = qw(simple_test);
+
+=head1 NAME
+
+OpenSSL::Test::Simple - a few very simple test functions
+
+=head1 SYNOPSIS
+
+  use OpenSSL::Test::Simple;
+
+  simple_test("my_test_name", "des", "destest");
+
+=head1 DESCRIPTION
+
+Sometimes, the functions in L<OpenSSL::Test> are quite tedious for some
+repetitive tasks.  This module provides functions to make life easier.
+You could call them hacks if you wish.
+
+=cut
+
+use OpenSSL::Test;
+
+=over 4
+
+=item B<simple_test NAME, PROGRAM, ALGORITHM>
+
+Runs a test named NAME, running the program PROGRAM with no arguments,
+to test the algorithm ALGORITHM.
+
+A complete recipe looks like this:
+
+  use OpenSSL::Test::Simple;
+
+  simple_test("test_bf", "bftest", "bf");
+
+=back
+
+=cut
+
+# args:
+#  name			(used with setup())
+#  algorithm		(used to check if it's at all supported)
+#  name of binary	(the program that does the actual test)
+sub simple_test {
+    my ($name, $prgr, $algo, @rest) = @_;
+
+    setup($name);
+
+    plan tests => 1;
+  SKIP: {
+      skip "$algo is not supported by this OpenSSL build, skipping this test...", 1
+	  if $algo && run(app(["openssl", "no-$algo"]));
+
+      ok(run(test([$prgr])), "running $prgr");
+    }
+}
+
+=head1 SEE ALSO
+
+L<OpenSSL::Test>
+
+=head1 AUTHORS
+
+Richard Levitte E<lt>levitte at openssl.orgE<gt> with inspiration
+from Rich Salz E<lt>rsalz at openssl.org<gt>.
+
+=cut
+
+1;
diff --git a/util/mk1mf.pl b/util/mk1mf.pl
index 6091a69..9d8a47d 100755
--- a/util/mk1mf.pl
+++ b/util/mk1mf.pl
@@ -752,7 +752,9 @@ headers: \$(HEADER)
 
 lib: \$(LIBS_DEP) \$(E_SHLIB)
 
-exe: \$(T_EXE) \$(BIN_D)$o\$(E_EXE)$exep
+exe: apps testapps
+apps: \$(BIN_D)$o\$(E_EXE)$exep
+testapps: \$(T_EXE)
 
 install: all
 	\$(MKDIR) \"\$(INSTALLTOP)\"
@@ -777,15 +779,8 @@ reallyclean:
 
 EOF
 
-if ($orig_platform ne 'copy')
-	{
-        $rules .= <<"EOF";
-test: \$(T_EXE)
-	cd \$(BIN_D)
-	..${o}ms${o}test
-
-EOF
-	}
+$rules .= &do_rehash_rule("rehash", "certs apps");
+$rules .= &do_test_rule("test", "rehash", "run_tests.pl");
 
 my $platform_cpp_symbol = "MK1MF_PLATFORM_$platform";
 $platform_cpp_symbol =~ s/-/_/g;
@@ -1004,8 +999,6 @@ if ($fips)
 
 $rules.=&do_link_rule("\$(BIN_D)$o\$(E_EXE)$exep","\$(E_OBJ)","\$(LIBS_DEP)","\$(L_LIBS) \$(EX_LIBS)", ($fips && !$shlib) ? 2 : 0);
 
-$rules .= get_tests('test/Makefile') if $orig_platform eq 'copy';
-
 print $defs;
 
 if ($platform eq "linux-elf") {
diff --git a/util/pl/BC-32.pl b/util/pl/BC-32.pl
index fd5c4b6..3b2b854 100644
--- a/util/pl/BC-32.pl
+++ b/util/pl/BC-32.pl
@@ -94,6 +94,29 @@ if ($shlib)
 	$tmp_def="tmp32dll";
 	}
 
+sub do_rehash_rule {
+    my ($target, $deps) = @_;
+    my $ret = <<"EOF";
+$target: $deps
+	set OPENSSL=\$(BIN_D)${o}openssl.exe
+	set OPENSSL_DEBUG_MEMORY=on
+	\$(PERL) tools/c_rehash certs/demo
+EOF
+    return $ret
+}
+sub do_test_rule {
+    my ($target, $deps, $test_cmd) = @_;
+    my $ret = <<"EOF";
+$target: $deps force.$target
+	set TOP=.
+	set BIN_D=\$(BIN_D)
+	set TEST_D=\$(TEST_D)
+	set PERL=\$(PERL)
+	\$(PERL) test\\$test_cmd
+force.$target:
+EOF
+}
+
 sub do_lib_rule
 	{
 	local($objs,$target,$name,$shlib)=@_;
diff --git a/util/pl/VC-32.pl b/util/pl/VC-32.pl
index bf6aebf..a2d35c6 100644
--- a/util/pl/VC-32.pl
+++ b/util/pl/VC-32.pl
@@ -300,6 +300,29 @@ elsif ($shlib && $FLAVOR =~ /CE/)
 	$lib_cflag.=" -D_DLL" if (!$fipscanisterbuild);
 	}
 
+sub do_rehash_rule {
+    my ($target, $deps) = @_;
+    my $ret = <<"EOF";
+$target: $deps
+	set OPENSSL=\$(BIN_D)${o}openssl.exe
+	set OPENSSL_DEBUG_MEMORY=on
+	\$(PERL) tools/c_rehash certs/demo
+EOF
+    return $ret
+}
+sub do_test_rule {
+    my ($target, $deps, $test_cmd) = @_;
+    my $ret = <<"EOF";
+$target: $deps force.$target
+	set TOP=.
+	set BIN_D=\$(BIN_D)
+	set TEST_D=\$(TEST_D)
+	set PERL=\$(PERL)
+	\$(PERL) test\\$test_cmd
+force.$target:
+EOF
+}
+
 sub do_lib_rule
 	{
 	my($objs,$target,$name,$shlib,$ign,$base_addr) = @_;
diff --git a/util/pl/unix.pl b/util/pl/unix.pl
index 40bbe0d..528d4d0 100644
--- a/util/pl/unix.pl
+++ b/util/pl/unix.pl
@@ -186,267 +186,28 @@ sub which
 		}
 	}
 
-sub fixtests
-  {
-  my ($str, $tests) = @_;
-
-  foreach my $t (keys %$tests)
-    {
-    $str =~ s/(\.\/)?\$\($t\)/\$(TEST_D)\/$tests->{$t}/g;
-    }
-
-  return $str;
-  }
-
-sub fixdeps
-  {
-  my ($str, $fakes) = @_;
-
-  my @t = split(/\s+/, $str);
-  $str = '';
-  foreach my $t (@t)
-    {
-    $str .= ' ' if $str ne '';
-    if (exists($fakes->{$t}))
-      {
-      $str .= $fakes->{$t};
-      next;
-      }
-    if ($t =~ /^[^\/]+$/)
-      {
-      $str .= '$(TEST_D)/' . $t;
-      }
-    else
-      {
-      $str .= $t;
-      }
-    }
-
-  return $str;
-  }
-
-sub fixrules
-  {
-  my ($str) = @_;
-
-  # Compatible with -j...
-#  $str =~ s/^(\s+@?)/$1cd \$(TEST_D) && /;
-#  return $str;
-
-  # Compatible with not -j.
-  my @t = split("\n", $str);
-  $str = '';
-  my $prev;
-  foreach my $t (@t)
-    {
-    $t =~ s/^\s+//;
-    if (!$prev)
-      {
-      if ($t =~ /^@/)
-        {
-        $t =~ s/^@/\@cd \$(TEST_D) && /;
-        }
-      elsif ($t !~ /^\s*#/ && $t !~ /^echo/)
-        {
-        $t = 'cd $(TEST_D) && ' . $t;
-        }
-      }
-    $str .= "\t$t\n";
-    $prev = $t =~/\\$/;
-    }
-  return $str;
+sub do_rehash_rule {
+    my ($target, $deps) = @_;
+    my $ret = <<"EOF";
+$target: $deps
+	(OPENSSL="`pwd`/util/opensslwrap.sh"; \\
+	OPENSSL_DEBUG_MEMORY=on; \\
+	export OPENSSL OPENSSL_DEBUG_MEMORY; \\
+	\$(PERL) tools/c_rehash certs/demo)
+EOF
+    return $ret
 }
+sub do_test_rule {
+    my ($target, $deps, $test_cmd) = @_;
+    my $ret = <<"EOF";
+$target: $deps force.$target
+	TOP=. BIN_D=\$(BIN_D) TEST_D=\$(TEST_D) \\
+	    PERL=\$(PERL) \$(PERL) test/$test_cmd
+force.$target:
 
-sub copy_scripts
-  {
-  my ($sed, $src, @targets) = @_;
-
-  my $s = '';
-  foreach my $t (@targets)
-    {
-    # Copy first so we get file modes...
-    $s .= "\$(TEST_D)/$t: \$(SRC_D)/$src/$t\n\tcp \$(SRC_D)/$src/$t \$(TEST_D)/$t\n";
-    $s .= "\tsed -e 's/\\.\\.\\/apps/..\\/\$(OUT_D)/' -e 's/\\.\\.\\/util/..\\/\$(TEST_D)/' < \$(SRC_D)/$src/$t > \$(TEST_D)/$t\n" if $sed;
-    $s .= "\n";
-    }
-  return $s;
-  }
-
-sub get_tests
-  {
-  my ($makefile) = @_;
-
-  open(M, $makefile) || die "Can't open $makefile: $!";
-  my %targets;
-  my %deps;
-  my %tests;
-  my %alltests;
-  my %fakes;
-  while (my $line = <M>)
-    {
-    chomp $line;
-    while ($line =~ /^(.*)\\$/)
-      {
-      $line = $1 . <M>;
-      }
-
-    if ($line =~ /^alltests:(.*)$/)
-      {
-      my @t = split(/\s+/, $1);
-      foreach my $t (@t)
-	{
-	$targets{$t} = '';
-	$alltests{$t} = undef;
-        }
-      }
-
-    if (($line =~ /^(?<t>\S+):(?<d>.*)$/ && exists $targets{$1})
-	|| $line =~ /^(?<t>test_(ss|gen) .*):(?<d>.*)/)
-      {
-      my $t = $+{t};
-      my $d = $+{d};
-      # If there are multiple targets stupid FreeBSD make runs the
-      # rules once for each dependency that matches one of the
-      # targets. Running the same rule twice concurrently causes
-      # breakage, so replace with a fake target.
-      if ($t =~ /\s/)
-        {
-	++$fake;
-	my @targets = split /\s+/, $t;
-	$t = "_fake$fake";
-	foreach my $f (@targets)
-	  {
-	  $fakes{$f} = $t;
-	  }
-	}
-      $deps{$t} = $d;
-      $deps{$t} =~ s/#.*$//;
-      for (;;)
-	{
-	$line = <M>;
-	chomp $line;
-	last if $line eq '';
-	$targets{$t} .= "$line\n";
-        }
-      next;
-      }
-
-    if ($line =~ /^(\S+TEST)=\s*(\S+)$/)
-      {
-      $tests{$1} = $2;
-      next;
-      }
-    }
-
-  delete $alltests{test_jpake} if $no_jpake;
-  delete $targets{test_ige} if $no_ige;
-  delete $alltests{test_md2} if $no_md2;
-  delete $alltests{test_rc5} if $no_rc5;
-
-  my $tests;
-  foreach my $t (keys %tests)
-    {
-    $tests .= "$t = $tests{$t}\n";
-    }
-
-  my $each;
-  foreach my $t (keys %targets)
-    {
-    next if $t eq '';
-
-    my $d = $deps{$t};
-    $d =~ s/\.\.\/apps/\$(BIN_D)/g;
-    $d =~ s/\.\.\/util/\$(TEST_D)/g;
-    $d = fixtests($d, \%tests);
-    $d = fixdeps($d, \%fakes);
-
-    my $r = $targets{$t};
-    $r =~ s/\.\.\/apps/..\/\$(BIN_D)/g;
-    $r =~ s/\.\.\/util/..\/\$(TEST_D)/g;
-    $r =~ s/\.\.\/(\S+)/\$(SRC_D)\/$1/g;
-    $r = fixrules($r);
-
-    next if $r eq '';
-
-    $t =~ s/\s+/ \$(TEST_D)\//g;
-
-    $each .= "$t: test_scripts $d\n\t\@echo '$t test started'\n$r\t\@echo '$t test done'\n\n";
-    }
-
-  # FIXME: Might be a clever way to figure out what needs copying
-  my @copies = ( 'bctest',
-		 'testgen',
-		 'cms-test.pl',
-		 'tx509',
-		 'test.cnf',
-		 'testenc',
-		 'tocsp',
-		 'testca',
-		 'CAss.cnf',
-		 'testtsa',
-		 'CAtsa.cnf',
-		 'Uss.cnf',
-		 'P1ss.cnf',
-		 'P2ss.cnf',
-		 'tcrl',
-		 'tsid',
-		 'treq',
-		 'tpkcs7',
-		 'tpkcs7d',
-		 'tkey',
-		 'testcrl.pem',
-		 'testx509.pem',
-		 'v3-cert1.pem',
-		 'v3-cert2.pem',
-		 'testreq2.pem',
-		 'testp7.pem',
-		 'pkcs7-1.pem',
-		 'trsa',
-		 'testdsa.pem',
-		 'testdsapub.pem',
-		 'testec-p256.pem',
-		 'testecpub-p256.pem',
-		 'testrsa.pem',
-		 'testrsapub.pem',
-		 'testsid.pem',
-		 'testss',
-		 'testssl',
-		 'testsslproxy',
-		 'serverinfo.pem',
-	       );
-  my $copies = copy_scripts(1, 'test', @copies);
-  $copies .= copy_scripts(0, 'test', ('smcont.txt', 'evptests.txt'));
-
-
-  my @utils = ( 'shlib_wrap.sh',
-		'opensslwrap.sh',
-	      );
-  $copies .= copy_scripts(1, 'util', @utils);
-
-  my @apps = ( 'CA.pl',
-	       'openssl.cnf',
-	       'server2.pem',
-	     );
-  $copies .= copy_scripts(1, 'apps', @apps);
-
-  $scripts = "test_scripts: \$(TEST_D)/CA.pl \$(TEST_D)/opensslwrap.sh \$(TEST_D)/openssl.cnf \$(TEST_D)/shlib_wrap.sh ocsp smime\n";
-  $scripts .= "\nocsp:\n\tcp -R test/ocsp-tests \$(TEST_D)\n";
-  $scripts .= "\smime:\n\tcp -R test/smime-certs \$(TEST_D)\n";
-
-  my $all = 'test:';
-  foreach my $t (keys %alltests)
-    {
-    if (exists($fakes{$t}))
-      {
-      $all .= " $fakes{$t}";
-      }
-    else
-      {
-      $all .= " $t";
-      }
-    }
+EOF
+    return $ret;
+}
 
-  return "$scripts\n$copies\n$tests\n$all\n\n$each";
-  }
 
 1;


More information about the openssl-commits mailing list