Add fips_algvs utility (from FIPS 2.0 stable branch).
diff --git a/CHANGES b/CHANGES
index 0d70e03..4159394 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,10 @@
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
+  *) Add fips_algvs: a multicall fips utility incorporaing all the algorithm
+     test programs and fips_test_suite. Includes functionality to parse
+     the minimal script output of fipsalgest.pl directly.
+
   *) Add authorisation parameter to FIPS_module_mode_set().
      [Steve Henson]
 
diff --git a/Makefile.fips b/Makefile.fips
index 703c9f9..36e9a7d 100644
--- a/Makefile.fips
+++ b/Makefile.fips
@@ -387,6 +387,8 @@
 	@dir=apps; target=all; $(BUILD_ONE_CMD)
 build_tests:
 	@dir=test; target=fipsexe; $(BUILD_ONE_CMD)
+build_algvs:
+	@dir=test; target=fipsalgvs; $(BUILD_ONE_CMD)
 build_tools:
 	@dir=tools; target=all; $(BUILD_ONE_CMD)
 
diff --git a/fips/aes/fips_aesavs.c b/fips/aes/fips_aesavs.c
index 84bcbac..9a09964 100644
--- a/fips/aes/fips_aesavs.c
+++ b/fips/aes/fips_aesavs.c
@@ -780,7 +780,7 @@
 		    if(do_mct(amode, akeysz, aKey, iVec, 
 			      dir, (unsigned char*)plaintext, len, 
 			      rfp) < 0)
-			EXIT(1);
+			err = 1;
 		    }
 		else
 		    {
@@ -862,7 +862,11 @@
     aes_test -d xxxxx.xxx
   The default is: -d req.txt
 --------------------------------------------------*/
+#ifdef FIPS_ALGVS
+int fips_aesavs_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
     {
     char *rqlist = "req.txt", *rspfile = NULL;
     FILE *fp = NULL;
@@ -915,7 +919,7 @@
 	    if (proc_file(rfn, rspfile))
 		{
 		printf(">>> Processing failed for: %s <<<\n", rfn);
-		EXIT(1);
+		return 1;
 		}
 	    }
 	fclose(fp);
@@ -929,7 +933,6 @@
 	    printf(">>> Processing failed for: %s <<<\n", fn);
 	    }
 	}
-    EXIT(0);
     return 0;
     }
 
diff --git a/fips/aes/fips_gcmtest.c b/fips/aes/fips_gcmtest.c
index 3839de8..a7c7873 100644
--- a/fips/aes/fips_gcmtest.c
+++ b/fips/aes/fips_gcmtest.c
@@ -496,7 +496,11 @@
 	FIPS_cipher_ctx_cleanup(&ctx);
 	}
 
