/security/nss/cmd/fipstest/fipstest.c
C | 4903 lines | 3797 code | 360 blank | 746 comment | 1445 complexity | ac6666cf55eeec83bda3ea3b4e6ec112 MD5 | raw file
Possible License(s): LGPL-3.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "secitem.h"
- #include "blapi.h"
- #include "nss.h"
- #include "secerr.h"
- #include "secder.h"
- #include "secdig.h"
- #include "keythi.h"
- #include "ec.h"
- #include "hasht.h"
- #include "lowkeyi.h"
- #include "softoken.h"
- #if 0
- #include "../../lib/freebl/mpi/mpi.h"
- #endif
- #ifdef NSS_ENABLE_ECC
- extern SECStatus
- EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
- extern SECStatus
- EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
- const ECParams *srcParams);
- #endif
- #define ENCRYPT 1
- #define DECRYPT 0
- #define BYTE unsigned char
- #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
- #define RSA_MAX_TEST_MODULUS_BITS 4096
- #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
- #define RSA_MAX_TEST_EXPONENT_BYTES 8
- #define PQG_TEST_SEED_BYTES 20
- SECStatus
- hex_to_byteval(const char *c2, unsigned char *byteval)
- {
- int i;
- unsigned char offset;
- *byteval = 0;
- for (i=0; i<2; i++) {
- if (c2[i] >= '0' && c2[i] <= '9') {
- offset = c2[i] - '0';
- *byteval |= offset << 4*(1-i);
- } else if (c2[i] >= 'a' && c2[i] <= 'f') {
- offset = c2[i] - 'a';
- *byteval |= (offset + 10) << 4*(1-i);
- } else if (c2[i] >= 'A' && c2[i] <= 'F') {
- offset = c2[i] - 'A';
- *byteval |= (offset + 10) << 4*(1-i);
- } else {
- return SECFailure;
- }
- }
- return SECSuccess;
- }
- SECStatus
- byteval_to_hex(unsigned char byteval, char *c2, char a)
- {
- int i;
- unsigned char offset;
- for (i=0; i<2; i++) {
- offset = (byteval >> 4*(1-i)) & 0x0f;
- if (offset < 10) {
- c2[i] = '0' + offset;
- } else {
- c2[i] = a + offset - 10;
- }
- }
- return SECSuccess;
- }
- void
- to_hex_str(char *str, const unsigned char *buf, unsigned int len)
- {
- unsigned int i;
- for (i=0; i<len; i++) {
- byteval_to_hex(buf[i], &str[2*i], 'a');
- }
- str[2*len] = '\0';
- }
- void
- to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
- {
- unsigned int i;
- for (i=0; i<len; i++) {
- byteval_to_hex(buf[i], &str[2*i], 'A');
- }
- str[2*len] = '\0';
- }
- /*
- * Convert a string of hex digits (str) to an array (buf) of len bytes.
- * Return PR_TRUE if the hex string can fit in the byte array. Return
- * PR_FALSE if the hex string is empty or is too long.
- */
- PRBool
- from_hex_str(unsigned char *buf, unsigned int len, const char *str)
- {
- unsigned int nxdigit; /* number of hex digits in str */
- unsigned int i; /* index into buf */
- unsigned int j; /* index into str */
- /* count the hex digits */
- nxdigit = 0;
- for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
- /* empty body */
- }
- if (nxdigit == 0) {
- return PR_FALSE;
- }
- if (nxdigit > 2*len) {
- /*
- * The input hex string is too long, but we allow it if the
- * extra digits are leading 0's.
- */
- for (j = 0; j < nxdigit-2*len; j++) {
- if (str[j] != '0') {
- return PR_FALSE;
- }
- }
- /* skip leading 0's */
- str += nxdigit-2*len;
- nxdigit = 2*len;
- }
- for (i=0, j=0; i< len; i++) {
- if (2*i < 2*len-nxdigit) {
- /* Handle a short input as if we padded it with leading 0's. */
- if (2*i+1 < 2*len-nxdigit) {
- buf[i] = 0;
- } else {
- char tmp[2];
- tmp[0] = '0';
- tmp[1] = str[j];
- hex_to_byteval(tmp, &buf[i]);
- j++;
- }
- } else {
- hex_to_byteval(&str[j], &buf[i]);
- j += 2;
- }
- }
- return PR_TRUE;
- }
- SECStatus
- tdea_encrypt_buf(
- int mode,
- const unsigned char *key,
- const unsigned char *iv,
- unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
- const unsigned char *input, unsigned int inputlen)
- {
- SECStatus rv = SECFailure;
- DESContext *cx;
- unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
- unsigned int doublechecklen = 0;
- cx = DES_CreateContext(key, iv, mode, PR_TRUE);
- if (cx == NULL) {
- goto loser;
- }
- rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (*outputlen != inputlen) {
- goto loser;
- }
- DES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- /*
- * Doublecheck our result by decrypting the ciphertext and
- * compare the output with the input plaintext.
- */
- cx = DES_CreateContext(key, iv, mode, PR_FALSE);
- if (cx == NULL) {
- goto loser;
- }
- rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
- output, *outputlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (doublechecklen != *outputlen) {
- goto loser;
- }
- DES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- if (memcmp(doublecheck, input, inputlen) != 0) {
- goto loser;
- }
- rv = SECSuccess;
- loser:
- if (cx != NULL) {
- DES_DestroyContext(cx, PR_TRUE);
- }
- return rv;
- }
- SECStatus
- tdea_decrypt_buf(
- int mode,
- const unsigned char *key,
- const unsigned char *iv,
- unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
- const unsigned char *input, unsigned int inputlen)
- {
- SECStatus rv = SECFailure;
- DESContext *cx;
- unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
- unsigned int doublechecklen = 0;
- cx = DES_CreateContext(key, iv, mode, PR_FALSE);
- if (cx == NULL) {
- goto loser;
- }
- rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
- input, inputlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (*outputlen != inputlen) {
- goto loser;
- }
- DES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- /*
- * Doublecheck our result by encrypting the plaintext and
- * compare the output with the input ciphertext.
- */
- cx = DES_CreateContext(key, iv, mode, PR_TRUE);
- if (cx == NULL) {
- goto loser;
- }
- rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
- output, *outputlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (doublechecklen != *outputlen) {
- goto loser;
- }
- DES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- if (memcmp(doublecheck, input, inputlen) != 0) {
- goto loser;
- }
- rv = SECSuccess;
- loser:
- if (cx != NULL) {
- DES_DestroyContext(cx, PR_TRUE);
- }
- return rv;
- }
- /*
- * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
- * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
- * and MMT have the same structure: given the key and IV (CBC mode
- * only), encrypt the given plaintext or decrypt the given ciphertext.
- * So we can handle them the same way.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- tdea_kat_mmt(char *reqfn)
- {
- char buf[180]; /* holds one line from the input REQUEST file.
- * needs to be large enough to hold the longest
- * line "CIPHERTEXT = <180 hex digits>\n".
- */
- FILE *req; /* input stream from the REQUEST file */
- FILE *resp; /* output stream to the RESPONSE file */
- int i, j;
- int mode; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
- int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */
- unsigned char key[24]; /* TDEA 3 key bundle */
- unsigned int numKeys = 0;
- unsigned char iv[8]; /* for all modes except ECB */
- unsigned char plaintext[8*20]; /* 1 to 20 blocks */
- unsigned int plaintextlen;
- unsigned char ciphertext[8*20]; /* 1 to 20 blocks */
- unsigned int ciphertextlen;
- SECStatus rv;
- req = fopen(reqfn, "r");
- resp = stdout;
- while (fgets(buf, sizeof buf, req) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, resp);
- continue;
- }
- /* [ENCRYPT] or [DECRYPT] */
- if (buf[0] == '[') {
- if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
- crypt = ENCRYPT;
- } else {
- crypt = DECRYPT;
- }
- fputs(buf, resp);
- continue;
- }
- /* NumKeys */
- if (strncmp(&buf[0], "NumKeys", 7) == 0) {
- i = 7;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- numKeys = buf[i];
- fputs(buf, resp);
- continue;
- }
- /* "COUNT = x" begins a new data set */
- if (strncmp(buf, "COUNT", 5) == 0) {
- /* mode defaults to ECB, if dataset has IV mode will be set CBC */
- mode = NSS_DES_EDE3;
- /* zeroize the variables for the test with this data set */
- memset(key, 0, sizeof key);
- memset(iv, 0, sizeof iv);
- memset(plaintext, 0, sizeof plaintext);
- plaintextlen = 0;
- memset(ciphertext, 0, sizeof ciphertext);
- ciphertextlen = 0;
- fputs(buf, resp);
- continue;
- }
- if (numKeys == 0) {
- if (strncmp(buf, "KEYs", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- key[j+8] = key[j];
- key[j+16] = key[j];
- }
- fputs(buf, resp);
- continue;
- }
- } else {
- /* KEY1 = ... */
- if (strncmp(buf, "KEY1", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- fputs(buf, resp);
- continue;
- }
- /* KEY2 = ... */
- if (strncmp(buf, "KEY2", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=8; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- fputs(buf, resp);
- continue;
- }
- /* KEY3 = ... */
- if (strncmp(buf, "KEY3", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=16; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- fputs(buf, resp);
- continue;
- }
- }
- /* IV = ... */
- if (strncmp(buf, "IV", 2) == 0) {
- mode = NSS_DES_EDE3_CBC;
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof iv; i+=2,j++) {
- hex_to_byteval(&buf[i], &iv[j]);
- }
- fputs(buf, resp);
- continue;
- }
- /* PLAINTEXT = ... */
- if (strncmp(buf, "PLAINTEXT", 9) == 0) {
- /* sanity check */
- if (crypt != ENCRYPT) {
- goto loser;
- }
- i = 9;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &plaintext[j]);
- }
- plaintextlen = j;
- rv = tdea_encrypt_buf(mode, key,
- (mode == NSS_DES_EDE3) ? NULL : iv,
- ciphertext, &ciphertextlen, sizeof ciphertext,
- plaintext, plaintextlen);
- if (rv != SECSuccess) {
- goto loser;
- }
-
- fputs(buf, resp);
- fputs("CIPHERTEXT = ", resp);
- to_hex_str(buf, ciphertext, ciphertextlen);
- fputs(buf, resp);
- fputc('\n', resp);
- continue;
- }
- /* CIPHERTEXT = ... */
- if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
- /* sanity check */
- if (crypt != DECRYPT) {
- goto loser;
- }
-
- i = 10;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &ciphertext[j]);
- }
- ciphertextlen = j;
-
- rv = tdea_decrypt_buf(mode, key,
- (mode == NSS_DES_EDE3) ? NULL : iv,
- plaintext, &plaintextlen, sizeof plaintext,
- ciphertext, ciphertextlen);
- if (rv != SECSuccess) {
- goto loser;
- }
-
- fputs(buf, resp);
- fputs("PLAINTEXT = ", resp);
- to_hex_str(buf, plaintext, plaintextlen);
- fputs(buf, resp);
- fputc('\n', resp);
- continue;
- }
- }
- loser:
- fclose(req);
- }
- /*
- * Set the parity bit for the given byte
- */
- BYTE odd_parity( BYTE in)
- {
- BYTE out = in;
- in ^= in >> 4;
- in ^= in >> 2;
- in ^= in >> 1;
- return (BYTE)(out ^ !(in & 1));
- }
- /*
- * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
- * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
- */
- void
- tdea_mct_next_keys(unsigned char *key,
- const unsigned char *text_2, const unsigned char *text_1,
- const unsigned char *text, unsigned int numKeys)
- {
- int k;
- /* key1[i+1] = key1[i] xor PT/CT[j] */
- for (k=0; k<8; k++) {
- key[k] ^= text[k];
- }
- /* key2 */
- if (numKeys == 2 || numKeys == 3) {
- /* key2 independent */
- for (k=8; k<16; k++) {
- /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
- key[k] ^= text_1[k-8];
- }
- } else {
- /* key2 == key 1 */
- for (k=8; k<16; k++) {
- /* key2[i+1] = KEY2[i] xor PT/CT[j] */
- key[k] = key[k-8];
- }
- }
- /* key3 */
- if (numKeys == 1 || numKeys == 2) {
- /* key3 == key 1 */
- for (k=16; k<24; k++) {
- /* key3[i+1] = KEY3[i] xor PT/CT[j] */
- key[k] = key[k-16];
- }
- } else {
- /* key3 independent */
- for (k=16; k<24; k++) {
- /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
- key[k] ^= text_2[k-16];
- }
- }
- /* set the parity bits */
- for (k=0; k<24; k++) {
- key[k] = odd_parity(key[k]);
- }
- }
- /*
- * Perform the Monte Carlo Test
- *
- * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
- * crypt = ENCRYPT || DECRYPT
- * inputtext = plaintext or Cyphertext depending on the value of crypt
- * inputlength is expected to be size 8 bytes
- * iv = needs to be set for NSS_DES_EDE3_CBC mode
- * resp = is the output response file.
- */
- void
- tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys,
- unsigned int crypt, unsigned char* inputtext,
- unsigned int inputlength, unsigned char* iv, FILE *resp) {
- int i, j;
- unsigned char outputtext_1[8]; /* PT/CT[j-1] */
- unsigned char outputtext_2[8]; /* PT/CT[j-2] */
- char buf[80]; /* holds one line from the input REQUEST file. */
- unsigned int outputlen;
- unsigned char outputtext[8];
-
-
- SECStatus rv;
- if (mode == NSS_DES_EDE3 && iv != NULL) {
- printf("IV must be NULL for NSS_DES_EDE3 mode");
- goto loser;
- } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
- printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
- goto loser;
- }
- /* loop 400 times */
- for (i=0; i<400; i++) {
- /* if i == 0 CV[0] = IV not necessary */
- /* record the count and key values and plainText */
- sprintf(buf, "COUNT = %d\n", i);
- fputs(buf, resp);
- /* Output KEY1[i] */
- fputs("KEY1 = ", resp);
- to_hex_str(buf, key, 8);
- fputs(buf, resp);
- fputc('\n', resp);
- /* Output KEY2[i] */
- fputs("KEY2 = ", resp);
- to_hex_str(buf, &key[8], 8);
- fputs(buf, resp);
- fputc('\n', resp);
- /* Output KEY3[i] */
- fputs("KEY3 = ", resp);
- to_hex_str(buf, &key[16], 8);
- fputs(buf, resp);
- fputc('\n', resp);
- if (mode == NSS_DES_EDE3_CBC) {
- /* Output CV[i] */
- fputs("IV = ", resp);
- to_hex_str(buf, iv, 8);
- fputs(buf, resp);
- fputc('\n', resp);
- }
- if (crypt == ENCRYPT) {
- /* Output PT[0] */
- fputs("PLAINTEXT = ", resp);
- } else {
- /* Output CT[0] */
- fputs("CIPHERTEXT = ", resp);
- }
- to_hex_str(buf, inputtext, inputlength);
- fputs(buf, resp);
- fputc('\n', resp);
- /* loop 10,000 times */
- for (j=0; j<10000; j++) {
- outputlen = 0;
- if (crypt == ENCRYPT) {
- /* inputtext == ciphertext outputtext == plaintext*/
- rv = tdea_encrypt_buf(mode, key,
- (mode == NSS_DES_EDE3) ? NULL : iv,
- outputtext, &outputlen, 8,
- inputtext, 8);
- } else {
- /* inputtext == plaintext outputtext == ciphertext */
- rv = tdea_decrypt_buf(mode, key,
- (mode == NSS_DES_EDE3) ? NULL : iv,
- outputtext, &outputlen, 8,
- inputtext, 8);
- }
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != inputlength) {
- goto loser;
- }
- if (mode == NSS_DES_EDE3_CBC) {
- if (crypt == ENCRYPT) {
- if (j == 0) {
- /*P[j+1] = CV[0] */
- memcpy(inputtext, iv, 8);
- } else {
- /* p[j+1] = C[j-1] */
- memcpy(inputtext, outputtext_1, 8);
- }
- /* CV[j+1] = C[j] */
- memcpy(iv, outputtext, 8);
- if (j != 9999) {
- /* save C[j-1] */
- memcpy(outputtext_1, outputtext, 8);
- }
- } else { /* DECRYPT */
- /* CV[j+1] = C[j] */
- memcpy(iv, inputtext, 8);
- /* C[j+1] = P[j] */
- memcpy(inputtext, outputtext, 8);
- }
- } else {
- /* ECB mode PT/CT[j+1] = CT/PT[j] */
- memcpy(inputtext, outputtext, 8);
- }
- /* Save PT/CT[j-2] and PT/CT[j-1] */
- if (j==9997) memcpy(outputtext_2, outputtext, 8);
- if (j==9998) memcpy(outputtext_1, outputtext, 8);
- /* done at the end of the for(j) loop */
- }
- if (crypt == ENCRYPT) {
- /* Output CT[j] */
- fputs("CIPHERTEXT = ", resp);
- } else {
- /* Output PT[j] */
- fputs("PLAINTEXT = ", resp);
- }
- to_hex_str(buf, outputtext, 8);
- fputs(buf, resp);
- fputc('\n', resp);
- /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
- * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
- */
- tdea_mct_next_keys(key, outputtext_2,
- outputtext_1, outputtext, numKeys);
- if (mode == NSS_DES_EDE3_CBC) {
- /* taken care of in the j=9999 iteration */
- if (crypt == ENCRYPT) {
- /* P[i] = C[j-1] */
- /* CV[i] = C[j] */
- } else {
- /* taken care of in the j=9999 iteration */
- /* CV[i] = C[j] */
- /* C[i] = P[j] */
- }
- } else {
- /* ECB PT/CT[i] = PT/CT[j] */
- memcpy(inputtext, outputtext, 8);
- }
- /* done at the end of the for(i) loop */
- fputc('\n', resp);
- }
- loser:
- return;
- }
- /*
- * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
- * by gathering the input from the request file, and then
- * calling tdea_mct_test.
- *
- * reqfn is the pathname of the input REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- tdea_mct(int mode, char *reqfn)
- {
- int i, j;
- char buf[80]; /* holds one line from the input REQUEST file. */
- FILE *req; /* input stream from the REQUEST file */
- FILE *resp; /* output stream to the RESPONSE file */
- unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
- unsigned char key[24]; /* TDEA 3 key bundle */
- unsigned int numKeys = 0;
- unsigned char plaintext[8]; /* PT[j] */
- unsigned char ciphertext[8]; /* CT[j] */
- unsigned char iv[8];
- /* zeroize the variables for the test with this data set */
- memset(key, 0, sizeof key);
- memset(plaintext, 0, sizeof plaintext);
- memset(ciphertext, 0, sizeof ciphertext);
- memset(iv, 0, sizeof iv);
- req = fopen(reqfn, "r");
- resp = stdout;
- while (fgets(buf, sizeof buf, req) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, resp);
- continue;
- }
- /* [ENCRYPT] or [DECRYPT] */
- if (buf[0] == '[') {
- if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
- crypt = ENCRYPT;
- } else {
- crypt = DECRYPT;
- }
- fputs(buf, resp);
- continue;
- }
- /* NumKeys */
- if (strncmp(&buf[0], "NumKeys", 7) == 0) {
- i = 7;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- numKeys = atoi(&buf[i]);
- continue;
- }
- /* KEY1 = ... */
- if (strncmp(buf, "KEY1", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- continue;
- }
- /* KEY2 = ... */
- if (strncmp(buf, "KEY2", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=8; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- continue;
- }
- /* KEY3 = ... */
- if (strncmp(buf, "KEY3", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=16; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- continue;
- }
- /* IV = ... */
- if (strncmp(buf, "IV", 2) == 0) {
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof iv; i+=2,j++) {
- hex_to_byteval(&buf[i], &iv[j]);
- }
- continue;
- }
- /* PLAINTEXT = ... */
- if (strncmp(buf, "PLAINTEXT", 9) == 0) {
- /* sanity check */
- if (crypt != ENCRYPT) {
- goto loser;
- }
- /* PT[0] = PT */
- i = 9;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof plaintext; i+=2,j++) {
- hex_to_byteval(&buf[i], &plaintext[j]);
- }
- /* do the Monte Carlo test */
- if (mode==NSS_DES_EDE3) {
- tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
- } else {
- tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
- }
- continue;
- }
- /* CIPHERTEXT = ... */
- if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
- /* sanity check */
- if (crypt != DECRYPT) {
- goto loser;
- }
- /* CT[0] = CT */
- i = 10;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &ciphertext[j]);
- }
-
- /* do the Monte Carlo test */
- if (mode==NSS_DES_EDE3) {
- tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
- } else {
- tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
- }
- continue;
- }
- }
- loser:
- fclose(req);
- }
- SECStatus
- aes_encrypt_buf(
- int mode,
- const unsigned char *key, unsigned int keysize,
- const unsigned char *iv,
- unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
- const unsigned char *input, unsigned int inputlen)
- {
- SECStatus rv = SECFailure;
- AESContext *cx;
- unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
- unsigned int doublechecklen = 0;
- cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
- if (cx == NULL) {
- goto loser;
- }
- rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (*outputlen != inputlen) {
- goto loser;
- }
- AES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- /*
- * Doublecheck our result by decrypting the ciphertext and
- * compare the output with the input plaintext.
- */
- cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
- if (cx == NULL) {
- goto loser;
- }
- rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
- output, *outputlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (doublechecklen != *outputlen) {
- goto loser;
- }
- AES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- if (memcmp(doublecheck, input, inputlen) != 0) {
- goto loser;
- }
- rv = SECSuccess;
- loser:
- if (cx != NULL) {
- AES_DestroyContext(cx, PR_TRUE);
- }
- return rv;
- }
- SECStatus
- aes_decrypt_buf(
- int mode,
- const unsigned char *key, unsigned int keysize,
- const unsigned char *iv,
- unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
- const unsigned char *input, unsigned int inputlen)
- {
- SECStatus rv = SECFailure;
- AESContext *cx;
- unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
- unsigned int doublechecklen = 0;
- cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
- if (cx == NULL) {
- goto loser;
- }
- rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
- input, inputlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (*outputlen != inputlen) {
- goto loser;
- }
- AES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- /*
- * Doublecheck our result by encrypting the plaintext and
- * compare the output with the input ciphertext.
- */
- cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
- if (cx == NULL) {
- goto loser;
- }
- rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
- output, *outputlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (doublechecklen != *outputlen) {
- goto loser;
- }
- AES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- if (memcmp(doublecheck, input, inputlen) != 0) {
- goto loser;
- }
- rv = SECSuccess;
- loser:
- if (cx != NULL) {
- AES_DestroyContext(cx, PR_TRUE);
- }
- return rv;
- }
- /*
- * Perform the AES Known Answer Test (KAT) or Multi-block Message
- * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
- * and MMT have the same structure: given the key and IV (CBC mode
- * only), encrypt the given plaintext or decrypt the given ciphertext.
- * So we can handle them the same way.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- aes_kat_mmt(char *reqfn)
- {
- char buf[512]; /* holds one line from the input REQUEST file.
- * needs to be large enough to hold the longest
- * line "CIPHERTEXT = <320 hex digits>\n".
- */
- FILE *aesreq; /* input stream from the REQUEST file */
- FILE *aesresp; /* output stream to the RESPONSE file */
- int i, j;
- int mode; /* NSS_AES (ECB) or NSS_AES_CBC */
- int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
- unsigned char key[32]; /* 128, 192, or 256 bits */
- unsigned int keysize;
- unsigned char iv[16]; /* for all modes except ECB */
- unsigned char plaintext[10*16]; /* 1 to 10 blocks */
- unsigned int plaintextlen;
- unsigned char ciphertext[10*16]; /* 1 to 10 blocks */
- unsigned int ciphertextlen;
- SECStatus rv;
- aesreq = fopen(reqfn, "r");
- aesresp = stdout;
- while (fgets(buf, sizeof buf, aesreq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, aesresp);
- continue;
- }
- /* [ENCRYPT] or [DECRYPT] */
- if (buf[0] == '[') {
- if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
- encrypt = 1;
- } else {
- encrypt = 0;
- }
- fputs(buf, aesresp);
- continue;
- }
- /* "COUNT = x" begins a new data set */
- if (strncmp(buf, "COUNT", 5) == 0) {
- mode = NSS_AES;
- /* zeroize the variables for the test with this data set */
- memset(key, 0, sizeof key);
- keysize = 0;
- memset(iv, 0, sizeof iv);
- memset(plaintext, 0, sizeof plaintext);
- plaintextlen = 0;
- memset(ciphertext, 0, sizeof ciphertext);
- ciphertextlen = 0;
- fputs(buf, aesresp);
- continue;
- }
- /* KEY = ... */
- if (strncmp(buf, "KEY", 3) == 0) {
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- keysize = j;
- fputs(buf, aesresp);
- continue;
- }
- /* IV = ... */
- if (strncmp(buf, "IV", 2) == 0) {
- mode = NSS_AES_CBC;
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof iv; i+=2,j++) {
- hex_to_byteval(&buf[i], &iv[j]);
- }
- fputs(buf, aesresp);
- continue;
- }
- /* PLAINTEXT = ... */
- if (strncmp(buf, "PLAINTEXT", 9) == 0) {
- /* sanity check */
- if (!encrypt) {
- goto loser;
- }
- i = 9;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &plaintext[j]);
- }
- plaintextlen = j;
- rv = aes_encrypt_buf(mode, key, keysize,
- (mode == NSS_AES) ? NULL : iv,
- ciphertext, &ciphertextlen, sizeof ciphertext,
- plaintext, plaintextlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- fputs(buf, aesresp);
- fputs("CIPHERTEXT = ", aesresp);
- to_hex_str(buf, ciphertext, ciphertextlen);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- continue;
- }
- /* CIPHERTEXT = ... */
- if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
- /* sanity check */
- if (encrypt) {
- goto loser;
- }
- i = 10;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &ciphertext[j]);
- }
- ciphertextlen = j;
- rv = aes_decrypt_buf(mode, key, keysize,
- (mode == NSS_AES) ? NULL : iv,
- plaintext, &plaintextlen, sizeof plaintext,
- ciphertext, ciphertextlen);
- if (rv != SECSuccess) {
- goto loser;
- }
- fputs(buf, aesresp);
- fputs("PLAINTEXT = ", aesresp);
- to_hex_str(buf, plaintext, plaintextlen);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- continue;
- }
- }
- loser:
- fclose(aesreq);
- }
- /*
- * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
- * Test (MCT) in ECB and CBC modes.
- */
- void
- aes_mct_next_key(unsigned char *key, unsigned int keysize,
- const unsigned char *ciphertext_1, const unsigned char *ciphertext)
- {
- int k;
- switch (keysize) {
- case 16: /* 128-bit key */
- /* Key[i+1] = Key[i] xor CT[j] */
- for (k=0; k<16; k++) {
- key[k] ^= ciphertext[k];
- }
- break;
- case 24: /* 192-bit key */
- /*
- * Key[i+1] = Key[i] xor (last 64-bits of
- * CT[j-1] || CT[j])
- */
- for (k=0; k<8; k++) {
- key[k] ^= ciphertext_1[k+8];
- }
- for (k=8; k<24; k++) {
- key[k] ^= ciphertext[k-8];
- }
- break;
- case 32: /* 256-bit key */
- /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
- for (k=0; k<16; k++) {
- key[k] ^= ciphertext_1[k];
- }
- for (k=16; k<32; k++) {
- key[k] ^= ciphertext[k-16];
- }
- break;
- }
- }
- /*
- * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
- * our AES code in streaming mode because the plaintext or ciphertext
- * is generated block by block as we go, so we can't collect all the
- * plaintext or ciphertext in one buffer and encrypt or decrypt it in
- * one shot.
- *
- * reqfn is the pathname of the input REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- aes_ecb_mct(char *reqfn)
- {
- char buf[80]; /* holds one line from the input REQUEST file.
- * needs to be large enough to hold the longest
- * line "KEY = <64 hex digits>\n".
- */
- FILE *aesreq; /* input stream from the REQUEST file */
- FILE *aesresp; /* output stream to the RESPONSE file */
- int i, j;
- int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
- unsigned char key[32]; /* 128, 192, or 256 bits */
- unsigned int keysize;
- unsigned char plaintext[16]; /* PT[j] */
- unsigned char plaintext_1[16]; /* PT[j-1] */
- unsigned char ciphertext[16]; /* CT[j] */
- unsigned char ciphertext_1[16]; /* CT[j-1] */
- unsigned char doublecheck[16];
- unsigned int outputlen;
- AESContext *cx = NULL; /* the operation being tested */
- AESContext *cx2 = NULL; /* the inverse operation done in parallel
- * to doublecheck our result.
- */
- SECStatus rv;
- aesreq = fopen(reqfn, "r");
- aesresp = stdout;
- while (fgets(buf, sizeof buf, aesreq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, aesresp);
- continue;
- }
- /* [ENCRYPT] or [DECRYPT] */
- if (buf[0] == '[') {
- if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
- encrypt = 1;
- } else {
- encrypt = 0;
- }
- fputs(buf, aesresp);
- continue;
- }
- /* "COUNT = x" begins a new data set */
- if (strncmp(buf, "COUNT", 5) == 0) {
- /* zeroize the variables for the test with this data set */
- memset(key, 0, sizeof key);
- keysize = 0;
- memset(plaintext, 0, sizeof plaintext);
- memset(ciphertext, 0, sizeof ciphertext);
- continue;
- }
- /* KEY = ... */
- if (strncmp(buf, "KEY", 3) == 0) {
- /* Key[0] = Key */
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- keysize = j;
- continue;
- }
- /* PLAINTEXT = ... */
- if (strncmp(buf, "PLAINTEXT", 9) == 0) {
- /* sanity check */
- if (!encrypt) {
- goto loser;
- }
- /* PT[0] = PT */
- i = 9;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof plaintext; i+=2,j++) {
- hex_to_byteval(&buf[i], &plaintext[j]);
- }
- for (i=0; i<100; i++) {
- sprintf(buf, "COUNT = %d\n", i);
- fputs(buf, aesresp);
- /* Output Key[i] */
- fputs("KEY = ", aesresp);
- to_hex_str(buf, key, keysize);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Output PT[0] */
- fputs("PLAINTEXT = ", aesresp);
- to_hex_str(buf, plaintext, sizeof plaintext);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- cx = AES_CreateContext(key, NULL, NSS_AES,
- PR_TRUE, keysize, 16);
- if (cx == NULL) {
- goto loser;
- }
- /*
- * doublecheck our result by decrypting the result
- * and comparing the output with the plaintext.
- */
- cx2 = AES_CreateContext(key, NULL, NSS_AES,
- PR_FALSE, keysize, 16);
- if (cx2 == NULL) {
- goto loser;
- }
- for (j=0; j<1000; j++) {
- /* Save CT[j-1] */
- memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
- /* CT[j] = AES(Key[i], PT[j]) */
- outputlen = 0;
- rv = AES_Encrypt(cx,
- ciphertext, &outputlen, sizeof ciphertext,
- plaintext, sizeof plaintext);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != sizeof plaintext) {
- goto loser;
- }
- /* doublecheck our result */
- outputlen = 0;
- rv = AES_Decrypt(cx2,
- doublecheck, &outputlen, sizeof doublecheck,
- ciphertext, sizeof ciphertext);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != sizeof ciphertext) {
- goto loser;
- }
- if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
- goto loser;
- }
- /* PT[j+1] = CT[j] */
- memcpy(plaintext, ciphertext, sizeof plaintext);
- }
- AES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- AES_DestroyContext(cx2, PR_TRUE);
- cx2 = NULL;
- /* Output CT[j] */
- fputs("CIPHERTEXT = ", aesresp);
- to_hex_str(buf, ciphertext, sizeof ciphertext);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Key[i+1] = Key[i] xor ... */
- aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
- /* PT[0] = CT[j] */
- /* done at the end of the for(j) loop */
- fputc('\n', aesresp);
- }
- continue;
- }
- /* CIPHERTEXT = ... */
- if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
- /* sanity check */
- if (encrypt) {
- goto loser;
- }
- /* CT[0] = CT */
- i = 10;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &ciphertext[j]);
- }
- for (i=0; i<100; i++) {
- sprintf(buf, "COUNT = %d\n", i);
- fputs(buf, aesresp);
- /* Output Key[i] */
- fputs("KEY = ", aesresp);
- to_hex_str(buf, key, keysize);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Output CT[0] */
- fputs("CIPHERTEXT = ", aesresp);
- to_hex_str(buf, ciphertext, sizeof ciphertext);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- cx = AES_CreateContext(key, NULL, NSS_AES,
- PR_FALSE, keysize, 16);
- if (cx == NULL) {
- goto loser;
- }
- /*
- * doublecheck our result by encrypting the result
- * and comparing the output with the ciphertext.
- */
- cx2 = AES_CreateContext(key, NULL, NSS_AES,
- PR_TRUE, keysize, 16);
- if (cx2 == NULL) {
- goto loser;
- }
- for (j=0; j<1000; j++) {
- /* Save PT[j-1] */
- memcpy(plaintext_1, plaintext, sizeof plaintext);
- /* PT[j] = AES(Key[i], CT[j]) */
- outputlen = 0;
- rv = AES_Decrypt(cx,
- plaintext, &outputlen, sizeof plaintext,
- ciphertext, sizeof ciphertext);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != sizeof ciphertext) {
- goto loser;
- }
- /* doublecheck our result */
- outputlen = 0;
- rv = AES_Encrypt(cx2,
- doublecheck, &outputlen, sizeof doublecheck,
- plaintext, sizeof plaintext);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != sizeof plaintext) {
- goto loser;
- }
- if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
- goto loser;
- }
- /* CT[j+1] = PT[j] */
- memcpy(ciphertext, plaintext, sizeof ciphertext);
- }
- AES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- AES_DestroyContext(cx2, PR_TRUE);
- cx2 = NULL;
- /* Output PT[j] */
- fputs("PLAINTEXT = ", aesresp);
- to_hex_str(buf, plaintext, sizeof plaintext);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Key[i+1] = Key[i] xor ... */
- aes_mct_next_key(key, keysize, plaintext_1, plaintext);
- /* CT[0] = PT[j] */
- /* done at the end of the for(j) loop */
- fputc('\n', aesresp);
- }
- continue;
- }
- }
- loser:
- if (cx != NULL) {
- AES_DestroyContext(cx, PR_TRUE);
- }
- if (cx2 != NULL) {
- AES_DestroyContext(cx2, PR_TRUE);
- }
- fclose(aesreq);
- }
- /*
- * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
- * our AES code in streaming mode because the plaintext or ciphertext
- * is generated block by block as we go, so we can't collect all the
- * plaintext or ciphertext in one buffer and encrypt or decrypt it in
- * one shot.
- *
- * reqfn is the pathname of the input REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- aes_cbc_mct(char *reqfn)
- {
- char buf[80]; /* holds one line from the input REQUEST file.
- * needs to be large enough to hold the longest
- * line "KEY = <64 hex digits>\n".
- */
- FILE *aesreq; /* input stream from the REQUEST file */
- FILE *aesresp; /* output stream to the RESPONSE file */
- int i, j;
- int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
- unsigned char key[32]; /* 128, 192, or 256 bits */
- unsigned int keysize;
- unsigned char iv[16];
- unsigned char plaintext[16]; /* PT[j] */
- unsigned char plaintext_1[16]; /* PT[j-1] */
- unsigned char ciphertext[16]; /* CT[j] */
- unsigned char ciphertext_1[16]; /* CT[j-1] */
- unsigned char doublecheck[16];
- unsigned int outputlen;
- AESContext *cx = NULL; /* the operation being tested */
- AESContext *cx2 = NULL; /* the inverse operation done in parallel
- * to doublecheck our result.
- */
- SECStatus rv;
- aesreq = fopen(reqfn, "r");
- aesresp = stdout;
- while (fgets(buf, sizeof buf, aesreq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, aesresp);
- continue;
- }
- /* [ENCRYPT] or [DECRYPT] */
- if (buf[0] == '[') {
- if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
- encrypt = 1;
- } else {
- encrypt = 0;
- }
- fputs(buf, aesresp);
- continue;
- }
- /* "COUNT = x" begins a new data set */
- if (strncmp(buf, "COUNT", 5) == 0) {
- /* zeroize the variables for the test with this data set */
- memset(key, 0, sizeof key);
- keysize = 0;
- memset(iv, 0, sizeof iv);
- memset(plaintext, 0, sizeof plaintext);
- memset(ciphertext, 0, sizeof ciphertext);
- continue;
- }
- /* KEY = ... */
- if (strncmp(buf, "KEY", 3) == 0) {
- /* Key[0] = Key */
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- keysize = j;
- continue;
- }
- /* IV = ... */
- if (strncmp(buf, "IV", 2) == 0) {
- /* IV[0] = IV */
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof iv; i+=2,j++) {
- hex_to_byteval(&buf[i], &iv[j]);
- }
- continue;
- }
- /* PLAINTEXT = ... */
- if (strncmp(buf, "PLAINTEXT", 9) == 0) {
- /* sanity check */
- if (!encrypt) {
- goto loser;
- }
- /* PT[0] = PT */
- i = 9;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof plaintext; i+=2,j++) {
- hex_to_byteval(&buf[i], &plaintext[j]);
- }
- for (i=0; i<100; i++) {
- sprintf(buf, "COUNT = %d\n", i);
- fputs(buf, aesresp);
- /* Output Key[i] */
- fputs("KEY = ", aesresp);
- to_hex_str(buf, key, keysize);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Output IV[i] */
- fputs("IV = ", aesresp);
- to_hex_str(buf, iv, sizeof iv);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Output PT[0] */
- fputs("PLAINTEXT = ", aesresp);
- to_hex_str(buf, plaintext, sizeof plaintext);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- cx = AES_CreateContext(key, iv, NSS_AES_CBC,
- PR_TRUE, keysize, 16);
- if (cx == NULL) {
- goto loser;
- }
- /*
- * doublecheck our result by decrypting the result
- * and comparing the output with the plaintext.
- */
- cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
- PR_FALSE, keysize, 16);
- if (cx2 == NULL) {
- goto loser;
- }
- /* CT[-1] = IV[i] */
- memcpy(ciphertext, iv, sizeof ciphertext);
- for (j=0; j<1000; j++) {
- /* Save CT[j-1] */
- memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
- /*
- * If ( j=0 )
- * CT[j] = AES(Key[i], IV[i], PT[j])
- * PT[j+1] = IV[i] (= CT[j-1])
- * Else
- * CT[j] = AES(Key[i], PT[j])
- * PT[j+1] = CT[j-1]
- */
- outputlen = 0;
- rv = AES_Encrypt(cx,
- ciphertext, &outputlen, sizeof ciphertext,
- plaintext, sizeof plaintext);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != sizeof plaintext) {
- goto loser;
- }
- /* doublecheck our result */
- outputlen = 0;
- rv = AES_Decrypt(cx2,
- doublecheck, &outputlen, sizeof doublecheck,
- ciphertext, sizeof ciphertext);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != sizeof ciphertext) {
- goto loser;
- }
- if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
- goto loser;
- }
- memcpy(plaintext, ciphertext_1, sizeof plaintext);
- }
- AES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- AES_DestroyContext(cx2, PR_TRUE);
- cx2 = NULL;
- /* Output CT[j] */
- fputs("CIPHERTEXT = ", aesresp);
- to_hex_str(buf, ciphertext, sizeof ciphertext);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Key[i+1] = Key[i] xor ... */
- aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
- /* IV[i+1] = CT[j] */
- memcpy(iv, ciphertext, sizeof iv);
- /* PT[0] = CT[j-1] */
- /* done at the end of the for(j) loop */
- fputc('\n', aesresp);
- }
- continue;
- }
- /* CIPHERTEXT = ... */
- if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
- /* sanity check */
- if (encrypt) {
- goto loser;
- }
- /* CT[0] = CT */
- i = 10;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &ciphertext[j]);
- }
- for (i=0; i<100; i++) {
- sprintf(buf, "COUNT = %d\n", i);
- fputs(buf, aesresp);
- /* Output Key[i] */
- fputs("KEY = ", aesresp);
- to_hex_str(buf, key, keysize);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Output IV[i] */
- fputs("IV = ", aesresp);
- to_hex_str(buf, iv, sizeof iv);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Output CT[0] */
- fputs("CIPHERTEXT = ", aesresp);
- to_hex_str(buf, ciphertext, sizeof ciphertext);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- cx = AES_CreateContext(key, iv, NSS_AES_CBC,
- PR_FALSE, keysize, 16);
- if (cx == NULL) {
- goto loser;
- }
- /*
- * doublecheck our result by encrypting the result
- * and comparing the output with the ciphertext.
- */
- cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
- PR_TRUE, keysize, 16);
- if (cx2 == NULL) {
- goto loser;
- }
- /* PT[-1] = IV[i] */
- memcpy(plaintext, iv, sizeof plaintext);
- for (j=0; j<1000; j++) {
- /* Save PT[j-1] */
- memcpy(plaintext_1, plaintext, sizeof plaintext);
- /*
- * If ( j=0 )
- * PT[j] = AES(Key[i], IV[i], CT[j])
- * CT[j+1] = IV[i] (= PT[j-1])
- * Else
- * PT[j] = AES(Key[i], CT[j])
- * CT[j+1] = PT[j-1]
- */
- outputlen = 0;
- rv = AES_Decrypt(cx,
- plaintext, &outputlen, sizeof plaintext,
- ciphertext, sizeof ciphertext);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != sizeof ciphertext) {
- goto loser;
- }
- /* doublecheck our result */
- outputlen = 0;
- rv = AES_Encrypt(cx2,
- doublecheck, &outputlen, sizeof doublecheck,
- plaintext, sizeof plaintext);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (outputlen != sizeof plaintext) {
- goto loser;
- }
- if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
- goto loser;
- }
- memcpy(ciphertext, plaintext_1, sizeof ciphertext);
- }
- AES_DestroyContext(cx, PR_TRUE);
- cx = NULL;
- AES_DestroyContext(cx2, PR_TRUE);
- cx2 = NULL;
- /* Output PT[j] */
- fputs("PLAINTEXT = ", aesresp);
- to_hex_str(buf, plaintext, sizeof plaintext);
- fputs(buf, aesresp);
- fputc('\n', aesresp);
- /* Key[i+1] = Key[i] xor ... */
- aes_mct_next_key(key, keysize, plaintext_1, plaintext);
- /* IV[i+1] = PT[j] */
- memcpy(iv, plaintext, sizeof iv);
- /* CT[0] = PT[j-1] */
- /* done at the end of the for(j) loop */
- fputc('\n', aesresp);
- }
- continue;
- }
- }
- loser:
- if (cx != NULL) {
- AES_DestroyContext(cx, PR_TRUE);
- }
- if (cx2 != NULL) {
- AES_DestroyContext(cx2, PR_TRUE);
- }
- fclose(aesreq);
- }
- void write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
- {
- unsigned int i;
- int j, count = 0, last = -1, z = 0;
- long start = ftell(out);
- for (i=0; i<len; i++) {
- for (j=7; j>=0; j--) {
- if (last < 0) {
- last = (hash[i] & (1 << j)) ? 1 : 0;
- fprintf(out, "%d ", last);
- count = 1;
- } else if (hash[i] & (1 << j)) {
- if (last) {
- count++;
- } else {
- last = 0;
- fprintf(out, "%d ", count);
- count = 1;
- z++;
- }
- } else {
- if (!last) {
- count++;
- } else {
- last = 1;
- fprintf(out, "%d ", count);
- count = 1;
- z++;
- }
- }
- }
- }
- fprintf(out, "^\n");
- fseek(out, start, SEEK_SET);
- fprintf(out, "%d ", z);
- fseek(out, 0, SEEK_END);
- }
- int get_next_line(FILE *req, char *key, char *val, FILE *rsp)
- {
- int ignore = 0;
- char *writeto = key;
- int w = 0;
- int c;
- while ((c = fgetc(req)) != EOF) {
- if (ignore) {
- fprintf(rsp, "%c", c);
- if (c == '\n') return ignore;
- } else if (c == '\n') {
- break;
- } else if (c == '#') {
- ignore = 1;
- fprintf(rsp, "%c", c);
- } else if (c == '=') {
- writeto[w] = '\0';
- w = 0;
- writeto = val;
- } else if (c == ' ' || c == '[' || c == ']') {
- continue;
- } else {
- writeto[w++] = c;
- }
- }
- writeto[w] = '\0';
- return (c == EOF) ? -1 : ignore;
- }
- #ifdef NSS_ENABLE_ECC
- typedef struct curveNameTagPairStr {
- char *curveName;
- SECOidTag curveOidTag;
- } CurveNameTagPair;
- #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
- /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
- static CurveNameTagPair nameTagPair[] =
- {
- { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
- { "nistk163", SEC_OID_SECG_EC_SECT163K1},
- { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
- { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
- { "nistb163", SEC_OID_SECG_EC_SECT163R2},
- { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
- { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
- { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
- { "nistk233", SEC_OID_SECG_EC_SECT233K1},
- { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
- { "nistb233", SEC_OID_SECG_EC_SECT233R1},
- { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
- { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
- { "nistk283", SEC_OID_SECG_EC_SECT283K1},
- { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
- { "nistb283", SEC_OID_SECG_EC_SECT283R1},
- { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
- { "nistk409", SEC_OID_SECG_EC_SECT409K1},
- { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
- { "nistb409", SEC_OID_SECG_EC_SECT409R1},
- { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
- { "nistk571", SEC_OID_SECG_EC_SECT571K1},
- { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
- { "nistb571", SEC_OID_SECG_EC_SECT571R1},
- { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
- { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
- { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
- { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
- { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
- { "nistp192", SEC_OID_SECG_EC_SECP192R1},
- { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
- { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
- { "nistp224", SEC_OID_SECG_EC_SECP224R1},
- { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
- { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
- { "nistp256", SEC_OID_SECG_EC_SECP256R1},
- { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
- { "nistp384", SEC_OID_SECG_EC_SECP384R1},
- { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
- { "nistp521", SEC_OID_SECG_EC_SECP521R1},
- { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
- { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
- { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
- { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
- { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
- { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
- { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
- { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
- { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
- { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
- { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
- { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
- { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
- { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
- { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
- { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
- { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
- { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
- { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
- { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
- { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
- { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
- { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
- { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
- { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
- { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
- { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
- { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
- { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
- { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
- { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
- { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
- { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
- { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
- };
- static SECKEYECParams *
- getECParams(const char *curve)
- {
- SECKEYECParams *ecparams;
- SECOidData *oidData = NULL;
- SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
- int i, numCurves;
- if (curve != NULL) {
- numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
- for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
- i++) {
- if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
- curveOidTag = nameTagPair[i].curveOidTag;
- }
- }
- /* Return NULL if curve name is not recognized */
- if ((curveOidTag == SEC_OID_UNKNOWN) ||
- (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
- fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
- return NULL;
- }
- ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
- /*
- * ecparams->data needs to contain the ASN encoding of an object ID (OID)
- * representing the named curve. The actual OID is in
- * oidData->oid.data so we simply prepend 0x06 and OID length
- */
- ecparams->data[0] = SEC_ASN1_OBJECT_ID;
- ecparams->data[1] = oidData->oid.len;
- memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
- return ecparams;
- }
- /*
- * Perform the ECDSA Key Pair Generation Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- ecdsa_keypair_test(char *reqfn)
- {
- char buf[256]; /* holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * needs to be large enough to hold the longest
- * line "Qx = <144 hex digits>\n".
- */
- FILE *ecdsareq; /* input stream from the REQUEST file */
- FILE *ecdsaresp; /* output stream to the RESPONSE file */
- char curve[16]; /* "nistxddd" */
- ECParams *ecparams;
- int N;
- int i;
- unsigned int len;
- ecdsareq = fopen(reqfn, "r");
- ecdsaresp = stdout;
- strcpy(curve, "nist");
- while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, ecdsaresp);
- continue;
- }
- /* [X-ddd] */
- if (buf[0] == '[') {
- const char *src;
- char *dst;
- SECKEYECParams *encodedparams;
- src = &buf[1];
- dst = &curve[4];
- *dst++ = tolower(*src);
- src += 2; /* skip the hyphen */
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst = '\0';
- encodedparams = getECParams(curve);
- if (encodedparams == NULL) {
- goto loser;
- }
- if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
- goto loser;
- }
- SECITEM_FreeItem(encodedparams, PR_TRUE);
- fputs(buf, ecdsaresp);
- continue;
- }
- /* N = x */
- if (buf[0] == 'N') {
- if (sscanf(buf, "N = %d", &N) != 1) {
- goto loser;
- }
- for (i = 0; i < N; i++) {
- ECPrivateKey *ecpriv;
- if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
- goto loser;
- }
- fputs("d = ", ecdsaresp);
- to_hex_str(buf, ecpriv->privateValue.data,
- ecpriv->privateValue.len);
- fputs(buf, ecdsaresp);
- fputc('\n', ecdsaresp);
- if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
- != SECSuccess) {
- goto loser;
- }
- len = ecpriv->publicValue.len;
- if (len%2 == 0) {
- goto loser;
- }
- len = (len-1)/2;
- if (ecpriv->publicValue.data[0]
- != EC_POINT_FORM_UNCOMPRESSED) {
- goto loser;
- }
- fputs("Qx = ", ecdsaresp);
- to_hex_str(buf, &ecpriv->publicValue.data[1], len);
- fputs(buf, ecdsaresp);
- fputc('\n', ecdsaresp);
- fputs("Qy = ", ecdsaresp);
- to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
- fputs(buf, ecdsaresp);
- fputc('\n', ecdsaresp);
- fputc('\n', ecdsaresp);
- PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
- }
- PORT_FreeArena(ecparams->arena, PR_FALSE);
- continue;
- }
- }
- loser:
- fclose(ecdsareq);
- }
- /*
- * Perform the ECDSA Public Key Validation Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- ecdsa_pkv_test(char *reqfn)
- {
- char buf[256]; /* holds one line from the input REQUEST file.
- * needs to be large enough to hold the longest
- * line "Qx = <144 hex digits>\n".
- */
- FILE *ecdsareq; /* input stream from the REQUEST file */
- FILE *ecdsaresp; /* output stream to the RESPONSE file */
- char curve[16]; /* "nistxddd" */
- ECParams *ecparams = NULL;
- SECItem pubkey;
- unsigned int i;
- unsigned int len;
- PRBool keyvalid = PR_TRUE;
- ecdsareq = fopen(reqfn, "r");
- ecdsaresp = stdout;
- strcpy(curve, "nist");
- pubkey.data = NULL;
- while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, ecdsaresp);
- continue;
- }
- /* [X-ddd] */
- if (buf[0] == '[') {
- const char *src;
- char *dst;
- SECKEYECParams *encodedparams;
- src = &buf[1];
- dst = &curve[4];
- *dst++ = tolower(*src);
- src += 2; /* skip the hyphen */
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst = '\0';
- if (ecparams != NULL) {
- PORT_FreeArena(ecparams->arena, PR_FALSE);
- ecparams = NULL;
- }
- encodedparams = getECParams(curve);
- if (encodedparams == NULL) {
- goto loser;
- }
- if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
- goto loser;
- }
- SECITEM_FreeItem(encodedparams, PR_TRUE);
- len = (ecparams->fieldID.size + 7) >> 3;
- if (pubkey.data != NULL) {
- PORT_Free(pubkey.data);
- pubkey.data = NULL;
- }
- SECITEM_AllocItem(NULL, &pubkey, 2*len+1);
- if (pubkey.data == NULL) {
- goto loser;
- }
- pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
- fputs(buf, ecdsaresp);
- continue;
- }
- /* Qx = ... */
- if (strncmp(buf, "Qx", 2) == 0) {
- fputs(buf, ecdsaresp);
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
- continue;
- }
- /* Qy = ... */
- if (strncmp(buf, "Qy", 2) == 0) {
- fputs(buf, ecdsaresp);
- if (!keyvalid) {
- fputs("Result = F\n", ecdsaresp);
- continue;
- }
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]);
- if (!keyvalid) {
- fputs("Result = F\n", ecdsaresp);
- continue;
- }
- if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
- fputs("Result = P\n", ecdsaresp);
- } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
- fputs("Result = F\n", ecdsaresp);
- } else {
- goto loser;
- }
- continue;
- }
- }
- loser:
- if (ecparams != NULL) {
- PORT_FreeArena(ecparams->arena, PR_FALSE);
- }
- if (pubkey.data != NULL) {
- PORT_Free(pubkey.data);
- }
- fclose(ecdsareq);
- }
- /*
- * Perform the ECDSA Signature Generation Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- ecdsa_siggen_test(char *reqfn)
- {
- char buf[1024]; /* holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * needs to be large enough to hold the longest
- * line "Msg = <256 hex digits>\n".
- */
- FILE *ecdsareq; /* input stream from the REQUEST file */
- FILE *ecdsaresp; /* output stream to the RESPONSE file */
- char curve[16]; /* "nistxddd" */
- ECParams *ecparams = NULL;
- int i, j;
- unsigned int len;
- unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
- unsigned int msglen;
- unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
- unsigned char sig[2*MAX_ECKEY_LEN];
- SECItem signature, digest;
- ecdsareq = fopen(reqfn, "r");
- ecdsaresp = stdout;
- strcpy(curve, "nist");
- while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, ecdsaresp);
- continue;
- }
- /* [X-ddd] */
- if (buf[0] == '[') {
- const char *src;
- char *dst;
- SECKEYECParams *encodedparams;
- src = &buf[1];
- dst = &curve[4];
- *dst++ = tolower(*src);
- src += 2; /* skip the hyphen */
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst = '\0';
- if (ecparams != NULL) {
- PORT_FreeArena(ecparams->arena, PR_FALSE);
- ecparams = NULL;
- }
- encodedparams = getECParams(curve);
- if (encodedparams == NULL) {
- goto loser;
- }
- if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
- goto loser;
- }
- SECITEM_FreeItem(encodedparams, PR_TRUE);
- fputs(buf, ecdsaresp);
- continue;
- }
- /* Msg = ... */
- if (strncmp(buf, "Msg", 3) == 0) {
- ECPrivateKey *ecpriv;
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &msg[j]);
- }
- msglen = j;
- if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
- goto loser;
- }
- fputs(buf, ecdsaresp);
- if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
- goto loser;
- }
- if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
- != SECSuccess) {
- goto loser;
- }
- len = ecpriv->publicValue.len;
- if (len%2 == 0) {
- goto loser;
- }
- len = (len-1)/2;
- if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
- goto loser;
- }
- fputs("Qx = ", ecdsaresp);
- to_hex_str(buf, &ecpriv->publicValue.data[1], len);
- fputs(buf, ecdsaresp);
- fputc('\n', ecdsaresp);
- fputs("Qy = ", ecdsaresp);
- to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
- fputs(buf, ecdsaresp);
- fputc('\n', ecdsaresp);
- digest.type = siBuffer;
- digest.data = sha1;
- digest.len = sizeof sha1;
- signature.type = siBuffer;
- signature.data = sig;
- signature.len = sizeof sig;
- if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
- goto loser;
- }
- len = signature.len;
- if (len%2 != 0) {
- goto loser;
- }
- len = len/2;
- fputs("R = ", ecdsaresp);
- to_hex_str(buf, &signature.data[0], len);
- fputs(buf, ecdsaresp);
- fputc('\n', ecdsaresp);
- fputs("S = ", ecdsaresp);
- to_hex_str(buf, &signature.data[len], len);
- fputs(buf, ecdsaresp);
- fputc('\n', ecdsaresp);
- PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
- continue;
- }
- }
- loser:
- if (ecparams != NULL) {
- PORT_FreeArena(ecparams->arena, PR_FALSE);
- }
- fclose(ecdsareq);
- }
- /*
- * Perform the ECDSA Signature Verification Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- ecdsa_sigver_test(char *reqfn)
- {
- char buf[1024]; /* holds one line from the input REQUEST file.
- * needs to be large enough to hold the longest
- * line "Msg = <256 hex digits>\n".
- */
- FILE *ecdsareq; /* input stream from the REQUEST file */
- FILE *ecdsaresp; /* output stream to the RESPONSE file */
- char curve[16]; /* "nistxddd" */
- ECPublicKey ecpub;
- unsigned int i, j;
- unsigned int flen; /* length in bytes of the field size */
- unsigned int olen; /* length in bytes of the base point order */
- unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
- unsigned int msglen;
- unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
- unsigned char sig[2*MAX_ECKEY_LEN];
- SECItem signature, digest;
- PRBool keyvalid = PR_TRUE;
- PRBool sigvalid = PR_TRUE;
- ecdsareq = fopen(reqfn, "r");
- ecdsaresp = stdout;
- ecpub.ecParams.arena = NULL;
- strcpy(curve, "nist");
- while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, ecdsaresp);
- continue;
- }
- /* [X-ddd] */
- if (buf[0] == '[') {
- const char *src;
- char *dst;
- SECKEYECParams *encodedparams;
- ECParams *ecparams;
- src = &buf[1];
- dst = &curve[4];
- *dst++ = tolower(*src);
- src += 2; /* skip the hyphen */
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst = '\0';
- encodedparams = getECParams(curve);
- if (encodedparams == NULL) {
- goto loser;
- }
- if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
- goto loser;
- }
- SECITEM_FreeItem(encodedparams, PR_TRUE);
- if (ecpub.ecParams.arena != NULL) {
- PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
- }
- ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (ecpub.ecParams.arena == NULL) {
- goto loser;
- }
- if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams)
- != SECSuccess) {
- goto loser;
- }
- PORT_FreeArena(ecparams->arena, PR_FALSE);
- flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
- olen = ecpub.ecParams.order.len;
- if (2*olen > sizeof sig) {
- goto loser;
- }
- ecpub.publicValue.type = siBuffer;
- ecpub.publicValue.data = NULL;
- ecpub.publicValue.len = 0;
- SECITEM_AllocItem(ecpub.ecParams.arena,
- &ecpub.publicValue, 2*flen+1);
- if (ecpub.publicValue.data == NULL) {
- goto loser;
- }
- ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
- fputs(buf, ecdsaresp);
- continue;
- }
- /* Msg = ... */
- if (strncmp(buf, "Msg", 3) == 0) {
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &msg[j]);
- }
- msglen = j;
- if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
- goto loser;
- }
- fputs(buf, ecdsaresp);
- digest.type = siBuffer;
- digest.data = sha1;
- digest.len = sizeof sha1;
- continue;
- }
- /* Qx = ... */
- if (strncmp(buf, "Qx", 2) == 0) {
- fputs(buf, ecdsaresp);
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
- &buf[i]);
- continue;
- }
- /* Qy = ... */
- if (strncmp(buf, "Qy", 2) == 0) {
- fputs(buf, ecdsaresp);
- if (!keyvalid) {
- continue;
- }
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen,
- &buf[i]);
- if (!keyvalid) {
- continue;
- }
- if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue)
- != SECSuccess) {
- if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
- keyvalid = PR_FALSE;
- } else {
- goto loser;
- }
- }
- continue;
- }
- /* R = ... */
- if (buf[0] == 'R') {
- fputs(buf, ecdsaresp);
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- sigvalid = from_hex_str(sig, olen, &buf[i]);
- continue;
- }
- /* S = ... */
- if (buf[0] == 'S') {
- fputs(buf, ecdsaresp);
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- if (sigvalid) {
- sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
- }
- signature.type = siBuffer;
- signature.data = sig;
- signature.len = 2*olen;
- if (!keyvalid || !sigvalid) {
- fputs("Result = F\n", ecdsaresp);
- } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest)
- == SECSuccess) {
- fputs("Result = P\n", ecdsaresp);
- } else {
- fputs("Result = F\n", ecdsaresp);
- }
- continue;
- }
- }
- loser:
- if (ecpub.ecParams.arena != NULL) {
- PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
- }
- fclose(ecdsareq);
- }
- #endif /* NSS_ENABLE_ECC */
- /*
- * Read a value from the test and allocate the result.
- */
- static unsigned char *
- alloc_value(char *buf, int *len)
- {
- unsigned char * value;
- int i, count;
- if (strncmp(buf, "<None>", 6) == 0) {
- *len = 0;
- return NULL;
- }
- /* find the length of the number */
- for (count = 0; isxdigit(buf[count]); count++);
- *len = count/2;
- if (*len == 0) {
- return NULL;
- }
- value = PORT_Alloc(*len);
- if (!value) {
- *len = 0;
- return NULL;
- }
-
- for (i=0; i<*len; buf+=2 , i++) {
- hex_to_byteval(buf, &value[i]);
- }
- return value;
- }
- PRBool
- isblankline(char *b)
- {
- while (isspace(*b)) b++;
- if ((*b == '\n') || (*b == 0)) {
- return PR_TRUE;
- }
- return PR_FALSE;
- }
- /*
- * Perform the Hash_DRBG (CAVS) for the RNG algorithm
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- drbg(char *reqfn)
- {
- char buf[2000]; /* test case has some very long lines, returned bits
- * as high as 800 bytes (6400 bits). That 1600 byte
- * plus a tag */
- char buf2[2000];
- FILE *rngreq; /* input stream from the REQUEST file */
- FILE *rngresp; /* output stream to the RESPONSE file */
- unsigned int i;
- unsigned char *entropy = NULL;
- int entropy_len = 0;
- unsigned char *nonce = NULL;
- int nonce_len = 0;
- unsigned char *personalization_string = NULL;
- int ps_len = 0;
- unsigned char *return_bytes = NULL;
- unsigned char *predicted_return_bytes = NULL;
- int return_bytes_len = 0;
- unsigned char *additional_input = NULL;
- int additional_len = 0;
- enum { NONE, INSTANTIATE, GENERATE, RESEED, UNINSTANTIATE } command =
- NONE;
- SECStatus rv;
- rngreq = fopen(reqfn, "r");
- rngresp = stdout;
- while (fgets(buf, sizeof buf, rngreq) != NULL) {
- /* a comment, skip it. */
- if (buf[0] == '#') {
- fputs(buf, rngresp);
- continue;
- }
- if (isblankline(buf)) {
- switch (command) {
- case INSTANTIATE:
- rv = PRNGTEST_Instantiate(entropy, entropy_len,
- nonce, nonce_len,
- personalization_string, ps_len);
- if (rv != SECSuccess) {
- goto loser;
- }
- /* clear */
- if (entropy) {
- PORT_ZFree(entropy, entropy_len);
- entropy = NULL;
- entropy_len = 0;
- }
- if (nonce) {
- PORT_ZFree(nonce, nonce_len);
- nonce = NULL;
- nonce_len = 0;
- }
- if (personalization_string) {
- PORT_ZFree(personalization_string, ps_len);
- personalization_string = NULL;
- ps_len = 0;
- }
- break;
- case GENERATE:
- rv = PRNGTEST_Generate(return_bytes, return_bytes_len,
- additional_input, additional_len);
- if (rv != SECSuccess) {
- goto loser;
- }
- /* clear */
- if (predicted_return_bytes) {
- fputc('+', rngresp);
- }
- fputs("Returned bits = ", rngresp);
- to_hex_str(buf2, return_bytes, return_bytes_len);
- fputs(buf2, rngresp);
- fputc('\n', rngresp);
- if (predicted_return_bytes) {
- if (memcmp(return_bytes,
- predicted_return_bytes, return_bytes_len) != 0) {
- fprintf(stderr, "Generate failed:\n");
- fputs( " predicted=", stderr);
- to_hex_str(buf, predicted_return_bytes,
- return_bytes_len);
- fputs(buf, stderr);
- fputs("\n actual = ", stderr);
- fputs(buf2, stderr);
- fputc('\n', stderr);
- }
- PORT_ZFree(predicted_return_bytes, return_bytes_len);
- predicted_return_bytes = NULL;
- }
-
- if (return_bytes) {
- PORT_ZFree(return_bytes, return_bytes_len);
- return_bytes = NULL;
- return_bytes_len = 0;
- }
- if (additional_input) {
- PORT_ZFree(additional_input, additional_len);
- additional_input = NULL;
- additional_len = 0;
- }
-
- break;
- case RESEED:
- rv = PRNGTEST_Reseed(entropy, entropy_len,
- additional_input, additional_len);
- if (rv != SECSuccess) {
- goto loser;
- }
- /* clear */
- if (entropy) {
- PORT_ZFree(entropy, entropy_len);
- entropy = NULL;
- entropy_len = 0;
- }
- if (additional_input) {
- PORT_ZFree(additional_input, additional_len);
- additional_input = NULL;
- additional_len = 0;
- }
- break;
- case UNINSTANTIATE:
- rv = PRNGTEST_Uninstantiate();
- if (rv != SECSuccess) {
- goto loser;
- }
- break;
- }
- fputs(buf, rngresp);
- command = NONE;
- continue;
- }
- /* [Hash - SHA256] */
- if (buf[0] == '[') {
- fputs(buf, rngresp);
- continue;
- }
- /* INSTANTIATE */
- if (strncmp(buf, "INSTANTIATE", 11) == 0) {
- i = 11;
- command = INSTANTIATE;
- fputs(buf, rngresp);
- continue;
- }
- /* Generate bytes */
- if (strncmp(buf, "GENERATE", 8) == 0) {
- i = 8;
- while (isspace(buf[i])) {
- i++;
- }
- return_bytes_len = atoi(&buf[i])/8;
- return_bytes = PORT_Alloc(return_bytes_len);
- command = GENERATE;
- fputs(buf, rngresp);
- continue;
- }
- if (strncmp(buf, "RESEED", 6) == 0) {
- i = 6;
- command = RESEED;
- fputs(buf, rngresp);
- continue;
- }
- if (strncmp(buf, "UNINSTANTIATE", 13) == 0) {
- i = 13;
- command = UNINSTANTIATE;
- fputs(buf, rngresp);
- continue;
- }
- /* Entropy input = ... */
- if (strncmp(buf, "Entropy input", 13) == 0) {
- i = 13;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- if ((command == INSTANTIATE) || (command == RESEED)) {
- entropy = alloc_value(&buf[i], &entropy_len);
- }
-
- fputs(buf, rngresp);
- continue;
- }
- /* Nonce = ... */
- if (strncmp(buf, "Nonce", 5) == 0) {
- i = 5;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- if (command == INSTANTIATE) {
- nonce = alloc_value(&buf[i], &nonce_len);
- }
-
- fputs(buf, rngresp);
- continue;
- }
- /* Personalization string = ... */
- if (strncmp(buf, "Personalization string", 22) == 0) {
- i = 22;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- if (command == INSTANTIATE) {
- personalization_string = alloc_value(&buf[i], &ps_len);
- }
-
- fputs(buf, rngresp);
- continue;
- }
- /* Returned bits = ... */
- if (strncmp(buf, "Returned bits", 13) == 0) {
- i = 13;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- if (command == GENERATE) {
- int len;
- predicted_return_bytes = alloc_value(&buf[i], &len);
- }
-
- fputs(buf, rngresp);
- continue;
- }
- /* Additional input = ... */
- if (strncmp(buf, "Additional input", 16) == 0) {
- i = 16;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- if ((command == GENERATE) || (command = RESEED)) {
- additional_input = alloc_value(&buf[i], &additional_len);
- }
-
- fputs(buf, rngresp);
- continue;
- }
- }
- loser:
- fclose(rngreq);
- }
- /*
- * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
- * "DSA - Generation of X", used both as specified and as a generic
- * purpose RNG. The presence of "Q = ..." in the REQUEST file
- * indicates we are using the algorithm as specified.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- rng_vst(char *reqfn)
- {
- char buf[256]; /* holds one line from the input REQUEST file.
- * needs to be large enough to hold the longest
- * line "XSeed = <128 hex digits>\n".
- */
- FILE *rngreq; /* input stream from the REQUEST file */
- FILE *rngresp; /* output stream to the RESPONSE file */
- unsigned int i, j;
- unsigned char Q[DSA_SUBPRIME_LEN];
- PRBool hasQ = PR_FALSE;
- unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
- unsigned char XKey[512/8];
- unsigned char XSeed[512/8];
- unsigned char GENX[2*SHA1_LENGTH];
- unsigned char DSAX[DSA_SUBPRIME_LEN];
- SECStatus rv;
- rngreq = fopen(reqfn, "r");
- rngresp = stdout;
- while (fgets(buf, sizeof buf, rngreq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, rngresp);
- continue;
- }
- /* [Xchange - SHA1] */
- if (buf[0] == '[') {
- fputs(buf, rngresp);
- continue;
- }
- /* Q = ... */
- if (buf[0] == 'Q') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof Q; i+=2,j++) {
- hex_to_byteval(&buf[i], &Q[j]);
- }
- fputs(buf, rngresp);
- hasQ = PR_TRUE;
- continue;
- }
- /* "COUNT = x" begins a new data set */
- if (strncmp(buf, "COUNT", 5) == 0) {
- /* zeroize the variables for the test with this data set */
- b = 0;
- memset(XKey, 0, sizeof XKey);
- memset(XSeed, 0, sizeof XSeed);
- fputs(buf, rngresp);
- continue;
- }
- /* b = ... */
- if (buf[0] == 'b') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- b = atoi(&buf[i]);
- if (b < 160 || b > 512 || b%8 != 0) {
- goto loser;
- }
- fputs(buf, rngresp);
- continue;
- }
- /* XKey = ... */
- if (strncmp(buf, "XKey", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<b/8; i+=2,j++) {
- hex_to_byteval(&buf[i], &XKey[j]);
- }
- fputs(buf, rngresp);
- continue;
- }
- /* XSeed = ... */
- if (strncmp(buf, "XSeed", 5) == 0) {
- i = 5;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<b/8; i+=2,j++) {
- hex_to_byteval(&buf[i], &XSeed[j]);
- }
- fputs(buf, rngresp);
- rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
- if (rv != SECSuccess) {
- goto loser;
- }
- fputs("X = ", rngresp);
- if (hasQ) {
- rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
- if (rv != SECSuccess) {
- goto loser;
- }
- to_hex_str(buf, DSAX, sizeof DSAX);
- } else {
- to_hex_str(buf, GENX, sizeof GENX);
- }
- fputs(buf, rngresp);
- fputc('\n', rngresp);
- continue;
- }
- }
- loser:
- fclose(rngreq);
- }
- /*
- * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
- * "DSA - Generation of X", used both as specified and as a generic
- * purpose RNG. The presence of "Q = ..." in the REQUEST file
- * indicates we are using the algorithm as specified.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- rng_mct(char *reqfn)
- {
- char buf[256]; /* holds one line from the input REQUEST file.
- * needs to be large enough to hold the longest
- * line "XSeed = <128 hex digits>\n".
- */
- FILE *rngreq; /* input stream from the REQUEST file */
- FILE *rngresp; /* output stream to the RESPONSE file */
- unsigned int i, j;
- unsigned char Q[DSA_SUBPRIME_LEN];
- PRBool hasQ = PR_FALSE;
- unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
- unsigned char XKey[512/8];
- unsigned char XSeed[512/8];
- unsigned char GENX[2*SHA1_LENGTH];
- unsigned char DSAX[DSA_SUBPRIME_LEN];
- SECStatus rv;
- rngreq = fopen(reqfn, "r");
- rngresp = stdout;
- while (fgets(buf, sizeof buf, rngreq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, rngresp);
- continue;
- }
- /* [Xchange - SHA1] */
- if (buf[0] == '[') {
- fputs(buf, rngresp);
- continue;
- }
- /* Q = ... */
- if (buf[0] == 'Q') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof Q; i+=2,j++) {
- hex_to_byteval(&buf[i], &Q[j]);
- }
- fputs(buf, rngresp);
- hasQ = PR_TRUE;
- continue;
- }
- /* "COUNT = x" begins a new data set */
- if (strncmp(buf, "COUNT", 5) == 0) {
- /* zeroize the variables for the test with this data set */
- b = 0;
- memset(XKey, 0, sizeof XKey);
- memset(XSeed, 0, sizeof XSeed);
- fputs(buf, rngresp);
- continue;
- }
- /* b = ... */
- if (buf[0] == 'b') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- b = atoi(&buf[i]);
- if (b < 160 || b > 512 || b%8 != 0) {
- goto loser;
- }
- fputs(buf, rngresp);
- continue;
- }
- /* XKey = ... */
- if (strncmp(buf, "XKey", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<b/8; i+=2,j++) {
- hex_to_byteval(&buf[i], &XKey[j]);
- }
- fputs(buf, rngresp);
- continue;
- }
- /* XSeed = ... */
- if (strncmp(buf, "XSeed", 5) == 0) {
- unsigned int k;
- i = 5;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<b/8; i+=2,j++) {
- hex_to_byteval(&buf[i], &XSeed[j]);
- }
- fputs(buf, rngresp);
- for (k = 0; k < 10000; k++) {
- rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
- if (rv != SECSuccess) {
- goto loser;
- }
- }
- fputs("X = ", rngresp);
- if (hasQ) {
- rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
- if (rv != SECSuccess) {
- goto loser;
- }
- to_hex_str(buf, DSAX, sizeof DSAX);
- } else {
- to_hex_str(buf, GENX, sizeof GENX);
- }
- fputs(buf, rngresp);
- fputc('\n', rngresp);
- continue;
- }
- }
- loser:
- fclose(rngreq);
- }
- /*
- * Calculate the SHA Message Digest
- *
- * MD = Message digest
- * MDLen = length of Message Digest and SHA_Type
- * msg = message to digest
- * msgLen = length of message to digest
- */
- SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
- {
- SECStatus sha_status = SECFailure;
- if (MDLen == SHA1_LENGTH) {
- sha_status = SHA1_HashBuf(MD, msg, msgLen);
- } else if (MDLen == SHA256_LENGTH) {
- sha_status = SHA256_HashBuf(MD, msg, msgLen);
- } else if (MDLen == SHA384_LENGTH) {
- sha_status = SHA384_HashBuf(MD, msg, msgLen);
- } else if (MDLen == SHA512_LENGTH) {
- sha_status = SHA512_HashBuf(MD, msg, msgLen);
- }
- return sha_status;
- }
- /*
- * Perform the SHA Monte Carlo Test
- *
- * MDLen = length of Message Digest and SHA_Type
- * seed = input seed value
- * resp = is the output response file.
- */
- SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
- {
- int i, j;
- unsigned int msgLen = MDLen*3;
- unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */
- unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */
- unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */
- unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */
- unsigned char msg[HASH_LENGTH_MAX*3];
- char buf[HASH_LENGTH_MAX*2 + 1]; /* MAX buf MD_i as a hex string */
- for (j=0; j<100; j++) {
- /* MD_0 = MD_1 = MD_2 = seed */
- memcpy(MD_i3, seed, MDLen);
- memcpy(MD_i2, seed, MDLen);
- memcpy(MD_i1, seed, MDLen);
- for (i=3; i < 1003; i++) {
- /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
- memcpy(msg, MD_i3, MDLen);
- memcpy(&msg[MDLen], MD_i2, MDLen);
- memcpy(&msg[MDLen*2], MD_i1,MDLen);
- /* MDi = SHA(Msg) */
- if (sha_calcMD(MD_i, MDLen,
- msg, msgLen) != SECSuccess) {
- return SECFailure;
- }
- /* save MD[i-3] MD[i-2] MD[i-1] */
- memcpy(MD_i3, MD_i2, MDLen);
- memcpy(MD_i2, MD_i1, MDLen);
- memcpy(MD_i1, MD_i, MDLen);
- }
- /* seed = MD_i */
- memcpy(seed, MD_i, MDLen);
- sprintf(buf, "COUNT = %d\n", j);
- fputs(buf, resp);
- /* output MD_i */
- fputs("MD = ", resp);
- to_hex_str(buf, MD_i, MDLen);
- fputs(buf, resp);
- fputc('\n', resp);
- }
- return SECSuccess;
- }
- /*
- * Perform the SHA Tests.
- *
- * reqfn is the pathname of the input REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void sha_test(char *reqfn)
- {
- unsigned int i, j;
- unsigned int MDlen; /* the length of the Message Digest in Bytes */
- unsigned int msgLen; /* the length of the input Message in Bytes */
- unsigned char *msg = NULL; /* holds the message to digest.*/
- size_t bufSize = 25608; /*MAX buffer size */
- char *buf = NULL; /* holds one line from the input REQUEST file.*/
- unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
- unsigned char MD[HASH_LENGTH_MAX]; /* message digest */
- FILE *req = NULL; /* input stream from the REQUEST file */
- FILE *resp; /* output stream to the RESPONSE file */
- buf = PORT_ZAlloc(bufSize);
- if (buf == NULL) {
- goto loser;
- }
- /* zeroize the variables for the test with this data set */
- memset(seed, 0, sizeof seed);
- req = fopen(reqfn, "r");
- resp = stdout;
- while (fgets(buf, bufSize, req) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, resp);
- continue;
- }
- /* [L = Length of the Message Digest and sha_type */
- if (buf[0] == '[') {
- if (strncmp(&buf[1], "L ", 1) == 0) {
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- MDlen = atoi(&buf[i]);
- fputs(buf, resp);
- continue;
- }
- }
- /* Len = Length of the Input Message Length ... */
- if (strncmp(buf, "Len", 3) == 0) {
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- if (msg) {
- PORT_ZFree(msg,msgLen);
- msg = NULL;
- }
- msgLen = atoi(&buf[i]); /* in bits */
- if (msgLen%8 != 0) {
- fprintf(stderr, "SHA tests are incorrectly configured for "
- "BIT oriented implementations\n");
- goto loser;
- }
- msgLen = msgLen/8; /* convert to bytes */
- fputs(buf, resp);
- msg = PORT_ZAlloc(msgLen);
- if (msg == NULL && msgLen != 0) {
- goto loser;
- }
- continue;
- }
- /* MSG = ... */
- if (strncmp(buf, "Msg", 3) == 0) {
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< msgLen; i+=2,j++) {
- hex_to_byteval(&buf[i], &msg[j]);
- }
- fputs(buf, resp);
- /* calculate the Message Digest */
- memset(MD, 0, sizeof MD);
- if (sha_calcMD(MD, MDlen,
- msg, msgLen) != SECSuccess) {
- goto loser;
- }
- fputs("MD = ", resp);
- to_hex_str(buf, MD, MDlen);
- fputs(buf, resp);
- fputc('\n', resp);
- continue;
- }
- /* Seed = ... */
- if (strncmp(buf, "Seed", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j<sizeof seed; i+=2,j++) {
- hex_to_byteval(&buf[i], &seed[j]);
- }
- fputs(buf, resp);
- fputc('\n', resp);
- /* do the Monte Carlo test */
- if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
- goto loser;
- }
- continue;
- }
- }
- loser:
- if (req) {
- fclose(req);
- }
- if (buf) {
- PORT_ZFree(buf, bufSize);
- }
- if (msg) {
- PORT_ZFree(msg, msgLen);
- }
- }
- /****************************************************/
- /* HMAC SHA-X calc */
- /* hmac_computed - the computed HMAC */
- /* hmac_length - the length of the computed HMAC */
- /* secret_key - secret key to HMAC */
- /* secret_key_length - length of secret key, */
- /* message - message to HMAC */
- /* message_length - length ofthe message */
- /****************************************************/
- static SECStatus
- hmac_calc(unsigned char *hmac_computed,
- const unsigned int hmac_length,
- const unsigned char *secret_key,
- const unsigned int secret_key_length,
- const unsigned char *message,
- const unsigned int message_length,
- const HASH_HashType hashAlg )
- {
- SECStatus hmac_status = SECFailure;
- HMACContext *cx = NULL;
- SECHashObject *hashObj = NULL;
- unsigned int bytes_hashed = 0;
- hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg);
-
- if (!hashObj)
- return( SECFailure );
- cx = HMAC_Create(hashObj, secret_key,
- secret_key_length,
- PR_TRUE); /* PR_TRUE for in FIPS mode */
- if (cx == NULL)
- return( SECFailure );
- HMAC_Begin(cx);
- HMAC_Update(cx, message, message_length);
- hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed,
- hmac_length);
- HMAC_Destroy(cx, PR_TRUE);
- return( hmac_status );
- }
- /*
- * Perform the HMAC Tests.
- *
- * reqfn is the pathname of the input REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void hmac_test(char *reqfn)
- {
- unsigned int i, j;
- size_t bufSize = 288; /* MAX buffer size */
- char *buf = NULL; /* holds one line from the input REQUEST file.*/
- unsigned int keyLen; /* Key Length */
- unsigned char key[140]; /* key MAX size = 140 */
- unsigned int msgLen = 128; /* the length of the input */
- /* Message is always 128 Bytes */
- unsigned char *msg = NULL; /* holds the message to digest.*/
- unsigned int HMACLen; /* the length of the HMAC Bytes */
- unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */
- HASH_HashType hash_alg; /* HMAC type */
- FILE *req = NULL; /* input stream from the REQUEST file */
- FILE *resp; /* output stream to the RESPONSE file */
- buf = PORT_ZAlloc(bufSize);
- if (buf == NULL) {
- goto loser;
- }
- msg = PORT_ZAlloc(msgLen);
- memset(msg, 0, msgLen);
- if (msg == NULL) {
- goto loser;
- }
- req = fopen(reqfn, "r");
- resp = stdout;
- while (fgets(buf, bufSize, req) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, resp);
- continue;
- }
- /* [L = Length of the MAC and HASH_type */
- if (buf[0] == '[') {
- if (strncmp(&buf[1], "L ", 1) == 0) {
- i = 2;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- /* HMACLen will get reused for Tlen */
- HMACLen = atoi(&buf[i]);
- /* set the HASH algorithm for HMAC */
- if (HMACLen == SHA1_LENGTH) {
- hash_alg = HASH_AlgSHA1;
- } else if (HMACLen == SHA256_LENGTH) {
- hash_alg = HASH_AlgSHA256;
- } else if (HMACLen == SHA384_LENGTH) {
- hash_alg = HASH_AlgSHA384;
- } else if (HMACLen == SHA512_LENGTH) {
- hash_alg = HASH_AlgSHA512;
- } else {
- goto loser;
- }
- fputs(buf, resp);
- continue;
- }
- }
- /* Count = test iteration number*/
- if (strncmp(buf, "Count ", 5) == 0) {
- /* count can just be put into resp file */
- fputs(buf, resp);
- /* zeroize the variables for the test with this data set */
- keyLen = 0;
- HMACLen = 0;
- memset(key, 0, sizeof key);
- memset(msg, 0, sizeof msg);
- memset(HMAC, 0, sizeof HMAC);
- continue;
- }
- /* KLen = Length of the Input Secret Key ... */
- if (strncmp(buf, "Klen", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- keyLen = atoi(&buf[i]); /* in bytes */
- fputs(buf, resp);
- continue;
- }
- /* key = the secret key for the key to MAC */
- if (strncmp(buf, "Key", 3) == 0) {
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< keyLen; i+=2,j++) {
- hex_to_byteval(&buf[i], &key[j]);
- }
- fputs(buf, resp);
- }
- /* TLen = Length of the calculated HMAC */
- if (strncmp(buf, "Tlen", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- HMACLen = atoi(&buf[i]); /* in bytes */
- fputs(buf, resp);
- continue;
- }
- /* MSG = to HMAC always 128 bytes for these tests */
- if (strncmp(buf, "Msg", 3) == 0) {
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< msgLen; i+=2,j++) {
- hex_to_byteval(&buf[i], &msg[j]);
- }
- fputs(buf, resp);
- /* calculate the HMAC and output */
- if (hmac_calc(HMAC, HMACLen, key, keyLen,
- msg, msgLen, hash_alg) != SECSuccess) {
- goto loser;
- }
- fputs("MAC = ", resp);
- to_hex_str(buf, HMAC, HMACLen);
- fputs(buf, resp);
- fputc('\n', resp);
- continue;
- }
- }
- loser:
- if (req) {
- fclose(req);
- }
- if (buf) {
- PORT_ZFree(buf, bufSize);
- }
- if (msg) {
- PORT_ZFree(msg, msgLen);
- }
- }
- /*
- * Perform the DSA Key Pair Generation Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- dsa_keypair_test(char *reqfn)
- {
- char buf[260]; /* holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * 257 to hold (128 public key (x2 for HEX) + 1'\n'
- */
- FILE *dsareq; /* input stream from the REQUEST file */
- FILE *dsaresp; /* output stream to the RESPONSE file */
- int N; /* number of time to generate key pair */
- int modulus;
- int i;
- PQGParams *pqg = NULL;
- PQGVerify *vfy = NULL;
- int keySizeIndex; /* index for valid key sizes */
- dsareq = fopen(reqfn, "r");
- dsaresp = stdout;
- while (fgets(buf, sizeof buf, dsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, dsaresp);
- continue;
- }
- /* [Mod = x] */
- if (buf[0] == '[') {
- if(pqg!=NULL) {
- PQG_DestroyParams(pqg);
- pqg = NULL;
- }
- if(vfy!=NULL) {
- PQG_DestroyVerify(vfy);
- vfy = NULL;
- }
- if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
- goto loser;
- }
- fputs(buf, dsaresp);
- fputc('\n', dsaresp);
- /*****************************************************************
- * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
- * that points to a valid key size.
- */
- keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
- if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
- fprintf(dsaresp,
- "DSA key size must be a multiple of 64 between 512 "
- "and 1024, inclusive");
- goto loser;
- }
- /* Generate the parameters P, Q, and G */
- if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
- &pqg, &vfy) != SECSuccess) {
- fprintf(dsaresp, "ERROR: Unable to generate PQG parameters");
- goto loser;
- }
- /* output P, Q, and G */
- to_hex_str(buf, pqg->prime.data, pqg->prime.len);
- fprintf(dsaresp, "P = %s\n", buf);
- to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
- fprintf(dsaresp, "Q = %s\n", buf);
- to_hex_str(buf, pqg->base.data, pqg->base.len);
- fprintf(dsaresp, "G = %s\n\n", buf);
- continue;
- }
- /* N = ...*/
- if (buf[0] == 'N') {
- if (sscanf(buf, "N = %d", &N) != 1) {
- goto loser;
- }
- /* Generate a DSA key, and output the key pair for N times */
- for (i = 0; i < N; i++) {
- DSAPrivateKey *dsakey = NULL;
- if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
- fprintf(dsaresp, "ERROR: Unable to generate DSA key");
- goto loser;
- }
- to_hex_str(buf, dsakey->privateValue.data,
- dsakey->privateValue.len);
- fprintf(dsaresp, "X = %s\n", buf);
- to_hex_str(buf, dsakey->publicValue.data,
- dsakey->publicValue.len);
- fprintf(dsaresp, "Y = %s\n\n", buf);
- PORT_FreeArena(dsakey->params.arena, PR_TRUE);
- dsakey = NULL;
- }
- continue;
- }
- }
- loser:
- fclose(dsareq);
- }
- /*
- * Perform the DSA Domain Parameter Validation Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- dsa_pqgver_test(char *reqfn)
- {
- char buf[263]; /* holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * 260 to hold (128 public key (x2 for HEX) + P = ...
- */
- FILE *dsareq; /* input stream from the REQUEST file */
- FILE *dsaresp; /* output stream to the RESPONSE file */
- int modulus;
- unsigned int i, j;
- PQGParams pqg;
- PQGVerify vfy;
- unsigned int pghSize; /* size for p, g, and h */
- dsareq = fopen(reqfn, "r");
- dsaresp = stdout;
- memset(&pqg, 0, sizeof(pqg));
- memset(&vfy, 0, sizeof(vfy));
- while (fgets(buf, sizeof buf, dsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, dsaresp);
- continue;
- }
- /* [Mod = x] */
- if (buf[0] == '[') {
- if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
- goto loser;
- }
- if (pqg.prime.data) { /* P */
- SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
- }
- if (pqg.subPrime.data) { /* Q */
- SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
- }
- if (pqg.base.data) { /* G */
- SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
- }
- if (vfy.seed.data) { /* seed */
- SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
- }
- if (vfy.h.data) { /* H */
- SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
- }
- fputs(buf, dsaresp);
- /*calculate the size of p, g, and h then allocate items */
- pghSize = modulus/8;
- SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
- SECITEM_AllocItem(NULL, &pqg.base, pghSize);
- SECITEM_AllocItem(NULL, &vfy.h, pghSize);
- pqg.prime.len = pqg.base.len = vfy.h.len = pghSize;
- /* seed and q are always 20 bytes */
- SECITEM_AllocItem(NULL, &vfy.seed, 20);
- SECITEM_AllocItem(NULL, &pqg.subPrime, 20);
- vfy.seed.len = pqg.subPrime.len = 20;
- vfy.counter = 0;
- continue;
- }
- /* P = ... */
- if (buf[0] == 'P') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< pqg.prime.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &pqg.prime.data[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* Q = ... */
- if (buf[0] == 'Q') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< pqg.subPrime.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* G = ... */
- if (buf[0] == 'G') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< pqg.base.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &pqg.base.data[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* Seed = ... */
- if (strncmp(buf, "Seed", 4) == 0) {
- i = 4;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< vfy.seed.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &vfy.seed.data[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* c = ... */
- if (buf[0] == 'c') {
- if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
- goto loser;
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* H = ... */
- if (buf[0] == 'H') {
- SECStatus rv, result = SECFailure;
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< vfy.h.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &vfy.h.data[j]);
- }
- fputs(buf, dsaresp);
- /* Verify the Parameters */
- rv = PQG_VerifyParams(&pqg, &vfy, &result);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (result == SECSuccess) {
- fprintf(dsaresp, "Result = P\n");
- } else {
- fprintf(dsaresp, "Result = F\n");
- }
- continue;
- }
- }
- loser:
- fclose(dsareq);
- if (pqg.prime.data) { /* P */
- SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
- }
- if (pqg.subPrime.data) { /* Q */
- SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
- }
- if (pqg.base.data) { /* G */
- SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
- }
- if (vfy.seed.data) { /* seed */
- SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
- }
- if (vfy.h.data) { /* H */
- SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
- }
- }
- /*
- * Perform the DSA Public Key Validation Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- dsa_pqggen_test(char *reqfn)
- {
- char buf[263]; /* holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * 263 to hold seed = (128 public key (x2 for HEX)
- */
- FILE *dsareq; /* input stream from the REQUEST file */
- FILE *dsaresp; /* output stream to the RESPONSE file */
- int N; /* number of times to generate parameters */
- int modulus;
- int i;
- unsigned int j;
- PQGParams *pqg = NULL;
- PQGVerify *vfy = NULL;
- unsigned int keySizeIndex;
- dsareq = fopen(reqfn, "r");
- dsaresp = stdout;
- while (fgets(buf, sizeof buf, dsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, dsaresp);
- continue;
- }
- /* [Mod = ... ] */
- if (buf[0] == '[') {
- if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
- goto loser;
- }
- fputs(buf, dsaresp);
- fputc('\n', dsaresp);
- /****************************************************************
- * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
- * that points to a valid key size.
- */
- keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
- if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
- fprintf(dsaresp,
- "DSA key size must be a multiple of 64 between 512 "
- "and 1024, inclusive");
- goto loser;
- }
- continue;
- }
- /* N = ... */
- if (buf[0] == 'N') {
- if (sscanf(buf, "N = %d", &N) != 1) {
- goto loser;
- }
- for (i = 0; i < N; i++) {
- if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
- &pqg, &vfy) != SECSuccess) {
- fprintf(dsaresp,
- "ERROR: Unable to generate PQG parameters");
- goto loser;
- }
- to_hex_str(buf, pqg->prime.data, pqg->prime.len);
- fprintf(dsaresp, "P = %s\n", buf);
- to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
- fprintf(dsaresp, "Q = %s\n", buf);
- to_hex_str(buf, pqg->base.data, pqg->base.len);
- fprintf(dsaresp, "G = %s\n", buf);
- to_hex_str(buf, vfy->seed.data, vfy->seed.len);
- fprintf(dsaresp, "Seed = %s\n", buf);
- fprintf(dsaresp, "c = %d\n", vfy->counter);
- to_hex_str(buf, vfy->h.data, vfy->h.len);
- fputs("H = ", dsaresp);
- for (j=vfy->h.len; j<pqg->prime.len; j++) {
- fprintf(dsaresp, "00");
- }
- fprintf(dsaresp, "%s\n", buf);
- fputc('\n', dsaresp);
- if(pqg!=NULL) {
- PQG_DestroyParams(pqg);
- pqg = NULL;
- }
- if(vfy!=NULL) {
- PQG_DestroyVerify(vfy);
- vfy = NULL;
- }
- }
- continue;
- }
- }
- loser:
- fclose(dsareq);
- if(pqg!=NULL) {
- PQG_DestroyParams(pqg);
- }
- if(vfy!=NULL) {
- PQG_DestroyVerify(vfy);
- }
- }
- /*
- * Perform the DSA Signature Generation Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- dsa_siggen_test(char *reqfn)
- {
- char buf[263]; /* holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * max for Msg = ....
- */
- FILE *dsareq; /* input stream from the REQUEST file */
- FILE *dsaresp; /* output stream to the RESPONSE file */
- int modulus;
- int i, j;
- PQGParams *pqg = NULL;
- PQGVerify *vfy = NULL;
- DSAPrivateKey *dsakey = NULL;
- int keySizeIndex; /* index for valid key sizes */
- unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
- unsigned char sig[DSA_SIGNATURE_LEN];
- SECItem digest, signature;
- dsareq = fopen(reqfn, "r");
- dsaresp = stdout;
- while (fgets(buf, sizeof buf, dsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, dsaresp);
- continue;
- }
- /* [Mod = x] */
- if (buf[0] == '[') {
- if(pqg!=NULL) {
- PQG_DestroyParams(pqg);
- pqg = NULL;
- }
- if(vfy!=NULL) {
- PQG_DestroyVerify(vfy);
- vfy = NULL;
- }
- if (dsakey != NULL) {
- PORT_FreeArena(dsakey->params.arena, PR_TRUE);
- dsakey = NULL;
- }
- if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
- goto loser;
- }
- fputs(buf, dsaresp);
- fputc('\n', dsaresp);
- /****************************************************************
- * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
- * that points to a valid key size.
- */
- keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
- if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
- fprintf(dsaresp,
- "DSA key size must be a multiple of 64 between 512 "
- "and 1024, inclusive");
- goto loser;
- }
- /* Generate PQG and output PQG */
- if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
- &pqg, &vfy) != SECSuccess) {
- fprintf(dsaresp, "ERROR: Unable to generate PQG parameters");
- goto loser;
- }
- to_hex_str(buf, pqg->prime.data, pqg->prime.len);
- fprintf(dsaresp, "P = %s\n", buf);
- to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
- fprintf(dsaresp, "Q = %s\n", buf);
- to_hex_str(buf, pqg->base.data, pqg->base.len);
- fprintf(dsaresp, "G = %s\n", buf);
- /* create DSA Key */
- if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
- fprintf(dsaresp, "ERROR: Unable to generate DSA key");
- goto loser;
- }
- continue;
- }
- /* Msg = ... */
- if (strncmp(buf, "Msg", 3) == 0) {
- unsigned char msg[128]; /* MAX msg 128 */
- unsigned int len = 0;
- memset(sha1, 0, sizeof sha1);
- memset(sig, 0, sizeof sig);
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &msg[j]);
- }
- if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) {
- fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest");
- goto loser;
- }
- digest.type = siBuffer;
- digest.data = sha1;
- digest.len = sizeof sha1;
- signature.type = siBuffer;
- signature.data = sig;
- signature.len = sizeof sig;
- if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
- fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
- goto loser;
- }
- len = signature.len;
- if (len%2 != 0) {
- goto loser;
- }
- len = len/2;
- /* output the orginal Msg, and generated Y, R, and S */
- fputs(buf, dsaresp);
- fputc('\n', dsaresp);
- to_hex_str(buf, dsakey->publicValue.data,
- dsakey->publicValue.len);
- fprintf(dsaresp, "Y = %s\n", buf);
- to_hex_str(buf, &signature.data[0], len);
- fprintf(dsaresp, "R = %s\n", buf);
- to_hex_str(buf, &signature.data[len], len);
- fprintf(dsaresp, "S = %s\n", buf);
- continue;
- }
- }
- loser:
- fclose(dsareq);
- if(pqg != NULL) {
- PQG_DestroyParams(pqg);
- pqg = NULL;
- }
- if(vfy != NULL) {
- PQG_DestroyVerify(vfy);
- vfy = NULL;
- }
- if (dsaKey) {
- PORT_FreeArena(dsakey->params.arena, PR_TRUE);
- dsakey = NULL;
- }
- }
- /*
- * Perform the DSA Signature Verification Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- dsa_sigver_test(char *reqfn)
- {
- char buf[263]; /* holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * max for Msg = ....
- */
- FILE *dsareq; /* input stream from the REQUEST file */
- FILE *dsaresp; /* output stream to the RESPONSE file */
- int modulus;
- unsigned int i, j;
- SECItem digest, signature;
- DSAPublicKey pubkey;
- unsigned int pgySize; /* size for p, g, and y */
- unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
- unsigned char sig[DSA_SIGNATURE_LEN];
- dsareq = fopen(reqfn, "r");
- dsaresp = stdout;
- memset(&pubkey, 0, sizeof(pubkey));
- while (fgets(buf, sizeof buf, dsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, dsaresp);
- continue;
- }
- /* [Mod = x] */
- if (buf[0] == '[') {
- if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
- goto loser;
- }
- if (pubkey.params.prime.data) { /* P */
- SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
- }
- if (pubkey.params.subPrime.data) { /* Q */
- SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
- }
- if (pubkey.params.base.data) { /* G */
- SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
- }
- if (pubkey.publicValue.data) { /* Y */
- SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
- }
- fputs(buf, dsaresp);
- /* calculate the size of p, g, and y then allocate items */
- pgySize = modulus/8;
- SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
- SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
- SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
- pubkey.params.prime.len = pubkey.params.base.len = pgySize;
- pubkey.publicValue.len = pgySize;
- /* q always 20 bytes */
- SECITEM_AllocItem(NULL, &pubkey.params.subPrime, 20);
- pubkey.params.subPrime.len = 20;
- continue;
- }
- /* P = ... */
- if (buf[0] == 'P') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
- for (j=0; j< pubkey.params.prime.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* Q = ... */
- if (buf[0] == 'Q') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
- for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* G = ... */
- if (buf[0] == 'G') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- memset(pubkey.params.base.data, 0, pubkey.params.base.len);
- for (j=0; j< pubkey.params.base.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* Msg = ... */
- if (strncmp(buf, "Msg", 3) == 0) {
- unsigned char msg[128]; /* MAX msg 128 */
- memset(sha1, 0, sizeof sha1);
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]); i+=2,j++) {
- hex_to_byteval(&buf[i], &msg[j]);
- }
- if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) {
- fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest");
- goto loser;
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* Y = ... */
- if (buf[0] == 'Y') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
- for (j=0; j< pubkey.publicValue.len; i+=2,j++) {
- hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* R = ... */
- if (buf[0] == 'R') {
- memset(sig, 0, sizeof sig);
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; j< DSA_SUBPRIME_LEN; i+=2,j++) {
- hex_to_byteval(&buf[i], &sig[j]);
- }
- fputs(buf, dsaresp);
- continue;
- }
- /* S = ... */
- if (buf[0] == 'S') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=DSA_SUBPRIME_LEN; j< DSA_SIGNATURE_LEN; i+=2,j++) {
- hex_to_byteval(&buf[i], &sig[j]);
- }
- fputs(buf, dsaresp);
- digest.type = siBuffer;
- digest.data = sha1;
- digest.len = sizeof sha1;
- signature.type = siBuffer;
- signature.data = sig;
- signature.len = sizeof sig;
- if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
- fprintf(dsaresp, "Result = P\n");
- } else {
- fprintf(dsaresp, "Result = F\n");
- }
- continue;
- }
- }
- loser:
- fclose(dsareq);
- if (pubkey.params.prime.data) { /* P */
- SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
- }
- if (pubkey.params.subPrime.data) { /* Q */
- SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
- }
- if (pubkey.params.base.data) { /* G */
- SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
- }
- if (pubkey.publicValue.data) { /* Y */
- SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
- }
- }
- /*
- * Perform the RSA Signature Generation Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- rsa_siggen_test(char *reqfn)
- {
- char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1];
- /* buf holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * 2x for HEX output + 1 for \n
- */
- FILE *rsareq; /* input stream from the REQUEST file */
- FILE *rsaresp; /* output stream to the RESPONSE file */
- int i, j;
- unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
- unsigned int shaLength = 0; /* length of SHA */
- HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
- SECOidTag shaOid = SEC_OID_UNKNOWN;
- int modulus; /* the Modulus size */
- int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
- SECItem pe = {0, 0, 0 };
- unsigned char pubEx[4];
- int peCount = 0;
- RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and
- * public keys */
- RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
- rsareq = fopen(reqfn, "r");
- rsaresp = stdout;
- /* calculate the exponent */
- for (i=0; i < 4; i++) {
- if (peCount || (publicExponent &
- ((unsigned long)0xff000000L >> (i*8)))) {
- pubEx[peCount] =
- (unsigned char)((publicExponent >> (3-i)*8) & 0xff);
- peCount++;
- }
- }
- pe.len = peCount;
- pe.data = &pubEx[0];
- pe.type = siBuffer;
- while (fgets(buf, sizeof buf, rsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, rsaresp);
- continue;
- }
- /* [mod = ...] */
- if (buf[0] == '[') {
- if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
- goto loser;
- }
- if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
- fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
- goto loser;
- }
- fputs(buf, rsaresp);
- if (rsaBlapiPrivKey != NULL) {
- PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
- rsaBlapiPrivKey = NULL;
- rsaBlapiPublicKey = NULL;
- }
- rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
- if (rsaBlapiPrivKey == NULL) {
- fprintf(rsaresp, "Error unable to create RSA key\n");
- goto loser;
- }
- to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
- rsaBlapiPrivKey->modulus.len);
- fprintf(rsaresp, "\nn = %s\n\n", buf);
- to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
- rsaBlapiPrivKey->publicExponent.len);
- fprintf(rsaresp, "e = %s\n", buf);
- /* convert private key to public key. Memory
- * is freed with private key's arena */
- rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
- rsaBlapiPrivKey->arena,
- sizeof(RSAPublicKey));
- rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
- rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
- rsaBlapiPublicKey->publicExponent.len =
- rsaBlapiPrivKey->publicExponent.len;
- rsaBlapiPublicKey->publicExponent.data =
- rsaBlapiPrivKey->publicExponent.data;
- continue;
- }
- /* SHAAlg = ... */
- if (strncmp(buf, "SHAAlg", 6) == 0) {
- i = 6;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- /* set the SHA Algorithm */
- if (strncmp(&buf[i], "SHA1", 4) == 0) {
- shaAlg = HASH_AlgSHA1;
- } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
- shaAlg = HASH_AlgSHA256;
- } else if (strncmp(&buf[i], "SHA384", 6)== 0) {
- shaAlg = HASH_AlgSHA384;
- } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
- shaAlg = HASH_AlgSHA512;
- } else {
- fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
- goto loser;
- }
- fputs(buf, rsaresp);
- continue;
- }
- /* Msg = ... */
- if (strncmp(buf, "Msg", 3) == 0) {
- unsigned char msg[128]; /* MAX msg 128 */
- unsigned int rsa_bytes_signed;
- unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
- SECStatus rv = SECFailure;
- NSSLOWKEYPublicKey * rsa_public_key;
- NSSLOWKEYPrivateKey * rsa_private_key;
- NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
- NSSLOWKEYRSAKey, };
- NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
- NSSLOWKEYRSAKey, };
- low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
- low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
- rsa_private_key = &low_RSA_private_key;
- rsa_public_key = &low_RSA_public_key;
- memset(sha, 0, sizeof sha);
- memset(msg, 0, sizeof msg);
- rsa_bytes_signed = 0;
- memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) {
- hex_to_byteval(&buf[i], &msg[j]);
- }
- if (shaAlg == HASH_AlgSHA1) {
- if (SHA1_HashBuf(sha, msg, j) != SECSuccess) {
- fprintf(rsaresp, "ERROR: Unable to generate SHA1");
- goto loser;
- }
- shaLength = SHA1_LENGTH;
- shaOid = SEC_OID_SHA1;
- } else if (shaAlg == HASH_AlgSHA256) {
- if (SHA256_HashBuf(sha, msg, j) != SECSuccess) {
- fprintf(rsaresp, "ERROR: Unable to generate SHA256");
- goto loser;
- }
- shaLength = SHA256_LENGTH;
- shaOid = SEC_OID_SHA256;
- } else if (shaAlg == HASH_AlgSHA384) {
- if (SHA384_HashBuf(sha, msg, j) != SECSuccess) {
- fprintf(rsaresp, "ERROR: Unable to generate SHA384");
- goto loser;
- }
- shaLength = SHA384_LENGTH;
- shaOid = SEC_OID_SHA384;
- } else if (shaAlg == HASH_AlgSHA512) {
- if (SHA512_HashBuf(sha, msg, j) != SECSuccess) {
- fprintf(rsaresp, "ERROR: Unable to generate SHA512");
- goto loser;
- }
- shaLength = SHA512_LENGTH;
- shaOid = SEC_OID_SHA512;
- } else {
- fprintf(rsaresp, "ERROR: SHAAlg not defined.");
- goto loser;
- }
- /* Perform RSA signature with the RSA private key. */
- rv = RSA_HashSign( shaOid,
- rsa_private_key,
- rsa_computed_signature,
- &rsa_bytes_signed,
- nsslowkey_PrivateModulusLen(rsa_private_key),
- sha,
- shaLength);
- if( rv != SECSuccess ) {
- fprintf(rsaresp, "ERROR: RSA_HashSign failed");
- goto loser;
- }
- /* Output the signature */
- fputs(buf, rsaresp);
- to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
- fprintf(rsaresp, "S = %s\n", buf);
- /* Perform RSA verification with the RSA public key. */
- rv = RSA_HashCheckSign( shaOid,
- rsa_public_key,
- rsa_computed_signature,
- rsa_bytes_signed,
- sha,
- shaLength);
- if( rv != SECSuccess ) {
- fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
- goto loser;
- }
- continue;
- }
- }
- loser:
- fclose(rsareq);
- if (rsaBlapiPrivKey != NULL) {
- /* frees private and public key */
- PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
- rsaBlapiPrivKey = NULL;
- rsaBlapiPublicKey = NULL;
- }
- }
- /*
- * Perform the RSA Signature Verification Test.
- *
- * reqfn is the pathname of the REQUEST file.
- *
- * The output RESPONSE file is written to stdout.
- */
- void
- rsa_sigver_test(char *reqfn)
- {
- char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7];
- /* buf holds one line from the input REQUEST file
- * or to the output RESPONSE file.
- * s = 2x for HEX output + 1 for \n
- */
- FILE *rsareq; /* input stream from the REQUEST file */
- FILE *rsaresp; /* output stream to the RESPONSE file */
- int i, j;
- unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
- unsigned int shaLength = 0; /* actual length of the digest */
- HASH_HashType shaAlg = HASH_AlgNULL;
- SECOidTag shaOid = SEC_OID_UNKNOWN;
- int modulus = 0; /* the Modulus size */
- unsigned char signature[513]; /* largest signature size + '\n' */
- unsigned int signatureLength = 0; /* actual length of the signature */
- PRBool keyvalid = PR_TRUE;
- RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
- rsareq = fopen(reqfn, "r");
- rsaresp = stdout;
- memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
- while (fgets(buf, sizeof buf, rsareq) != NULL) {
- /* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
- fputs(buf, rsaresp);
- continue;
- }
- /* [Mod = ...] */
- if (buf[0] == '[') {
- unsigned int flen; /* length in bytes of the field size */
- if (rsaBlapiPublicKey.modulus.data) { /* n */
- SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
- }
- if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
- goto loser;
- }
- if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
- fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
- goto loser;
- }
- fputs(buf, rsaresp);
- signatureLength = flen = modulus/8;
- SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
- if (rsaBlapiPublicKey.modulus.data == NULL) {
- goto loser;
- }
- continue;
- }
- /* n = ... modulus */
- if (buf[0] == 'n') {
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
- rsaBlapiPublicKey.modulus.len,
- &buf[i]);
- if (!keyvalid) {
- fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
- goto loser;
- }
- fputs(buf, rsaresp);
- continue;
- }
- /* SHAAlg = ... */
- if (strncmp(buf, "SHAAlg", 6) == 0) {
- i = 6;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- /* set the SHA Algorithm */
- if (strncmp(&buf[i], "SHA1", 4) == 0) {
- shaAlg = HASH_AlgSHA1;
- } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
- shaAlg = HASH_AlgSHA256;
- } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
- shaAlg = HASH_AlgSHA384;
- } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
- shaAlg = HASH_AlgSHA512;
- } else {
- fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
- goto loser;
- }
- fputs(buf, rsaresp);
- continue;
- }
- /* e = ... public Key */
- if (buf[0] == 'e') {
- unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
- unsigned char t;
- memset(data, 0, sizeof data);
- if (rsaBlapiPublicKey.publicExponent.data) { /* e */
- SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
- }
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- /* skip leading zero's */
- while (isxdigit(buf[i])) {
- hex_to_byteval(&buf[i], &t);
- if (t == 0) {
- i+=2;
- } else break;
- }
-
- /* get the exponent */
- for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) {
- hex_to_byteval(&buf[i], &data[j]);
- }
- if (j == 0) { j = 1; } /* to handle 1 byte length exponents */
- SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
- if (rsaBlapiPublicKey.publicExponent.data == NULL) {
- goto loser;
- }
- for (i=0; i < j; i++) {
- rsaBlapiPublicKey.publicExponent.data[i] = data[i];
- }
- fputs(buf, rsaresp);
- continue;
- }
- /* Msg = ... */
- if (strncmp(buf, "Msg", 3) == 0) {
- unsigned char msg[128]; /* MAX msg 128 */
- memset(sha, 0, sizeof sha);
- memset(msg, 0, sizeof msg);
- i = 3;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) {
- hex_to_byteval(&buf[i], &msg[j]);
- }
- if (shaAlg == HASH_AlgSHA1) {
- if (SHA1_HashBuf(sha, msg, j) != SECSuccess) {
- fprintf(rsaresp, "ERROR: Unable to generate SHA1");
- goto loser;
- }
- shaLength = SHA1_LENGTH;
- shaOid = SEC_OID_SHA1;
- } else if (shaAlg == HASH_AlgSHA256) {
- if (SHA256_HashBuf(sha, msg, j) != SECSuccess) {
- fprintf(rsaresp, "ERROR: Unable to generate SHA256");
- goto loser;
- }
- shaLength = SHA256_LENGTH;
- shaOid = SEC_OID_SHA256;
- } else if (shaAlg == HASH_AlgSHA384) {
- if (SHA384_HashBuf(sha, msg, j) != SECSuccess) {
- fprintf(rsaresp, "ERROR: Unable to generate SHA384");
- goto loser;
- }
- shaLength = SHA384_LENGTH;
- shaOid = SEC_OID_SHA384;
- } else if (shaAlg == HASH_AlgSHA512) {
- if (SHA512_HashBuf(sha, msg, j) != SECSuccess) {
- fprintf(rsaresp, "ERROR: Unable to generate SHA512");
- goto loser;
- }
- shaLength = SHA512_LENGTH;
- shaOid = SEC_OID_SHA512;
- } else {
- fprintf(rsaresp, "ERROR: SHAAlg not defined.");
- goto loser;
- }
- fputs(buf, rsaresp);
- continue;
- }
- /* S = ... */
- if (buf[0] == 'S') {
- SECStatus rv = SECFailure;
- NSSLOWKEYPublicKey * rsa_public_key;
- NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
- NSSLOWKEYRSAKey, };
- /* convert to a low RSA public key */
- low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
- rsa_public_key = &low_RSA_public_key;
- memset(signature, 0, sizeof(signature));
- i = 1;
- while (isspace(buf[i]) || buf[i] == '=') {
- i++;
- }
- for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) {
- hex_to_byteval(&buf[i], &signature[j]);
- }
- signatureLength = j;
- fputs(buf, rsaresp);
- /* Perform RSA verification with the RSA public key. */
- rv = RSA_HashCheckSign( shaOid,
- rsa_public_key,
- signature,
- signatureLength,
- sha,
- shaLength);
- if( rv == SECSuccess ) {
- fputs("Result = P\n", rsaresp);
- } else {
- fputs("Result = F\n", rsaresp);
- }
- continue;
- }
- }
- loser:
- fclose(rsareq);
- if (rsaBlapiPublicKey.modulus.data) { /* n */
- SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
- }
- if (rsaBlapiPublicKey.publicExponent.data) { /* e */
- SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
- }
- }
- int main(int argc, char **argv)
- {
- if (argc < 2) exit (-1);
- NSS_NoDB_Init(NULL);
- /*************/
- /* TDEA */
- /*************/
- if (strcmp(argv[1], "tdea") == 0) {
- /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
- if (strcmp(argv[2], "kat") == 0) {
- /* Known Answer Test (KAT) */
- tdea_kat_mmt(argv[4]);
- } else if (strcmp(argv[2], "mmt") == 0) {
- /* Multi-block Message Test (MMT) */
- tdea_kat_mmt(argv[4]);
- } else if (strcmp(argv[2], "mct") == 0) {
- /* Monte Carlo Test (MCT) */
- if (strcmp(argv[3], "ecb") == 0) {
- /* ECB mode */
- tdea_mct(NSS_DES_EDE3, argv[4]);
- } else if (strcmp(argv[3], "cbc") == 0) {
- /* CBC mode */
- tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
- }
- }
- /*************/
- /* AES */
- /*************/
- } else if (strcmp(argv[1], "aes") == 0) {
- /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
- if ( strcmp(argv[2], "kat") == 0) {
- /* Known Answer Test (KAT) */
- aes_kat_mmt(argv[4]);
- } else if (strcmp(argv[2], "mmt") == 0) {
- /* Multi-block Message Test (MMT) */
- aes_kat_mmt(argv[4]);
- } else if (strcmp(argv[2], "mct") == 0) {
- /* Monte Carlo Test (MCT) */
- if ( strcmp(argv[3], "ecb") == 0) {
- /* ECB mode */
- aes_ecb_mct(argv[4]);
- } else if (strcmp(argv[3], "cbc") == 0) {
- /* CBC mode */
- aes_cbc_mct(argv[4]);
- }
- }
- /*************/
- /* SHA */
- /*************/
- } else if (strcmp(argv[1], "sha") == 0) {
- sha_test(argv[2]);
- /*************/
- /* RSA */
- /*************/
- } else if (strcmp(argv[1], "rsa") == 0) {
- /* argv[2]=siggen|sigver */
- /* argv[3]=<test name>.req */
- if (strcmp(argv[2], "siggen") == 0) {
- /* Signature Generation Test */
- rsa_siggen_test(argv[3]);
- } else if (strcmp(argv[2], "sigver") == 0) {
- /* Signature Verification Test */
- rsa_sigver_test(argv[3]);
- }
- /*************/
- /* HMAC */
- /*************/
- } else if (strcmp(argv[1], "hmac") == 0) {
- hmac_test(argv[2]);
- /*************/
- /* DSA */
- /*************/
- } else if (strcmp(argv[1], "dsa") == 0) {
- /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
- /* argv[3]=<test name>.req */
- if (strcmp(argv[2], "keypair") == 0) {
- /* Key Pair Generation Test */
- dsa_keypair_test(argv[3]);
- } else if (strcmp(argv[2], "pqggen") == 0) {
- /* Domain Parameter Generation Test */
- dsa_pqggen_test(argv[3]);
- } else if (strcmp(argv[2], "pqgver") == 0) {
- /* Domain Parameter Validation Test */
- dsa_pqgver_test(argv[3]);
- } else if (strcmp(argv[2], "siggen") == 0) {
- /* Signature Generation Test */
- dsa_siggen_test(argv[3]);
- } else if (strcmp(argv[2], "sigver") == 0) {
- /* Signature Verification Test */
- dsa_sigver_test(argv[3]);
- }
- #ifdef NSS_ENABLE_ECC
- /*************/
- /* ECDSA */
- /*************/
- } else if (strcmp(argv[1], "ecdsa") == 0) {
- /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
- if ( strcmp(argv[2], "keypair") == 0) {
- /* Key Pair Generation Test */
- ecdsa_keypair_test(argv[3]);
- } else if (strcmp(argv[2], "pkv") == 0) {
- /* Public Key Validation Test */
- ecdsa_pkv_test(argv[3]);
- } else if (strcmp(argv[2], "siggen") == 0) {
- /* Signature Generation Test */
- ecdsa_siggen_test(argv[3]);
- } else if (strcmp(argv[2], "sigver") == 0) {
- /* Signature Verification Test */
- ecdsa_sigver_test(argv[3]);
- }
- #endif /* NSS_ENABLE_ECC */
- /*************/
- /* RNG */
- /*************/
- } else if (strcmp(argv[1], "rng") == 0) {
- /* argv[2]=vst|mct argv[3]=<test name>.req */
- if ( strcmp(argv[2], "vst") == 0) {
- /* Variable Seed Test */
- rng_vst(argv[3]);
- } else if (strcmp(argv[2], "mct") == 0) {
- /* Monte Carlo Test */
- rng_mct(argv[3]);
- }
- } else if (strcmp(argv[1], "drbg") == 0) {
- /* Variable Seed Test */
- drbg(argv[2]);
- }
- return 0;
- }