Blame SOURCES/nss-softokn-add-kas-tests.patch

70d46f
diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c
70d46f
--- a/cmd/fipstest/fipstest.c
70d46f
+++ b/cmd/fipstest/fipstest.c
70d46f
@@ -2330,16 +2330,44 @@ sha_get_hashType(int hashbits)
70d46f
             hashType = HASH_AlgSHA512;
70d46f
             break;
70d46f
         default:
70d46f
             break;
70d46f
     }
70d46f
     return hashType;
70d46f
 }
70d46f
 
70d46f
+HASH_HashType
70d46f
+hash_string_to_hashType(const char * src)
70d46f
+{
70d46f
+    HASH_HashType shaAlg = HASH_AlgNULL;
70d46f
+    if (strncmp(src, "SHA-1", 5) == 0) {
70d46f
+         shaAlg = HASH_AlgSHA1;
70d46f
+    } else if (strncmp(src, "SHA-224", 7) == 0) {
70d46f
+        shaAlg = HASH_AlgSHA224;
70d46f
+    } else if (strncmp(src, "SHA-256", 7) == 0) {
70d46f
+        shaAlg = HASH_AlgSHA256;
70d46f
+    } else if (strncmp(src, "SHA-384", 7) == 0) {
70d46f
+        shaAlg = HASH_AlgSHA384;
70d46f
+    } else if (strncmp(src, "SHA-512", 7) == 0) {
70d46f
+        shaAlg = HASH_AlgSHA512;
70d46f
+    } else if (strncmp(src, "SHA1", 4) == 0) {
70d46f
+         shaAlg = HASH_AlgSHA1;
70d46f
+    } else if (strncmp(src, "SHA224", 6) == 0) {
70d46f
+        shaAlg = HASH_AlgSHA224;
70d46f
+    } else if (strncmp(src, "SHA256", 6) == 0) {
70d46f
+        shaAlg = HASH_AlgSHA256;
70d46f
+    } else if (strncmp(src, "SHA384", 6) == 0) {
70d46f
+        shaAlg = HASH_AlgSHA384;
70d46f
+    } else if (strncmp(src, "SHA512", 6) == 0) {
70d46f
+        shaAlg = HASH_AlgSHA512;
70d46f
+    }
70d46f
+    return shaAlg;
70d46f
+}
70d46f
+
70d46f
 /*
70d46f
  * Perform the ECDSA Key Pair Generation Test.
70d46f
  *
70d46f
  * reqfn is the pathname of the REQUEST file.
70d46f
  *
70d46f
  * The output RESPONSE file is written to stdout.
70d46f
  */
70d46f
 void
70d46f
@@ -2623,27 +2651,18 @@ ecdsa_siggen_test(char *reqfn)
70d46f
             *dst++ = tolower(*src);
70d46f
             src += 2; /* skip the hyphen */
70d46f
             *dst++ = *src++;
70d46f
             *dst++ = *src++;
70d46f
             *dst++ = *src++;
70d46f
             *dst = '\0';
70d46f
             src++; /* skip the comma */
70d46f
             /* set the SHA Algorithm */
70d46f
-            if (strncmp(src, "SHA-1", 5) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA1;
70d46f
-            } else if (strncmp(src, "SHA-224", 7) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA224;
70d46f
-            } else if (strncmp(src, "SHA-256", 7) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA256;
70d46f
-            } else if (strncmp(src, "SHA-384", 7) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA384;
70d46f
-            } else if (strncmp(src, "SHA-512", 7) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA512;
70d46f
-            } else {
70d46f
+            shaAlg = hash_string_to_hashType(src);
70d46f
+            if (shaAlg == HASH_AlgNULL){
70d46f
                 fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
70d46f
                 goto loser;
70d46f
             }
70d46f
             if (ecparams != NULL) {
70d46f
                 PORT_FreeArena(ecparams->arena, PR_FALSE);
70d46f
                 ecparams = NULL;
70d46f
             }
70d46f
             encodedparams = getECParams(curve);
70d46f
@@ -2793,27 +2812,18 @@ ecdsa_sigver_test(char *reqfn)
70d46f
             *dst++ = tolower(*src);
70d46f
             src += 2; /* skip the hyphen */
70d46f
             *dst++ = *src++;
70d46f
             *dst++ = *src++;
70d46f
             *dst++ = *src++;
70d46f
             *dst = '\0';
70d46f
             src++; /* skip the comma */
70d46f
             /* set the SHA Algorithm */
70d46f
-            if (strncmp(src, "SHA-1", 5) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA1;
70d46f
-            } else if (strncmp(src, "SHA-224", 7) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA224;
70d46f
-            } else if (strncmp(src, "SHA-256", 7) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA256;
70d46f
-            } else if (strncmp(src, "SHA-384", 7) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA384;
70d46f
-            } else if (strncmp(src, "SHA-512", 7) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA512;
70d46f
-            } else {
70d46f
+            shaAlg = hash_string_to_hashType(src);
70d46f
+            if (shaAlg == HASH_AlgNULL) {
70d46f
                 fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
70d46f
                 goto loser;
70d46f
             }
70d46f
             encodedparams = getECParams(curve);
70d46f
             if (encodedparams == NULL) {
70d46f
                 fprintf(stderr, "Unknown curve %s.", curve);
70d46f
                 goto loser;
70d46f
             }
70d46f
@@ -2951,16 +2961,932 @@ ecdsa_sigver_test(char *reqfn)
70d46f
     }
70d46f
 loser:
70d46f
     if (ecpub.ecParams.arena != NULL) {
70d46f
         PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
70d46f
     }
70d46f
     fclose(ecdsareq);
70d46f
 }
70d46f
 