-int main(int argc,char **argv)
+#ifdef FIPS_ALGVS
+int fips_gcmtest_main(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
 	{
 	int encrypt;
 	int xts = 0, ccm = 0;
diff --git a/fips/cmac/fips_cmactest.c b/fips/cmac/fips_cmactest.c
index 6d799f2..2c8c766 100644
--- a/fips/cmac/fips_cmactest.c
+++ b/fips/cmac/fips_cmactest.c
@@ -92,7 +92,11 @@
 		unsigned char *Mac, int Maclen,
 		int Tlen);
 
+#ifdef FIPS_ALGVS
+int fips_cmactest_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 	{
 	FILE *in = NULL, *out = NULL;
 	int mode = 0;		/* 0 => Generate, 1 => Verify */
diff --git a/fips/des/fips_desmovs.c b/fips/des/fips_desmovs.c
index e876656..29035f0 100644
--- a/fips/des/fips_desmovs.c
+++ b/fips/des/fips_desmovs.c
@@ -102,7 +102,7 @@
     if (akeysz != 192)
 	{
 	printf("Invalid key size: %d\n", akeysz);
-	EXIT(1);
+	return 0;
 	}
 
     if (fips_strcasecmp(amode, "CBC") == 0)
@@ -120,7 +120,7 @@
     else
 	{
 	printf("Unknown mode: %s\n", amode);
-	EXIT(1);
+	return 0;
 	}
 
     if (FIPS_cipherinit(ctx, cipher, aKey, iVec, dir) <= 0)
@@ -155,12 +155,12 @@
     }	
 
 /*-----------------------------------------------*/
-char *t_tag[2] = {"PLAINTEXT", "CIPHERTEXT"};
-char *t_mode[6] = {"CBC","ECB","OFB","CFB1","CFB8","CFB64"};
-enum Mode {CBC, ECB, OFB, CFB1, CFB8, CFB64};
+char *tdes_t_tag[2] = {"PLAINTEXT", "CIPHERTEXT"};
+char *tdes_t_mode[6] = {"CBC","ECB","OFB","CFB1","CFB8","CFB64"};
+enum tdes_Mode {TCBC, TECB, TOFB, TCFB1, TCFB8, TCFB64};
 int Sizes[6]={64,64,64,1,8,64};
 
-static void do_mct(char *amode, 
+static int do_tmct(char *amode, 
 	    int akeysz, int numkeys, unsigned char *akey,unsigned char *ivec,
 	    int dir, unsigned char *text, int len,
 	    FILE *rfp)
@@ -170,12 +170,12 @@
     unsigned char text0[8];
 
     for (imode=0 ; imode < 6 ; ++imode)
-	if(!strcmp(amode,t_mode[imode]))
+	if(!strcmp(amode,tdes_t_mode[imode]))
 	    break;
     if (imode == 6)
 	{ 
 	printf("Unrecognized mode: %s\n", amode);
-	EXIT(1);
+	return 0;
 	}
     for(i=0 ; i < 400 ; ++i)
 	{
@@ -196,12 +196,12 @@
 		OutputValue("",akey+n*8,8,rfp,0);
 		}
 
-	if(imode != ECB)
+	if(imode != TECB)
 	    OutputValue("IV",ivec,8,rfp,0);
-	OutputValue(t_tag[dir^1],text,len,rfp,imode == CFB1);
+	OutputValue(tdes_t_tag[dir^1],text,len,rfp,imode == TCFB1);
 #if 0
 	/* compensate for endianness */
-	if(imode == CFB1)
+	if(imode == TCFB1)
 	    text[0]<<=7;
 #endif
 	memcpy(text0,text,8);
@@ -223,18 +223,18 @@
 		}
 	    if(j == 9999)
 		{
-		OutputValue(t_tag[dir],text,len,rfp,imode == CFB1);
+		OutputValue(tdes_t_tag[dir],text,len,rfp,imode == TCFB1);
 		/*		memcpy(ivec,text,8); */
 		}
 	    /*	    DebugValue("iv",ctx.iv,8); */
 	    /* accumulate material for the next key */
 	    shiftin(nk,text,Sizes[imode]);
 	    /*	    DebugValue("nk",nk,24);*/
-	    if((dir && (imode == CFB1 || imode == CFB8 || imode == CFB64
-			|| imode == CBC)) || imode == OFB)
+	    if((dir && (imode == TCFB1 || imode == TCFB8
+			|| imode == TCFB64 || imode == TCBC)) || imode == TOFB)
 		memcpy(text,old_iv,8);
 
-	    if(!dir && (imode == CFB1 || imode == CFB8 || imode == CFB64))
+	    if(!dir && (imode == TCFB1 || imode == TCFB8 || imode == TCFB64))
 		{
 		/* the test specifies using the output of the raw DES operation
 		   which we don't have, so reconstruct it... */
@@ -260,13 +260,14 @@
 	/* pointless exercise - the final text doesn't depend on the
 	   initial text in OFB mode, so who cares what it is? (Who
 	   designed these tests?) */
-	if(imode == OFB)
+	if(imode == TOFB)
 	    for(n=0 ; n < 8 ; ++n)
 		text[n]=text0[n]^old_iv[n];
 	}
+    return 1;
     }
     
