/security/nss/cmd/fipstest/fipstest.c
C | 5071 lines | 3945 code | 380 blank | 746 comment | 1501 complexity | 8a4f52b3f88f2fb370afaaa2e856fe85 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD
Large files files are truncated, but you can click here to view the full file
- /* ***** 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 "nssutil.h"
- #include "secerr.h"
- #include "secder.h"
- #include "secdig.h"
- #include "secoid.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] */
- fpu…
Large files files are truncated, but you can click here to view the full file