70d46f
+/*
70d46f
+ * Perform the ECDH Functional Test.
70d46f
+ *
70d46f
+ * reqfn is the pathname of the REQUEST file.
70d46f
+ *
70d46f
+ * The output RESPONSE file is written to stdout.
70d46f
+ */
70d46f
+#define MAX_ECC_PARAMS 256
70d46f
+void
70d46f
+ecdh_functional(char *reqfn, PRBool response)
70d46f
+{
70d46f
+    char buf[256];   /* holds one line from the input REQUEST file.
70d46f
+                         * needs to be large enough to hold the longest
70d46f
+                         * line "Qx = <144 hex digits>\n".
70d46f
+                         */
70d46f
+    FILE *ecdhreq;  /* input stream from the REQUEST file */
70d46f
+    FILE *ecdhresp; /* output stream to the RESPONSE file */
70d46f
+    char curve[16];  /* "nistxddd" */
70d46f
+    unsigned char hashBuf[HASH_LENGTH_MAX];
70d46f
+    ECParams *ecparams[MAX_ECC_PARAMS] = {NULL};
70d46f
+    ECPrivateKey *ecpriv = NULL;
70d46f
+    ECParams *current_ecparams = NULL;
70d46f
+    SECItem pubkey;
70d46f
+    SECItem ZZ;
70d46f
+    unsigned int i;
70d46f
+    unsigned int len = 0;
70d46f
+    unsigned int uit_len = 0;
70d46f
+    int current_curve = -1;
70d46f
+    HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
70d46f
+
70d46f
+    ecdhreq = fopen(reqfn, "r");
70d46f
+    ecdhresp = stdout;
70d46f
+    strcpy(curve, "nist");
70d46f
+    pubkey.data = NULL;
70d46f
+    while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
70d46f
+        /* a comment or blank line */
70d46f
+        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (buf[0] == '[') {
70d46f
+            /* [Ex] */
70d46f
+            if (buf[1] == 'E' && buf[3] == ']') {
70d46f
+                current_curve = buf[2] - 'A';
70d46f
+                fputs(buf, ecdhresp);
70d46f
+                continue;
70d46f
+            }
70d46f
+            /* [Curve selected: x-nnn */
70d46f
+            if (strncmp(buf, "[Curve ", 7) == 0) {
70d46f
+                const char *src;
70d46f
+                char *dst;
70d46f
+                SECItem *encodedparams;
70d46f
+
70d46f
+                if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
70d46f
+                    fprintf(stderr, "No curve type defined\n");
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+
70d46f
+                src = &buf[1];
70d46f
+                /* skip passed the colon */
70d46f
+                while (*src && *src != ':') src++;
70d46f
+                if (*src != ':') {
70d46f
+                    fprintf(stderr,
70d46f
+                        "No colon in curve selected statement\n%s", buf);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                src++;
70d46f
+                /* skip to the first non-space */
70d46f
+                while (*src && *src == ' ') src++;
70d46f
+                dst = &curve[4];
70d46f
+                *dst++ = tolower(*src);
70d46f
+                src += 2; /* skip the hyphen */
70d46f
+                *dst++ = *src++;
70d46f
+                *dst++ = *src++;
70d46f
+                *dst++ = *src++;
70d46f
+                *dst = '\0';
70d46f
+                if (ecparams[current_curve] != NULL) {
70d46f
+                    PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
70d46f
+                    ecparams[current_curve] = NULL;
70d46f
+                }
70d46f
+                encodedparams = getECParams(curve);
70d46f
+                if (encodedparams == NULL) {
70d46f
+                    fprintf(stderr, "Unknown curve %s.", curve);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                if (EC_DecodeParams(encodedparams, &ecparams[current_curve])
70d46f
+                                                        != SECSuccess) {
70d46f
+                    fprintf(stderr, "Curve %s not supported.\n", curve);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                SECITEM_FreeItem(encodedparams, PR_TRUE);
70d46f
+                fputs(buf, ecdhresp);
70d46f
+                continue;
70d46f
+            }
70d46f
+            /* [Ex - SHAxxx] */
70d46f
+            if (buf[1] == 'E' && buf[3] == ' ') {
70d46f
+                const char *src;
70d46f
+                current_curve = buf[2] - 'A';
70d46f
+                if ((current_curve < 0) || (current_curve > 256)) {
70d46f
+                    fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                    current_ecparams = ecparams[current_curve];
70d46f
+                if (current_ecparams == NULL) {
70d46f
+                    fprintf(stderr, "no curve defined for type %c defined\n",
70d46f
+                            buf[2]);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                /* skip passed the colon */
70d46f
+                src = &buf[1];
70d46f
+                while (*src && *src != '-') src++;
70d46f
+                if (*src != '-') {
70d46f
+                    fprintf(stderr,
70d46f
+                        "No data in curve selected statement\n%s",buf);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                src++;
70d46f
+                /* skip to the first non-space */
70d46f
+                while (*src && *src == ' ') src++;
70d46f
+                hash = hash_string_to_hashType(src);
70d46f
+                if (hash == HASH_AlgNULL){
70d46f
+                    fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                fputs(buf, ecdhresp);
70d46f
+                continue;
70d46f
+            }
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* COUNT = ... */
70d46f
+        if (strncmp(buf, "COUNT", 5) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            if (current_ecparams == NULL) {
70d46f
+                fprintf(stderr, "no curve defined for type %c defined\n",
70d46f
+                            buf[2]);
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            len = (current_ecparams->fieldID.size + 7) >> 3;
70d46f
+            if (pubkey.data != NULL) {
70d46f
+                PORT_Free(pubkey.data);
70d46f
+                pubkey.data = NULL;
70d46f
+            }
70d46f
+            SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
70d46f
+            if (pubkey.data == NULL) {
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* QeCAVSx = ... */
70d46f
+        if (strncmp(buf, "QeCAVSx", 7) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            i = 7;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(&pubkey.data[1], len, &buf[i]);
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* QeCAVSy = ... */
70d46f
+        if (strncmp(buf, "QeCAVSy", 7) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            i = 7;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
70d46f
+            if (current_ecparams == NULL) {
70d46f
+                fprintf(stderr, "no curve defined\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            /* validate CAVS public key */
70d46f
+            if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
70d46f
+                fprintf(stderr,"BAD key detected\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+
70d46f
+            /* generate ECC key pair */
70d46f
+            if (EC_NewKey(current_ecparams, &ecpriv) != SECSuccess) {
70d46f
+                fprintf(stderr,"Failed to generate new key\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            /* validate UIT generated public key */
70d46f
+            if (EC_ValidatePublicKey(current_ecparams, &ecpriv->publicValue) !=
70d46f
+                    SECSuccess) {
70d46f
+                fprintf(stderr,"generate key did not validate\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            /* output UIT public key */
70d46f
+            uit_len = ecpriv->publicValue.len;
70d46f
+            if (uit_len % 2 == 0) {
70d46f
+                fprintf(stderr,"generate key had invalid public value len\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            uit_len = (uit_len - 1) / 2;
70d46f
+            if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
70d46f
+                fprintf(stderr,"generate key was compressed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            fputs("QeIUTx = ", ecdhresp);
70d46f
+            to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len);
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            fputc('\n', ecdhresp);
70d46f
+            fputs("QeIUTy = ", ecdhresp);
70d46f
+            to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len);
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            fputc('\n', ecdhresp);
70d46f
+            /* ECDH */
70d46f
+            if (ECDH_Derive(&pubkey,current_ecparams, &ecpriv->privateValue,
70d46f
+                        PR_FALSE, &ZZ) != SECSuccess) {
70d46f
+                fprintf(stderr,"Derive failed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            /* output hash of ZZ */
70d46f
+            if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess ) {
70d46f
+                fprintf(stderr,"hash of derived key failed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            SECITEM_FreeItem(&ZZ, PR_FALSE);
70d46f
+            fputs("HashZZ = ", ecdhresp);
70d46f
+            to_hex_str(buf, hashBuf, fips_hashLen(hash));
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            fputc('\n', ecdhresp);
70d46f
+            fputc('\n', ecdhresp);
70d46f
+            PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
70d46f
+            ecpriv = NULL;
70d46f
+            continue;
70d46f
+        }
70d46f
+    }
70d46f
+loser:
70d46f
+    if (ecpriv != NULL) {
70d46f
+        PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
70d46f
+    }
70d46f
+    for (i=0; i < MAX_ECC_PARAMS; i++) {
70d46f
+        if (ecparams[i] != NULL) {
70d46f
+            PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
70d46f
+            ecparams[i] = NULL;
70d46f
+        }
70d46f
+    }
70d46f
+    if (pubkey.data != NULL) {
70d46f
+        PORT_Free(pubkey.data);
70d46f
+    }
70d46f
+    fclose(ecdhreq);
70d46f
+}
70d46f
+
70d46f
+#define MATCH_OPENSSL 1 
70d46f
+/*
70d46f
+ * Perform the ECDH Validity Test.
70d46f
+ *
70d46f
+ * reqfn is the pathname of the REQUEST file.
70d46f
+ *
70d46f
+ * The output RESPONSE file is written to stdout.
70d46f
+ */
70d46f
+void
70d46f
+ecdh_verify(char *reqfn, PRBool response)
70d46f
+{
70d46f
+    char buf[256];   /* holds one line from the input REQUEST file.
70d46f
+                         * needs to be large enough to hold the longest
70d46f
+                         * line "Qx = <144 hex digits>\n".
70d46f
+                         */
70d46f
+    FILE *ecdhreq;  /* input stream from the REQUEST file */
70d46f
+    FILE *ecdhresp; /* output stream to the RESPONSE file */
70d46f
+    char curve[16];  /* "nistxddd" */
70d46f
+    unsigned char hashBuf[HASH_LENGTH_MAX];
70d46f
+    unsigned char cavsHashBuf[HASH_LENGTH_MAX];
70d46f
+    unsigned char private_data[MAX_ECKEY_LEN];
70d46f
+    ECParams *ecparams[MAX_ECC_PARAMS] =  {NULL};
70d46f
+    ECParams *current_ecparams = NULL;
70d46f
+    SECItem pubkey;
70d46f
+    SECItem ZZ;
70d46f
+    SECItem private_value;
70d46f
+    unsigned int i;
70d46f
+    unsigned int len = 0;
70d46f
+    int current_curve = -1;
70d46f
+    HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
70d46f
+
70d46f
+    ecdhreq = fopen(reqfn, "r");
70d46f
+    ecdhresp = stdout;
70d46f
+    strcpy(curve, "nist");
70d46f
+    pubkey.data = NULL;
70d46f
+    while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
70d46f
+        /* a comment or blank line */
70d46f
+        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (buf[0] == '[') {
70d46f
+            /* [Ex] */
70d46f
+            if (buf[1] == 'E' && buf[3] == ']') {
70d46f
+                current_curve = buf[2] - 'A';
70d46f
+                fputs(buf, ecdhresp);
70d46f
+                continue;
70d46f
+            }
70d46f
+            /* [Curve selected: x-nnn */
70d46f
+            if (strncmp(buf, "[Curve ", 7) == 0) {
70d46f
+                const char *src;
70d46f
+                char *dst;
70d46f
+                SECItem *encodedparams;
70d46f
+
70d46f
+                if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
70d46f
+                    fprintf(stderr, "No curve type defined\n");
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+
70d46f
+                src = &buf[1];
70d46f
+                /* skip passed the colon */
70d46f
+                while (*src && *src != ':') src++;
70d46f
+                if (*src != ':') {
70d46f
+                    fprintf(stderr,
70d46f
+                        "No colon in curve selected statement\n%s", buf);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                src++;
70d46f
+                /* skip to the first non-space */
70d46f
+                while (*src && *src == ' ') src++;
70d46f
+                dst = &curve[4];
70d46f
+                *dst++ = tolower(*src);
70d46f
+                src += 2; /* skip the hyphen */
70d46f
+                *dst++ = *src++;
70d46f
+                *dst++ = *src++;
70d46f
+                *dst++ = *src++;
70d46f
+                *dst = '\0';
70d46f
+                if (ecparams[current_curve] != NULL) {
70d46f
+                    PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
70d46f
+                    ecparams[current_curve] = NULL;
70d46f
+                }
70d46f
+                encodedparams = getECParams(curve);
70d46f
+                if (encodedparams == NULL) {
70d46f
+                    fprintf(stderr, "Unknown curve %s.\n", curve);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                if (EC_DecodeParams(encodedparams, &ecparams[current_curve])
70d46f
+                                                        != SECSuccess) {
70d46f
+                    fprintf(stderr, "Curve %s not supported.\n", curve);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                SECITEM_FreeItem(encodedparams, PR_TRUE);
70d46f
+                fputs(buf, ecdhresp);
70d46f
+                continue;
70d46f
+            }
70d46f
+            /* [Ex - SHAxxx] */
70d46f
+            if (buf[1] == 'E' && buf[3] == ' ') {
70d46f
+                const char *src;
70d46f
+                current_curve = buf[2] - 'A';
70d46f
+                if ((current_curve < 0) || (current_curve > 256)) {
70d46f
+                    fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                    current_ecparams = ecparams[current_curve];
70d46f
+                if (current_ecparams == NULL) {
70d46f
+                    fprintf(stderr, "no curve defined for type %c defined\n",
70d46f
+                            buf[2]);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                /* skip passed the colon */
70d46f
+                src = &buf[1];
70d46f
+                while (*src && *src != '-') src++;
70d46f
+                if (*src != '-') {
70d46f
+                    fprintf(stderr,
70d46f
+                        "No data in curve selected statement\n%s",buf);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                src++;
70d46f
+                /* skip to the first non-space */
70d46f
+                while (*src && *src == ' ') src++;
70d46f
+                hash = hash_string_to_hashType(src);
70d46f
+                if (hash == HASH_AlgNULL){
70d46f
+                    fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                fputs(buf, ecdhresp);
70d46f
+                continue;
70d46f
+            }
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* COUNT = ... */
70d46f
+        if (strncmp(buf, "COUNT", 5) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            if (current_ecparams == NULL) {
70d46f
+                fprintf(stderr, "no curve defined for type %c defined\n",
70d46f
+                            buf[2]);
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            len = (current_ecparams->fieldID.size + 7) >> 3;
70d46f
+            if (pubkey.data != NULL) {
70d46f
+                PORT_Free(pubkey.data);
70d46f
+                pubkey.data = NULL;
70d46f
+            }
70d46f
+            SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
70d46f
+            if (pubkey.data == NULL) {
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* QeCAVSx = ... */
70d46f
+        if (strncmp(buf, "QeCAVSx", 7) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            i = 7;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(&pubkey.data[1], len, &buf[i]);
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* QeCAVSy = ... */
70d46f
+        if (strncmp(buf, "QeCAVSy", 7) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            i = 7;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (strncmp(buf, "deIUT", 5) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            i = 5;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(private_data, len, &buf[i]);
70d46f
+            private_value.data = private_data;
70d46f
+            private_value.len = len;
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (strncmp(buf, "QeIUTx", 6) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (strncmp(buf, "QeIUTy", 6) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (strncmp(buf, "CAVSHashZZ", 10) == 0) {
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            i = 10;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
70d46f
+            if (current_ecparams == NULL) {
70d46f
+                fprintf(stderr, "no curve defined for type defined\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            /* validate CAVS public key */
70d46f
+            if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
70d46f
+#ifdef MATCH_OPENSSL
70d46f
+		fprintf(ecdhresp, "Result = F\n");
70d46f
+#else
70d46f
+		fprintf(ecdhresp, "Result = F # key didn't validate\n");
70d46f
+#endif
70d46f
+                continue;
70d46f
+            }
70d46f
+
70d46f
+            /* ECDH */
70d46f
+            if (ECDH_Derive(&pubkey, current_ecparams, &private_value,
70d46f
+                        PR_FALSE, &ZZ) != SECSuccess) {
70d46f
+                fprintf(stderr,"Derive failed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            /* output  ZZ */
70d46f
+#ifndef MATCH_OPENSSL
70d46f
+            fputs("Z = ", ecdhresp);
70d46f
+            to_hex_str(buf, ZZ.data, ZZ.len);
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            fputc('\n', ecdhresp);
70d46f
+#endif
70d46f
+
70d46f
+            if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess ) {
70d46f
+                fprintf(stderr,"hash of derived key failed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            SECITEM_FreeItem(&ZZ, PR_FALSE);
70d46f
+#ifndef MATCH_NIST
70d46f
+            fputs("IUTHashZZ = ", ecdhresp);
70d46f
+            to_hex_str(buf, hashBuf, fips_hashLen(hash));
70d46f
+            fputs(buf, ecdhresp);
70d46f
+            fputc('\n', ecdhresp);
70d46f
+#endif
70d46f
+            if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
70d46f
+#ifdef MATCH_OPENSSL
70d46f
+		fprintf(ecdhresp, "Result = F\n");
70d46f
+#else
70d46f
+		fprintf(ecdhresp, "Result = F # hash doesn't match\n");
70d46f
+#endif
70d46f
+            } else {
70d46f
+		fprintf(ecdhresp, "Result = P\n");
70d46f
+            }
70d46f
+#ifndef MATCH_OPENSSL
70d46f
+            fputc('\n', ecdhresp);
70d46f
+#endif
70d46f
+            continue;
70d46f
+        }
70d46f
+    }
70d46f
+loser:
70d46f
+    for (i=0; i < MAX_ECC_PARAMS; i++) {
70d46f
+        if (ecparams[i] != NULL) {
70d46f
+            PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
70d46f
+            ecparams[i] = NULL;
70d46f
+        }
70d46f
+    }
70d46f
+    if (pubkey.data != NULL) {
70d46f
+        PORT_Free(pubkey.data);
70d46f
+    }
70d46f
+    fclose(ecdhreq);
70d46f
+}
70d46f
+
70d46f
+/*
70d46f
+ * Perform the DH Functional Test.
70d46f
+ *
70d46f
+ * reqfn is the pathname of the REQUEST file.
70d46f
+ *
70d46f
+ * The output RESPONSE file is written to stdout.
70d46f
+ */
70d46f
+#define MAX_ECC_PARAMS 256
70d46f
+void
70d46f
+dh_functional(char *reqfn, PRBool response)
70d46f
+{
70d46f
+    char buf[1024];   /* holds one line from the input REQUEST file.
70d46f
+                         * needs to be large enough to hold the longest
70d46f
+                         * line "YephCAVS = <512 hex digits>\n".
70d46f
+                         */
70d46f
+    FILE *dhreq;  /* input stream from the REQUEST file */
70d46f
+    FILE *dhresp; /* output stream to the RESPONSE file */
70d46f
+    unsigned char hashBuf[HASH_LENGTH_MAX];
70d46f
+    DSAPrivateKey *dsapriv = NULL;
70d46f
+    PQGParams pqg = { 0 };
70d46f
+    unsigned char pubkeydata[DSA_MAX_P_BITS/8];
70d46f
+    SECItem pubkey;
70d46f
+    SECItem ZZ;
70d46f
+    unsigned int i,j;
70d46f
+    unsigned int pgySize;
70d46f
+    HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
70d46f
+
70d46f
+    dhreq = fopen(reqfn, "r");
70d46f
+    dhresp = stdout;
70d46f
+    while (fgets(buf, sizeof buf, dhreq) != NULL) {
70d46f
+        /* a comment or blank line */
70d46f
+        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (buf[0] == '[') {
70d46f
+            /* [Fx - SHAxxx] */
70d46f
+            if (buf[1] == 'F' && buf[3] == ' ') {
70d46f
+                const char *src;
70d46f
+                /* skip passed the colon */
70d46f
+                src = &buf[1];
70d46f
+                while (*src && *src != '-') src++;
70d46f
+                if (*src != '-') {
70d46f
+                    fprintf(stderr, "No hash specified\n%s",buf);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                src++;
70d46f
+                /* skip to the first non-space */
70d46f
+                while (*src && *src == ' ') src++;
70d46f
+                hash = hash_string_to_hashType(src);
70d46f
+                if (hash == HASH_AlgNULL){
70d46f
+                    fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                /* clear the PQG parameters */
70d46f
+                if (pqg.prime.data) { /* P */
70d46f
+                    SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
70d46f
+                }
70d46f
+                if (pqg.subPrime.data) { /* Q */
70d46f
+                    SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
70d46f
+                }
70d46f
+                if (pqg.base.data) { /* G */
70d46f
+                    SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
70d46f
+                }
70d46f
+                pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
70d46f
+                SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
70d46f
+                SECITEM_AllocItem(NULL, &pqg.base, pgySize);
70d46f
+                pqg.prime.len = pqg.base.len = pgySize;
70d46f
+
70d46f
+                /* set q to the max allows */
70d46f
+                SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS/ 8);
70d46f
+                pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
70d46f
+                fputs(buf, dhresp);
70d46f
+                continue;
70d46f
+            }
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (buf[0] == 'P') {
70d46f
+            i = 1;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            for (j = 0; j < pqg.prime.len; i += 2, j++) {
70d46f
+                if (!isxdigit(buf[i])) {
70d46f
+                    pqg.prime.len = j;
70d46f
+                    break;
70d46f
+                }
70d46f
+                hex_to_byteval(&buf[i], &pqg.prime.data[j]);
70d46f
+            }
70d46f
+
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+
70d46f
+        /* Q = ... */
70d46f
+        if (buf[0] == 'Q') {
70d46f
+            i = 1;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
70d46f
+                if (!isxdigit(buf[i])) {
70d46f
+                    pqg.subPrime.len = j;
70d46f
+                    break;
70d46f
+                }
70d46f
+                hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
70d46f
+            }
70d46f
+
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+
70d46f
+        /* G = ... */
70d46f
+        if (buf[0] == 'G') {
70d46f
+            i = 1;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            for (j = 0; j < pqg.base.len; i += 2, j++) {
70d46f
+                if (!isxdigit(buf[i])) {
70d46f
+                    pqg.base.len = j;
70d46f
+                    break;
70d46f
+                }
70d46f
+                hex_to_byteval(&buf[i], &pqg.base.data[j]);
70d46f
+            }
70d46f
+
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+
70d46f
+        /* COUNT = ... */
70d46f
+        if (strncmp(buf, "COUNT", 5) == 0) {
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+
70d46f
+        /* YephemCAVS = ... */
70d46f
+        if (strncmp(buf, "YephemCAVS", 10) == 0) {
70d46f
+            fputs(buf, dhresp);
70d46f
+            i = 10;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
70d46f
+            pubkey.data = pubkeydata;
70d46f
+            pubkey.len = pqg.prime.len;
70d46f
+
70d46f
+            /* generate FCC key pair, nist uses pqg rather then pg,
70d46f
+             * so use DSA to generate the key */
70d46f
+            if (DSA_NewKey(&pqg, &dsapriv) != SECSuccess) {
70d46f
+                fprintf(stderr,"Failed to generate new key\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            fputs("XephemIUT = ", dhresp);
70d46f
+            to_hex_str(buf, dsapriv->privateValue.data, dsapriv->privateValue.len);
70d46f
+            fputs(buf, dhresp);
70d46f
+            fputc('\n', dhresp);
70d46f
+            fputs("YephemIUT = ", dhresp);
70d46f
+            to_hex_str(buf, dsapriv->publicValue.data, dsapriv->publicValue.len);
70d46f
+            fputs(buf, dhresp);
70d46f
+            fputc('\n', dhresp);
70d46f
+            /* DH */
70d46f
+            if (DH_Derive(&pubkey,&pqg.prime, &dsapriv->privateValue,
70d46f
+                        &ZZ, pqg.prime.len) != SECSuccess) {
70d46f
+                fprintf(stderr,"Derive failed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            /* output hash of ZZ */
70d46f
+            if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess ) {
70d46f
+                fprintf(stderr,"hash of derived key failed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            SECITEM_FreeItem(&ZZ, PR_FALSE);
70d46f
+            fputs("HashZZ = ", dhresp);
70d46f
+            to_hex_str(buf, hashBuf, fips_hashLen(hash));
70d46f
+            fputs(buf, dhresp);
70d46f
+            fputc('\n', dhresp);
70d46f
+            fputc('\n', dhresp);
70d46f
+            PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
70d46f
+            dsapriv = NULL;
70d46f
+            continue;
70d46f
+        }
70d46f
+    }
70d46f
+loser:
70d46f
+    if (dsapriv != NULL) {
70d46f
+        PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
70d46f
+    }
70d46f
+    fclose(dhreq);
70d46f
+}
70d46f
+
70d46f
+#define MATCH_OPENSSL 1 
70d46f
+/*
70d46f
+ * Perform the DH Validity Test.
70d46f
+ *
70d46f
+ * reqfn is the pathname of the REQUEST file.
70d46f
+ *
70d46f
+ * The output RESPONSE file is written to stdout.
70d46f
+ */
70d46f
+void
70d46f
+dh_verify(char *reqfn, PRBool response)
70d46f
+{
70d46f
+    char buf[1024];   /* holds one line from the input REQUEST file.
70d46f
+                         * needs to be large enough to hold the longest
70d46f
+                         * line "YephCAVS = <512 hex digits>\n".
70d46f
+                         */
70d46f
+    FILE *dhreq;  /* input stream from the REQUEST file */
70d46f
+    FILE *dhresp; /* output stream to the RESPONSE file */
70d46f
+    unsigned char hashBuf[HASH_LENGTH_MAX];
70d46f
+    unsigned char cavsHashBuf[HASH_LENGTH_MAX];
70d46f
+    PQGParams pqg = { 0 };
70d46f
+    unsigned char pubkeydata[DSA_MAX_P_BITS/8];
70d46f
+    unsigned char privkeydata[DSA_MAX_P_BITS/8];
70d46f
+    SECItem pubkey;
70d46f
+    SECItem privkey;
70d46f
+    SECItem ZZ;
70d46f
+    unsigned int i,j;
70d46f
+    unsigned int pgySize;
70d46f
+    HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
70d46f
+
70d46f
+    dhreq = fopen(reqfn, "r");
70d46f
+    dhresp = stdout;
70d46f
+    while (fgets(buf, sizeof buf, dhreq) != NULL) {
70d46f
+        /* a comment or blank line */
70d46f
+        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (buf[0] == '[') {
70d46f
+            /* [Fx - SHAxxx] */
70d46f
+            if (buf[1] == 'F' && buf[3] == ' ') {
70d46f
+                const char *src;
70d46f
+                /* skip passed the colon */
70d46f
+                src = &buf[1];
70d46f
+                while (*src && *src != '-') src++;
70d46f
+                if (*src != '-') {
70d46f
+                    fprintf(stderr, "No hash specified\n%s",buf);
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                src++;
70d46f
+                /* skip to the first non-space */
70d46f
+                while (*src && *src == ' ') src++;
70d46f
+                hash = hash_string_to_hashType(src);
70d46f
+                if (hash == HASH_AlgNULL){
70d46f
+                    fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
70d46f
+                    goto loser;
70d46f
+                }
70d46f
+                /* clear the PQG parameters */
70d46f
+                if (pqg.prime.data) { /* P */
70d46f
+                    SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
70d46f
+                }
70d46f
+                if (pqg.subPrime.data) { /* Q */
70d46f
+                    SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
70d46f
+                }
70d46f
+                if (pqg.base.data) { /* G */
70d46f
+                    SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
70d46f
+                }
70d46f
+                pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
70d46f
+                SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
70d46f
+                SECITEM_AllocItem(NULL, &pqg.base, pgySize);
70d46f
+                pqg.prime.len = pqg.base.len = pgySize;
70d46f
+
70d46f
+                /* set q to the max allows */
70d46f
+                SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS/ 8);
70d46f
+                pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
70d46f
+                fputs(buf, dhresp);
70d46f
+                continue;
70d46f
+            }
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        if (buf[0] == 'P') {
70d46f
+            i = 1;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            for (j = 0; j < pqg.prime.len; i += 2, j++) {
70d46f
+                if (!isxdigit(buf[i])) {
70d46f
+                    pqg.prime.len = j;
70d46f
+                    break;
70d46f
+                }
70d46f
+                hex_to_byteval(&buf[i], &pqg.prime.data[j]);
70d46f
+            }
70d46f
+
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+
70d46f
+        /* Q = ... */
70d46f
+        if (buf[0] == 'Q') {
70d46f
+            i = 1;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
70d46f
+                if (!isxdigit(buf[i])) {
70d46f
+                    pqg.subPrime.len = j;
70d46f
+                    break;
70d46f
+                }
70d46f
+                hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
70d46f
+            }
70d46f
+
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+
70d46f
+        /* G = ... */
70d46f
+        if (buf[0] == 'G') {
70d46f
+            i = 1;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            for (j = 0; j < pqg.base.len; i += 2, j++) {
70d46f
+                if (!isxdigit(buf[i])) {
70d46f
+                    pqg.base.len = j;
70d46f
+                    break;
70d46f
+                }
70d46f
+                hex_to_byteval(&buf[i], &pqg.base.data[j]);
70d46f
+            }
70d46f
+
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+
70d46f
+        /* COUNT = ... */
70d46f
+        if (strncmp(buf, "COUNT", 5) == 0) {
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+
70d46f
+        /* YephemCAVS = ... */
70d46f
+        if (strncmp(buf, "YephemCAVS", 10) == 0) {
70d46f
+            fputs(buf, dhresp);
70d46f
+            i = 10;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
70d46f
+            pubkey.data = pubkeydata;
70d46f
+            pubkey.len = pqg.prime.len;
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* XephemUIT = ... */
70d46f
+        if (strncmp(buf, "XephemIUT", 9) == 0) {
70d46f
+            fputs(buf, dhresp);
70d46f
+            i = 9;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(privkeydata, pqg.subPrime.len, &buf[i]);
70d46f
+            privkey.data = privkeydata;
70d46f
+            privkey.len = pqg.subPrime.len;
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* YephemUIT = ... */
70d46f
+        if (strncmp(buf, "YephemIUT", 9) == 0) {
70d46f
+            fputs(buf, dhresp);
70d46f
+            continue;
70d46f
+        }
70d46f
+        /* CAVSHashZZ = ... */
70d46f
+        if (strncmp(buf, "CAVSHashZZ", 10) == 0) {
70d46f
+            fputs(buf, dhresp);
70d46f
+            i = 10;
70d46f
+            while (isspace(buf[i]) || buf[i] == '=') {
70d46f
+                i++;
70d46f
+            }
70d46f
+            from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
70d46f
+            /* do the DH operation*/
70d46f
+            if (DH_Derive(&pubkey,&pqg.prime, &privkey,
70d46f
+                        &ZZ, pqg.prime.len) != SECSuccess) {
70d46f
+                fprintf(stderr,"Derive failed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            /* output  ZZ */
70d46f
+#ifndef MATCH_OPENSSL
70d46f
+            fputs("Z = ", dhresp);
70d46f
+            to_hex_str(buf, ZZ.data, ZZ.len);
70d46f
+            fputs(buf, dhresp);
70d46f
+            fputc('\n', dhresp);
70d46f
+#endif
70d46f
+            if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess ) {
70d46f
+                fprintf(stderr,"hash of derived key failed\n");
70d46f
+                goto loser;
70d46f
+            }
70d46f
+            SECITEM_FreeItem(&ZZ, PR_FALSE);
70d46f
+#ifndef MATCH_NIST_
70d46f
+            fputs("IUTHashZZ = ", dhresp);
70d46f
+            to_hex_str(buf, hashBuf, fips_hashLen(hash));
70d46f
+            fputs(buf, dhresp);
70d46f
+            fputc('\n', dhresp);
70d46f
+#endif
70d46f
+            if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
70d46f
+		fprintf(dhresp, "Result = F\n");
70d46f
+            } else {
70d46f
+		fprintf(dhresp, "Result = P\n");
70d46f
+            }
70d46f
+#ifndef MATCH_OPENSSL
70d46f
+            fputc('\n', dhresp);
70d46f
+#endif
70d46f
+            continue;
70d46f
+        }
70d46f
+    }
70d46f
+loser:
70d46f
+    fclose(dhreq);
70d46f
+}
70d46f
+
70d46f
 PRBool
70d46f
 isblankline(char *b)
70d46f
 {
70d46f
     while (isspace(*b))
70d46f
         b++;
70d46f
     if ((*b == '\n') || (*b == 0)) {
70d46f
         return PR_TRUE;
70d46f
     }
70d46f
@@ -5337,27 +6263,18 @@ rsa_siggen_test(char *reqfn)
70d46f
 
70d46f
         /* SHAAlg = ... */
70d46f
         if (strncmp(buf, "SHAAlg", 6) == 0) {
70d46f
             i = 6;
70d46f
             while (isspace(buf[i]) || buf[i] == '=') {
70d46f
                 i++;
70d46f
             }
70d46f
             /* set the SHA Algorithm */
70d46f
-            if (strncmp(&buf[i], "SHA1", 4) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA1;
70d46f
-            } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA224;
70d46f
-            } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA256;
70d46f
-            } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA384;
70d46f
-            } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA512;
70d46f
-            } else {
70d46f
+            shaAlg = hash_string_to_hashType(&buf[i]);
70d46f
+            if (shaAlg == HASH_AlgNULL) {
70d46f
                 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
70d46f
                 goto loser;
70d46f
             }
70d46f
             fputs(buf, rsaresp);
70d46f
             continue;
70d46f
         }
70d46f
         /* Msg = ... */
70d46f
         if (strncmp(buf, "Msg", 3) == 0) {
70d46f
@@ -5532,27 +6449,18 @@ rsa_sigver_test(char *reqfn)
70d46f
 
70d46f
         /* SHAAlg = ... */
70d46f
         if (strncmp(buf, "SHAAlg", 6) == 0) {
70d46f
             i = 6;
70d46f
             while (isspace(buf[i]) || buf[i] == '=') {
70d46f
                 i++;
70d46f
             }
70d46f
             /* set the SHA Algorithm */
70d46f
-            if (strncmp(&buf[i], "SHA1", 4) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA1;
70d46f
-            } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA224;
70d46f
-            } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA256;
70d46f
-            } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA384;
70d46f
-            } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
70d46f
-                shaAlg = HASH_AlgSHA512;
70d46f
-            } else {
70d46f
+            shaAlg = hash_string_to_hashType(&buf[i]);
70d46f
+            if (shaAlg == HASH_AlgNULL) {
70d46f
                 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
70d46f
                 goto loser;
70d46f
             }
70d46f
             fputs(buf, rsaresp);
70d46f
             continue;
70d46f
         }
70d46f
 
70d46f
         /* e = ... public Key */
70d46f
@@ -6103,16 +7011,44 @@ main(int argc, char **argv)
70d46f
         } else if (strcmp(argv[2], "siggen") == 0) {
70d46f
             /* Signature Generation Test */
70d46f
             ecdsa_siggen_test(argv[3]);
70d46f
         } else if (strcmp(argv[2], "sigver") == 0) {
70d46f
             /* Signature Verification Test */
70d46f
             ecdsa_sigver_test(argv[3]);
70d46f
         }
70d46f
         /*************/
70d46f
+        /*   ECDH   */
70d46f
+        /*************/
70d46f
+    } else if (strcmp(argv[1], "ecdh") == 0) {
70d46f
+        /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
70d46f
+        if (strcmp(argv[2], "init-func") == 0) {
70d46f
+            ecdh_functional(argv[3], 0);
70d46f
+        } else if (strcmp(argv[2], "resp-func") == 0) {
70d46f
+            ecdh_functional(argv[3], 1);
70d46f
+        } else if (strcmp(argv[2], "init-verify") == 0) {
70d46f
+            ecdh_verify(argv[3], 0);
70d46f
+        } else if (strcmp(argv[2], "resp-verify") == 0) {
70d46f
+            ecdh_verify(argv[3], 1);
70d46f
+        }
70d46f
+        /*************/
70d46f
+        /*   DH   */
70d46f
+        /*************/
70d46f
+    } else if (strcmp(argv[1], "dh") == 0) {
70d46f
+        /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
70d46f
+        if (strcmp(argv[2], "init-func") == 0) {
70d46f
+            dh_functional(argv[3], 0);
70d46f
+        } else if (strcmp(argv[2], "resp-func") == 0) {
70d46f
+            dh_functional(argv[3], 1);
70d46f
+        } else if (strcmp(argv[2], "init-verify") == 0) {
70d46f
+            dh_verify(argv[3], 0);
70d46f
+        } else if (strcmp(argv[2], "resp-verify") == 0) {
70d46f
+            dh_verify(argv[3], 1);
70d46f
+        }
70d46f
+        /*************/
70d46f
         /*   RNG     */
70d46f
         /*************/
70d46f
     } else if (strcmp(argv[1], "rng") == 0) {
70d46f
         /* argv[2]=vst|mct argv[3]=<test name>.req */
70d46f
         if (strcmp(argv[2], "vst") == 0) {
70d46f
             /* Variable Seed Test */
70d46f
             rng_vst(argv[3]);
70d46f
         } else if (strcmp(argv[2], "mct") == 0) {
70d46f
diff --git a/cmd/fipstest/kas.sh b/cmd/fipstest/kas.sh
70d46f
new file mode 100755
70d46f
--- /dev/null
70d46f
+++ b/cmd/fipstest/kas.sh
70d46f
@@ -0,0 +1,84 @@
70d46f
+#!/bin/sh
70d46f
+# 
70d46f
+# This Source Code Form is subject to the terms of the Mozilla Public
70d46f
+# License, v. 2.0. If a copy of the MPL was not distributed with this
70d46f
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
70d46f
+#
70d46f
+# A Bourne shell script for running the NIST DSA Validation System
70d46f
+#
70d46f
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
70d46f
+# variables appropriately so that the fipstest command and the NSPR and NSS
70d46f
+# shared libraries/DLLs are on the search path.  Then run this script in the
70d46f
+# directory where the REQUEST (.req) files reside.  The script generates the
70d46f
+# RESPONSE (.rsp) files in the same directory.
70d46f
+BASEDIR=${1-.}
70d46f
+TESTDIR=${BASEDIR}/KAS
70d46f
+COMMAND=${2-run}
70d46f
+REQDIR=${TESTDIR}/req
70d46f
+RSPDIR=${TESTDIR}/resp
70d46f
+
70d46f
+
70d46f
+#
70d46f
+if [ ${COMMAND} = "verify" ]; then
70d46f
+#
70d46f
+# need verify for KAS tests
70d46f
+
70d46f
+# verify generated keys
70d46f
+#    name=KeyPair
70d46f
+#    echo ">>>>>  $name"
70d46f
+#    fipstest dsa keyver ${RSPDIR}/$name.rsp | grep ^Result.=.F
70d46f
+# verify generated pqg values
70d46f
+#    name=PQGGen
70d46f
+#    echo ">>>>>  $name"
70d46f
+#    fipstest dsa pqgver ${RSPDIR}/$name.rsp | grep ^Result.=.F
70d46f
+# verify PQGVer with known answer
70d46f
+#    sh ./validate1.sh ${TESTDIR} PQGVer.req ' ' '-e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;'
70d46f
+# verify signatures
70d46f
+#    name=SigGen
70d46f
+#    echo ">>>>>  $name"
70d46f
+#    fipstest dsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F
70d46f
+# verify SigVer with known answer
70d46f
+#    sh ./validate1.sh ${TESTDIR} SigVer.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);;'
70d46f
+    exit 0
70d46f
+fi
70d46f
+
70d46f
+request=KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req
70d46f
+response=`echo $request | sed -e "s/req/rsp/"`
70d46f
+echo $request $response
70d46f
+fipstest ecdh init-func ${REQDIR}/$request > ${RSPDIR}/$response
70d46f
+
70d46f
+request=KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req
70d46f
+response=`echo $request | sed -e "s/req/rsp/"`
70d46f
+echo $request $response
70d46f
+fipstest ecdh resp-func ${REQDIR}/$request > ${RSPDIR}/$response
70d46f
+
70d46f
+request=KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req
70d46f
+response=`echo $request | sed -e "s/req/rsp/"`
70d46f
+echo $request $response
70d46f
+fipstest ecdh init-verify ${REQDIR}/$request > ${RSPDIR}/$response
70d46f
+
70d46f
+request=KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req
70d46f
+response=`echo $request | sed -e "s/req/rsp/"`
70d46f
+echo $request $response
70d46f
+fipstest ecdh resp-verify ${REQDIR}/$request > ${RSPDIR}/$response
70d46f
+
70d46f
+request=KASFunctionTest_FFCEphem_NOKC_ZZOnly_init.req
70d46f
+response=`echo $request | sed -e "s/req/rsp/"`
70d46f
+echo $request $response
70d46f
+fipstest dh init-func ${REQDIR}/$request > ${RSPDIR}/$response
70d46f
+
70d46f
+request=KASFunctionTest_FFCEphem_NOKC_ZZOnly_resp.req
70d46f
+response=`echo $request | sed -e "s/req/rsp/"`
70d46f
+echo $request $response
70d46f
+fipstest dh resp-func ${REQDIR}/$request > ${RSPDIR}/$response
70d46f
+
70d46f
+request=KASValidityTest_FFCEphem_NOKC_ZZOnly_init.req
70d46f
+response=`echo $request | sed -e "s/req/rsp/"`
70d46f
+echo $request $response
70d46f
+fipstest dh init-verify ${REQDIR}/$request > ${RSPDIR}/$response
70d46f
+
70d46f
+request=KASValidityTest_FFCEphem_NOKC_ZZOnly_resp.req
70d46f
+response=`echo $request | sed -e "s/req/rsp/"`
70d46f
+echo $request $response
70d46f
+fipstest dh resp-verify ${REQDIR}/$request > ${RSPDIR}/$response
70d46f
+
70d46f
diff --git a/cmd/fipstest/runtest.sh b/cmd/fipstest/runtest.sh
70d46f
--- a/cmd/fipstest/runtest.sh
70d46f
+++ b/cmd/fipstest/runtest.sh
70d46f
@@ -1,14 +1,14 @@
70d46f
 #!/bin/sh
70d46f
 # 
70d46f
 # This Source Code Form is subject to the terms of the Mozilla Public
70d46f
 # License, v. 2.0. If a copy of the MPL was not distributed with this
70d46f
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
70d46f
 #
70d46f
 TESTDIR=${1-.}
70d46f
 COMMAND=${2-run}
70d46f
-TESTS="aes aesgcm dsa ecdsa hmac tls rng rsa sha tdea"
70d46f
+TESTS="aes aesgcm dsa ecdsa hmac kas tls rng rsa sha tdea"
70d46f
 for i in $TESTS
70d46f
 do
70d46f
     echo "********************Running $i tests"
70d46f
     sh ./${i}.sh ${TESTDIR} ${COMMAND}
70d46f
 done