-static int proc_file(char *rqfile, char *rspfile)
+static int tproc_file(char *rqfile, char *rspfile)
     {
     char afn[256], rfn[256];
     FILE *afp = NULL, *rfp = NULL;
@@ -546,7 +547,9 @@
 		PrintValue("PLAINTEXT", (unsigned char*)plaintext, len);
 		if (strcmp(atest, "Monte") == 0)  /* Monte Carlo Test */
 		    {
-		    do_mct(amode,akeysz,numkeys,aKey,iVec,dir,plaintext,len,rfp);
+		    if (!do_tmct(amode,akeysz,numkeys,aKey,iVec,
+					dir,plaintext,len,rfp))
+			return -1;
 		    }
 		else
 		    {
@@ -585,7 +588,7 @@
 		PrintValue("CIPHERTEXT", ciphertext, len);
 		if (strcmp(atest, "Monte") == 0)  /* Monte Carlo Test */
 		    {
-		    do_mct(amode, akeysz, numkeys, aKey, iVec, 
+		    do_tmct(amode, akeysz, numkeys, aKey, iVec, 
 			   dir, ciphertext, len, rfp);
 		    }
 		else
@@ -631,7 +634,11 @@
     aes_test -d xxxxx.xxx
   The default is: -d req.txt
 --------------------------------------------------*/
+#ifdef FIPS_ALGVS
+int fips_desmovs_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
     {
     char *rqlist = "req.txt", *rspfile = NULL;
     FILE *fp = NULL;
@@ -680,10 +687,10 @@
 	    strtok(fn, "\r\n");
 	    strcpy(rfn, fn);
 	    printf("Processing: %s\n", rfn);
-	    if (proc_file(rfn, rspfile))
+	    if (tproc_file(rfn, rspfile))
 		{
 		printf(">>> Processing failed for: %s <<<\n", rfn);
-		EXIT(1);
+		return -1;
 		}
 	    }
 	fclose(fp);
@@ -692,12 +699,11 @@
 	{
 	if (VERBOSE)
 		printf("Processing: %s\n", fn);
-	if (proc_file(fn, rspfile))
+	if (tproc_file(fn, rspfile))
 	    {
 	    printf(">>> Processing failed for: %s <<<\n", fn);
 	    }
 	}
-    EXIT(0);
     return 0;
     }
 
diff --git a/fips/dh/fips_dhvs.c b/fips/dh/fips_dhvs.c
index ad760c8..3ba1977 100644
--- a/fips/dh/fips_dhvs.c
+++ b/fips/dh/fips_dhvs.c
@@ -145,8 +145,12 @@
 	OPENSSL_cleanse(Z, Zlen);
 	OPENSSL_free(Z);
 	}
-		
-int main(int argc,char **argv)
+
+#ifdef FIPS_ALGVS
+int fips_dhvs_main(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
 	{
 	char **args = argv + 1;
 	int argn = argc - 1;
diff --git a/fips/dsa/fips_dssvs.c b/fips/dsa/fips_dssvs.c
index 45bca7c..706babf 100644
--- a/fips/dsa/fips_dssvs.c
+++ b/fips/dsa/fips_dssvs.c
@@ -717,7 +717,11 @@
 	}
     }
 
-int main(int argc,char **argv)
+#ifdef FIPS_ALGVS
+int fips_dssvs_main(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
     {
     FILE *in, *out;
     if (argc == 4)
diff --git a/fips/ecdh/fips_ecdhvs.c b/fips/ecdh/fips_ecdhvs.c
index 72ebe81..821821a 100644
--- a/fips/ecdh/fips_ecdhvs.c
+++ b/fips/ecdh/fips_ecdhvs.c
@@ -76,7 +76,7 @@
 
 #include "fips_utl.h"
 
-static const EVP_MD *parse_md(char *line)
+static const EVP_MD *eparse_md(char *line)
 	{
 	char *p;
 	if (line[0] != '[' || line[1] != 'E')
@@ -301,7 +301,11 @@
 	EC_POINT_free(peerkey);
 	}
 		
-int main(int argc,char **argv)
+#ifdef FIPS_ALGVS
+int fips_ecdhvs_main(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
 	{
 	char **args = argv + 1;
 	int argn = argc - 1;
@@ -412,7 +416,7 @@
 
 		if (strlen(buf) > 6 && !strncmp(buf, "[E", 2))
 			{
-			md = parse_md(buf);
+			md = eparse_md(buf);
 			if (md == NULL)
 				goto parse_error;
 			continue;
diff --git a/fips/ecdsa/fips_ecdsavs.c b/fips/ecdsa/fips_ecdsavs.c
index 898951a..50b1b7c 100644
--- a/fips/ecdsa/fips_ecdsavs.c
+++ b/fips/ecdsa/fips_ecdsavs.c
@@ -75,7 +75,7 @@
 #include <openssl/objects.h>
 
 
-static int lookup_curve(char *in, char *curve_name, const EVP_MD **pmd)
+static int elookup_curve(char *in, char *curve_name, const EVP_MD **pmd)
 	{
 	char *cname, *p;
 	/* Copy buffer as we will change it */
@@ -200,7 +200,7 @@
 		if (*buf == '[' && buf[2] == '-')
 			{
 			if (buf[2] == '-')
-			curve_nid = lookup_curve(buf, lbuf, NULL);
+			curve_nid = elookup_curve(buf, lbuf, NULL);
 			fputs(buf, out);
 			continue;
 			}
@@ -260,7 +260,7 @@
 		fputs(buf, out);
 		if (*buf == '[' && buf[2] == '-')
 			{
-			curve_nid = lookup_curve(buf, lbuf, NULL);
+			curve_nid = elookup_curve(buf, lbuf, NULL);
 			if (curve_nid == NID_undef)
 				return 0;
 				
@@ -314,7 +314,7 @@
 		fputs(buf, out);
 		if (*buf == '[')
 			{
-			curve_nid = lookup_curve(buf, lbuf, &digest);
+			curve_nid = elookup_curve(buf, lbuf, &digest);
 			if (curve_nid == NID_undef)
 				return 0;
 			}
@@ -390,7 +390,7 @@
 		fputs(buf, out);
 		if (*buf == '[')
 			{
-			curve_nid = lookup_curve(buf, lbuf, &digest);
+			curve_nid = elookup_curve(buf, lbuf, &digest);
 			if (curve_nid == NID_undef)
 				return 0;
 			}
@@ -459,8 +459,11 @@
 		}
 	return 1;
 	}
-
+#ifdef FIPS_ALGVS
+int fips_ecdsavs_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 	{
 	FILE *in = NULL, *out = NULL;
 	const char *cmd = argv[1];
diff --git a/fips/fips_test_suite.c b/fips/fips_test_suite.c
index b7aea4e..1344b11 100644
--- a/fips/fips_test_suite.c
+++ b/fips/fips_test_suite.c
@@ -995,7 +995,11 @@
 	return 1;
 	}
 
-int main(int argc,char **argv)
+#ifdef FIPS_ALGVS
+int fips_test_suite_main(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
     {
     int bad_rsa = 0, bad_dsa = 0;
     int do_rng_stick = 0;
@@ -1088,16 +1092,16 @@
 		pass = "";
         } else {
             printf("Bad argument \"%s\"\n", argv[1]);
-            exit(1);
+            return 1;
         }
 	if (!no_exit) {
     		fips_algtest_init_nofips();
         	if (!FIPS_module_mode_set(1, pass)) {
         	    printf("Power-up self test failed\n");
-		    exit(1);
+		    return 1;
 		}
         	printf("Power-up self test successful\n");
-        	exit(0);
+        	return 0;
 	}
     }
 
@@ -1116,7 +1120,7 @@
     ERR_clear_error();
     test_msg("2. Automatic power-up self test", FIPS_module_mode_set(1, pass));
     if (!FIPS_module_mode())
-	exit(1);
+	return 1;
     if (do_drbg_stick)
             FIPS_drbg_stick();
     if (do_rng_stick)
diff --git a/fips/fips_utl.h b/fips/fips_utl.h
index 1ed133c..491bc2a 100644
--- a/fips/fips_utl.h
+++ b/fips/fips_utl.h
@@ -47,6 +47,9 @@
  *
  */
 
+#ifndef FIPS_UTL_H
+#define FIPS_UTL_H
+
 #define OPENSSL_FIPSAPI
 
 #include <openssl/fips_rand.h>
@@ -487,3 +490,5 @@
 	return fips_strncasecmp(str1, str2, (size_t)-1);
 	}
 
+
+#endif
diff --git a/fips/hmac/fips_hmactest.c b/fips/hmac/fips_hmactest.c
index 07c18bf..da9c8d7 100644
--- a/fips/hmac/fips_hmactest.c
+++ b/fips/hmac/fips_hmactest.c
@@ -85,7 +85,11 @@
 		unsigned char *Key, int Klen,
 		unsigned char *Msg, int Msglen, int Tlen);
 
+#ifdef FIPS_ALGVS
+int fips_hmactest_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 	{
 	FILE *in = NULL, *out = NULL;
 
diff --git a/fips/rand/fips_drbgvs.c b/fips/rand/fips_drbgvs.c
index 4d3f0cf..bcdfa6d 100644
--- a/fips/rand/fips_drbgvs.c
+++ b/fips/rand/fips_drbgvs.c
@@ -76,7 +76,7 @@
 
 #include "fips_utl.h"
 
-static int parse_md(char *str)
+static int dparse_md(char *str)
 	{
 	switch(atoi(str + 5))
 		{
@@ -115,7 +115,7 @@
 		curve_nid = NID_secp521r1;
 	else
 		return NID_undef;
-	md_nid = parse_md(md);
+	md_nid = dparse_md(md);
 	if (md_nid == NID_undef)
 		return NID_undef;
 	return (curve_nid << 16) | md_nid;
@@ -170,9 +170,11 @@
 	return t->noncelen;
 	}
 
-
-
+#ifdef FIPS_ALGVS
+int fips_drbgvs_main(int argc,char **argv)
+#else
 int main(int argc,char **argv)
+#endif
 	{
 	FILE *in, *out;
 	DRBG_CTX *dctx = NULL;
@@ -240,7 +242,7 @@
 			}
 		if (strlen(buf) > 4 && !strncmp(buf, "[SHA-", 5))
 			{
-			nid = parse_md(buf);
+			nid = dparse_md(buf);
 			if (nid == NID_undef)
 				exit(1);
 			if (drbg_type == DRBG_HMAC)
diff --git a/fips/rand/fips_rngvs.c b/fips/rand/fips_rngvs.c
index ac0a526..9e1f070 100644
--- a/fips/rand/fips_rngvs.c
+++ b/fips/rand/fips_rngvs.c
@@ -198,7 +198,11 @@
 	}
     }
 
-int main(int argc,char **argv)
+#ifdef FIPS_ALGVS
+int fips_rngvs_main(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
     {
     FILE *in, *out;
     if (argc == 4)
diff --git a/fips/rsa/fips_rsagtest.c b/fips/rsa/fips_rsagtest.c
index 78b4531..8342f61 100644
--- a/fips/rsa/fips_rsagtest.c
+++ b/fips/rsa/fips_rsagtest.c
@@ -88,7 +88,11 @@
 static int rsa_printkey2(FILE *out, RSA *rsa,
 		BIGNUM *Xq1, BIGNUM *Xq2, BIGNUM *Xq);
 
+#ifdef FIPS_ALGVS
+int fips_rsagtest_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 	{
 	FILE *in = NULL, *out = NULL;
 
diff --git a/fips/rsa/fips_rsastest.c b/fips/rsa/fips_rsastest.c
index e0dbe2a..d11b063 100644
--- a/fips/rsa/fips_rsastest.c
+++ b/fips/rsa/fips_rsastest.c
@@ -85,7 +85,11 @@
 static int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst,
 		unsigned char *Msg, long Msglen, int Saltlen);
 
+#ifdef FIPS_ALGVS
+int fips_rsastest_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 	{
 	FILE *in = NULL, *out = NULL;
 
diff --git a/fips/rsa/fips_rsavtest.c b/fips/rsa/fips_rsavtest.c
index df33842..7685c74 100644
--- a/fips/rsa/fips_rsavtest.c
+++ b/fips/rsa/fips_rsavtest.c
@@ -82,14 +82,18 @@
 
 #include "fips_utl.h"
 
-int rsa_test(FILE *out, FILE *in, int saltlen);
+int rsa_vtest(FILE *out, FILE *in, int saltlen);
 static int rsa_printver(FILE *out,
 		BIGNUM *n, BIGNUM *e,
 		const EVP_MD *dgst,
 		unsigned char *Msg, long Msglen,
 		unsigned char *S, long Slen, int Saltlen);
 
+#ifdef FIPS_ALGVS
+int fips_rsavtest_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 	{
 	FILE *in = NULL, *out = NULL;
 
@@ -138,7 +142,7 @@
 		goto end;
 		}
 
-	if (!rsa_test(out, in, Saltlen))
+	if (!rsa_vtest(out, in, Saltlen))
 		{
 		fprintf(stderr, "FATAL RSAVTEST file processing error\n");
 		goto end;
@@ -159,7 +163,7 @@
 
 #define RSA_TEST_MAXLINELEN	10240
 
-int rsa_test(FILE *out, FILE *in, int Saltlen)
+int rsa_vtest(FILE *out, FILE *in, int Saltlen)
 	{
 	char *linebuf, *olinebuf, *p, *q;
 	char *keyword, *value;
diff --git a/fips/sha/fips_shatest.c b/fips/sha/fips_shatest.c
index c14df16..3954777 100644
--- a/fips/sha/fips_shatest.c
+++ b/fips/sha/fips_shatest.c
@@ -86,7 +86,11 @@
 static int print_monte(const EVP_MD *md, FILE *out,
 		unsigned char *Seed, int SeedLen);
 
+#ifdef FIPS_ALGVS
+int fips_shatest_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 	{
 	FILE *in = NULL, *out = NULL;
 
diff --git a/test/Makefile b/test/Makefile
index 2577d24..2fcc78d 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -81,6 +81,7 @@
 FIPS_ECDSAVS=	fips_ecdsavs
 FIPS_TEST_SUITE=fips_test_suite
 FIPS_CMACTEST=	fips_cmactest
+FIPS_ALGVS=	fips_algvs
 
 TESTS=		alltests
 
@@ -119,7 +120,7 @@
 	$(FIPS_RSASTEST).o $(FIPS_RSAGTEST).o $(FIPS_GCMTEST).o \
 	$(FIPS_DSSVS).o $(FIPS_DSATEST).o $(FIPS_RNGVS).o $(FIPS_DRBGVS).o \
 	$(FIPS_TEST_SUITE).o $(FIPS_DHVS).o $(FIPS_ECDSAVS).o \
-	$(FIPS_ECDHVS).o $(FIPS_CMACTEST).o \
+	$(FIPS_ECDHVS).o $(FIPS_CMACTEST).o $(FIPS_ALGVS).o \
 	$(EVPTEST).o $(IGETEST).o $(JPAKETEST).o
 SRC=	$(BNTEST).c $(ECTEST).c  $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
 	$(MD2TEST).c  $(MD4TEST).c $(MD5TEST).c \
@@ -133,7 +134,7 @@
 	$(FIPS_RSASTEST).c $(FIPS_RSAGTEST).c $(FIPS_GCMTEST).c \
 	$(FIPS_DSSVS).c $(FIPS_DSATEST).c $(FIPS_RNGVS).c $(FIPS_DRBGVS).c \
 	$(FIPS_TEST_SUITE).c $(FIPS_DHVS).c $(FIPS_ECDSAVS).c \
-	$(FIPS_ECDHVS).c $(FIPS_CMACTEST).c \
+	$(FIPS_ECDHVS).c $(FIPS_CMACTEST).c $(FIPS_ALGVS).c \
 	$(EVPTEST).c $(IGETEST).c $(JPAKETEST).c
 
 EXHEADER= 
@@ -150,6 +151,8 @@
 
 fipsexe:	$(FIPSEXE)
 
+fipsalgvs:	$(FIPS_ALGVS)
+
 files:
 	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
 
@@ -504,6 +507,9 @@
 $(FIPS_CMACTEST)$(EXE_EXT): $(FIPS_CMACTEST).o $(DLIBCRYPTO)
 	@target=$(FIPS_CMACTEST); $(FIPS_BUILD_CMD)
 
+$(FIPS_ALGVS)$(EXE_EXT): $(FIPS_ALGVS).o $(DLIBCRYPTO)
+	@target=$(FIPS_ALGVS); $(FIPS_BUILD_CMD)
+
 $(RMDTEST)$(EXE_EXT): $(RMDTEST).o $(DLIBCRYPTO)
 	@target=$(RMDTEST); $(BUILD_CMD)
 
diff --git a/test/fips_algvs.c b/test/fips_algvs.c
new file mode 100644
index 0000000..a662d01
--- /dev/null
+++ b/test/fips_algvs.c
@@ -0,0 +1,312 @@
+/* test/fips_algvs.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2011
+ */
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_FIPS
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+    printf("No FIPS ALGVS support\n");
+    return 0;
+}
+#else
+
+#define FIPS_ALGVS
+
+extern int fips_aesavs_main(int argc, char **argv);
+extern int fips_cmactest_main(int argc, char **argv);
+extern int fips_desmovs_main(int argc, char **argv);
+extern int fips_dhvs_main(int argc, char **argv);
+extern int fips_drbgvs_main(int argc,char **argv);
+extern int fips_dssvs_main(int argc, char **argv);
+extern int fips_ecdhvs_main(int argc, char **argv);
+extern int fips_ecdsavs_main(int argc, char **argv);
+extern int fips_gcmtest_main(int argc, char **argv);
+extern int fips_hmactest_main(int argc, char **argv);
+extern int fips_rngvs_main(int argc, char **argv);
+extern int fips_rsagtest_main(int argc, char **argv);
+extern int fips_rsastest_main(int argc, char **argv);
+extern int fips_rsavtest_main(int argc, char **argv);
+extern int fips_shatest_main(int argc, char **argv);
+extern int fips_test_suite_main(int argc, char **argv);
+
+#include "fips_aesavs.c"
+#include "fips_cmactest.c"
+#include "fips_desmovs.c"
+#include "fips_dhvs.c"
+#include "fips_drbgvs.c"
+#include "fips_dssvs.c"
+#include "fips_ecdhvs.c"
+#include "fips_ecdsavs.c"
+#include "fips_gcmtest.c"
+#include "fips_hmactest.c"
+#include "fips_rngvs.c"
+#include "fips_rsagtest.c"
+#include "fips_rsastest.c"
+#include "fips_rsavtest.c"
+#include "fips_shatest.c"
+#include "fips_test_suite.c"
+
+typedef struct
+	{
+	const char *name;
+	int (*func)(int argc, char **argv);
+	} ALGVS_FUNCTION;
+
+static ALGVS_FUNCTION algvs[] = {
+	{"fips_aesavs", fips_aesavs_main}, 
+	{"fips_cmactest", fips_cmactest_main}, 
+	{"fips_desmovs", fips_desmovs_main}, 
+	{"fips_dhvs", fips_dhvs_main}, 
+	{"fips_drbgvs", fips_drbgvs_main}, 
+	{"fips_dssvs", fips_dssvs_main}, 
+	{"fips_ecdhvs", fips_ecdhvs_main}, 
+	{"fips_ecdsavs", fips_ecdsavs_main}, 
+	{"fips_gcmtest", fips_gcmtest_main}, 
+	{"fips_hmactest", fips_hmactest_main}, 
+	{"fips_rngvs", fips_rngvs_main}, 
+	{"fips_rsagtest", fips_rsagtest_main}, 
+	{"fips_rsastest", fips_rsastest_main}, 
+	{"fips_rsavtest", fips_rsavtest_main}, 
+	{"fips_shatest", fips_shatest_main}, 
+	{"fips_test_suite", fips_test_suite_main}, 
+	{NULL, 0}
+	};
+
+/* Argument parsing taken from apps/apps.c */
+
+typedef struct args_st
+	{
+	char **data;
+	int count;
+	} ARGS;
+
+static int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
+	{
+	int num,i;
+	char *p;
+
+	*argc=0;
+	*argv=NULL;
+
+	i=0;
+	if (arg->count == 0)
+		{
+		arg->count=20;
+		arg->data=(char **)OPENSSL_malloc(sizeof(char *)*arg->count);
+		}
+	for (i=0; i<arg->count; i++)
+		arg->data[i]=NULL;
+
+	num=0;
+	p=buf;
+	for (;;)
+		{
+		/* first scan over white space */
+		if (!*p) break;
+		while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
+			p++;
+		if (!*p) break;
+
+		/* The start of something good :-) */
+		if (num >= arg->count)
+			{
+			fprintf(stderr, "Too many arguments!!\n");
+			return 0;
+			}
+		arg->data[num++]=p;
+
+		/* now look for the end of this */
+		if ((*p == '\'') || (*p == '\"')) /* scan for closing quote */
+			{
+			i= *(p++);
+			arg->data[num-1]++; /* jump over quote */
+			while (*p && (*p != i))
+				p++;
+			*p='\0';
+			}
+		else
+			{
+			while (*p && ((*p != ' ') &&
+				(*p != '\t') && (*p != '\n')))
+				p++;
+
+			if (*p == '\0')
+				p--;
+			else
+				*p='\0';
+			}
+		p++;
+		}
+	*argc=num;
+	*argv=arg->data;
+	return(1);
+	}
+
+static int run_prg(int argc, char **argv)
+	{
+	ALGVS_FUNCTION *t;
+	const char *prg_name;
+	prg_name = strrchr(argv[0], '/');
+	if (prg_name)
+		prg_name++;
+	else
+		prg_name = argv[0];
+	for (t = algvs; t->name; t++)
+		{
+		if (!strcmp(prg_name, t->name))
+			return t->func(argc, argv);
+		}
+	return -100;
+	}
+
+int main(int argc, char **argv)
+	{
+	char buf[1024];
+	char **args = argv + 1;
+	const char *sname = "fipstests.sh";
+	ARGS arg;
+	int xargc;
+	char **xargv;
+	int lineno = 0, badarg = 0;
+	int nerr = 0, quiet = 0, verbose = 0;
+	FILE *in = NULL;
+	if (*args && *args[0] != '-')
+		return run_prg(argc - 1, args);
+	while (!badarg && *args && *args[0] == '-')
+		{
+		if (!strcmp(*args, "-script"))
+			{
+			if (args[1])
+				{
+				args++;
+				sname = *args;
+				}
+			else
+				badarg = 1;
+			}
+		else if (!strcmp(*args, "-quiet"))
+			quiet = 1;
+		else if (!strcmp(*args, "-verbose"))
+			verbose = 1;
+		else
+			badarg = 1;
+		args++;
+		}
+
+	if (badarg)
+		{
+		fprintf(stderr, "Error processing arguments\n");
+		return 1;
+		}
+
+	in = fopen(sname, "r");
+	if (!in)
+		{
+		fprintf(stderr, "Error opening script file \"%s\"\n", sname);
+		return 1;
+		}
+
+	arg.data = NULL;
+	arg.count = 0;
+
+	while (fgets(buf, sizeof(buf), in))
+		{
+		lineno++;
+		if (!chopup_args(&arg, buf, &xargc, &xargv))
+			fprintf(stderr, "Error processing line %d\n", lineno);
+		else
+			{
+			int rv;
+			if (!quiet)
+				{
+				int i;
+				int narg = verbose ? xargc : xargc - 2;
+				printf("Running command line:");
+				for (i = 0; i < narg; i++)
+					printf(" %s", xargv[i]);
+				printf("\n");
+				}
+			rv = run_prg(xargc, xargv);
+			if (FIPS_module_mode())
+				FIPS_module_mode_set(0, NULL);
+			if (rv != 0)
+				nerr++;
+			if (rv == -100)
+				fprintf(stderr, "ERROR: Command not found\n");
+			else if (rv != 0)
+				fprintf(stderr, "ERROR: returned %d\n", rv);
+			else if (verbose)
+				printf("\tCommand run successfully\n");
+			}
+		}
+
+	if (!quiet)
+		printf("Completed with %d errors\n", nerr);
+
+	fclose(in);
+	if (nerr == 0)
+		return 0;
+	return 1;
+	}
+
+#endif