зеркало из https://github.com/mozilla/gecko-dev.git
318958 TDEA algorithm tests for FIPS 140-2
This commit is contained in:
Родитель
cf1fabfb6d
Коммит
b6c6d7d561
|
@ -45,6 +45,9 @@
|
|||
#include "../../lib/freebl/mpi/mpi.h"
|
||||
#endif
|
||||
|
||||
#define ENCRYPT 1
|
||||
#define DECRYPT 0
|
||||
|
||||
static const unsigned char
|
||||
table3[32][8] = {
|
||||
{ 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31 },
|
||||
|
@ -838,6 +841,714 @@ des_modes(int mode, PRBool encrypt, unsigned int len,
|
|||
}
|
||||
}
|
||||
|
||||
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_from_2char(&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_from_2char(&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_from_2char(&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_from_2char(&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_from_2char(&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_from_2char(&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_from_2char(&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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, k;
|
||||
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 char tempKey[8];
|
||||
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);
|
||||
for (j=0; j < 8; j++) tempKey[j] = key[j];
|
||||
to_hex_str(buf, tempKey, 8);
|
||||
fputs(buf, resp);
|
||||
fputc('\n', resp);
|
||||
/* Output KEY2[i] */
|
||||
fputs("KEY2 = ", resp);
|
||||
for (j=0; j < 8; j++) tempKey[j] = key[j+8];
|
||||
to_hex_str(buf, tempKey, 8);
|
||||
fputs(buf, resp);
|
||||
fputc('\n', resp);
|
||||
/* Output KEY3[i] */
|
||||
fputs("KEY3 = ", resp);
|
||||
for (j=0; j < 8; j++) tempKey[j] = key[j+16];
|
||||
to_hex_str(buf, tempKey, 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);
|
||||
/* save C[j-1] */
|
||||
memcpy(outputtext_1, outputtext, 8);
|
||||
}
|
||||
/* CV[j+1] = C[j] */
|
||||
memcpy(iv, 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_1, 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) {
|
||||
if (crypt == ENCRYPT) {
|
||||
/* P[i] = C[j-1] */
|
||||
memcpy(inputtext, outputtext_1, 8);
|
||||
/*CV[i] = C[j] */
|
||||
memcpy(iv, outputtext, 8);
|
||||
} else {
|
||||
/*CV[i] = C[j] */
|
||||
memcpy(iv, inputtext, 8);
|
||||
/*C[i] = P[j] */
|
||||
memcpy(inputtext, outputtext, 8);
|
||||
}
|
||||
} 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]);
|
||||
fputs(buf, resp);
|
||||
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_from_2char(&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_from_2char(&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_from_2char(&buf[i], &key[j]);
|
||||
}
|
||||
fputs(buf, resp);
|
||||
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_from_2char(&buf[i], &iv[j]);
|
||||
}
|
||||
fputs(buf, resp);
|
||||
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_from_2char(&buf[i], &plaintext[j]);
|
||||
}
|
||||
|
||||
fputs(buf, resp);
|
||||
fputc('\n', resp);
|
||||
|
||||
/* 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_from_2char(&buf[i], &ciphertext[j]);
|
||||
}
|
||||
|
||||
fputs(buf, resp);
|
||||
fputc('\n', resp);
|
||||
|
||||
/* 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,
|
||||
|
@ -2611,6 +3322,28 @@ int main(int argc, char **argv)
|
|||
des_modes(NSS_DES_EDE3_CBC, PR_FALSE, 24, tdea3_cbc_dec_key,
|
||||
tdea3_cbc_dec_iv, tdea3_cbc_dec_inp, 3);
|
||||
/*************/
|
||||
/* TDEA */
|
||||
/*************/
|
||||
/* encrypt */
|
||||
} else 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) {
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# A Bourne shell script for running the NIST tdea Algorithm Validation Suite
|
||||
#
|
||||
# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
|
||||
# variables appropriately so that the fipstest command and the NSPR and NSS
|
||||
# shared libraries/DLLs are on the search path. Then run this script in the
|
||||
# directory where the REQUEST (.req) files reside. The script generates the
|
||||
# RESPONSE (.rsp) files in the same directory.
|
||||
|
||||
#CBC_Known_Answer_tests
|
||||
#Initial Permutation KAT
|
||||
#Permutation Operation KAT
|
||||
#Subsitution Table KAT
|
||||
#Variable Key KAT
|
||||
#Variable PlainText KAT
|
||||
cbc_kat_requests="
|
||||
TCBCinvperm.req
|
||||
TCBCpermop.req
|
||||
TCBCsubtab.req
|
||||
TCBCvarkey.req
|
||||
TCBCvartext.req
|
||||
"
|
||||
|
||||
#CBC Monte Carlo KATs
|
||||
cbc_monte_requests="
|
||||
TCBCMonte1.req
|
||||
TCBCMonte2.req
|
||||
TCBCMonte3.req
|
||||
"
|
||||
#Multi-block Message KATs
|
||||
cbc_mmt_requests="
|
||||
TCBCMMT1.req
|
||||
TCBCMMT2.req
|
||||
TCBCMMT3.req
|
||||
"
|
||||
|
||||
ecb_kat_requests="
|
||||
TECBinvperm.req
|
||||
TECBpermop.req
|
||||
TECBsubtab.req
|
||||
TECBvarkey.req
|
||||
TECBvartext.req
|
||||
"
|
||||
|
||||
ecb_monte_requests="
|
||||
TECBMonte1.req
|
||||
TECBMonte2.req
|
||||
TECBMonte3.req
|
||||
"
|
||||
|
||||
ecb_mmt_requests="
|
||||
TECBMMT1.req
|
||||
TECBMMT2.req
|
||||
TECBMMT3.req
|
||||
"
|
||||
|
||||
for request in $ecb_mmt_requests; do
|
||||
response=`echo $request | sed -e "s/req/rsp/"`
|
||||
echo $request $response
|
||||
fipstest tdea mmt ecb $request > $response
|
||||
done
|
||||
for request in $ecb_kat_requests; do
|
||||
response=`echo $request | sed -e "s/req/rsp/"`
|
||||
echo $request $response
|
||||
fipstest tdea kat ecb $request > $response
|
||||
done
|
||||
for request in $ecb_monte_requests; do
|
||||
response=`echo $request | sed -e "s/req/rsp/"`
|
||||
echo $request $response
|
||||
fipstest tdea mct ecb $request > $response
|
||||
done
|
||||
for request in $cbc_mmt_requests; do
|
||||
response=`echo $request | sed -e "s/req/rsp/"`
|
||||
echo $request $response
|
||||
fipstest tdea mmt cbc $request > $response
|
||||
done
|
||||
for request in $cbc_kat_requests; do
|
||||
response=`echo $request | sed -e "s/req/rsp/"`
|
||||
echo $request $response
|
||||
fipstest tdea kat cbc $request > $response
|
||||
done
|
||||
for request in $cbc_monte_requests; do
|
||||
response=`echo $request | sed -e "s/req/rsp/"`
|
||||
echo $request $response
|
||||
fipstest tdea mct cbc $request > $response
|
||||
done
|
Загрузка…
Ссылка в новой задаче