1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/fipstest/fipstest.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,5370 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include <stdio.h> 1.9 +#include <stdlib.h> 1.10 +#include <ctype.h> 1.11 + 1.12 +#include "secitem.h" 1.13 +#include "blapi.h" 1.14 +#include "nssutil.h" 1.15 +#include "secerr.h" 1.16 +#include "secder.h" 1.17 +#include "secdig.h" 1.18 +#include "secoid.h" 1.19 +#include "ec.h" 1.20 +#include "hasht.h" 1.21 +#include "lowkeyi.h" 1.22 +#include "softoken.h" 1.23 + 1.24 +#if 0 1.25 +#include "../../lib/freebl/mpi/mpi.h" 1.26 +#endif 1.27 + 1.28 +#ifndef NSS_DISABLE_ECC 1.29 +extern SECStatus 1.30 +EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams); 1.31 +extern SECStatus 1.32 +EC_CopyParams(PLArenaPool *arena, ECParams *dstParams, 1.33 + const ECParams *srcParams); 1.34 +#endif 1.35 + 1.36 +#define ENCRYPT 1 1.37 +#define DECRYPT 0 1.38 +#define BYTE unsigned char 1.39 +#define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001 1.40 +#define RSA_MAX_TEST_MODULUS_BITS 4096 1.41 +#define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8 1.42 +#define RSA_MAX_TEST_EXPONENT_BYTES 8 1.43 +#define PQG_TEST_SEED_BYTES 20 1.44 + 1.45 +SECStatus 1.46 +hex_to_byteval(const char *c2, unsigned char *byteval) 1.47 +{ 1.48 + int i; 1.49 + unsigned char offset; 1.50 + *byteval = 0; 1.51 + for (i=0; i<2; i++) { 1.52 + if (c2[i] >= '0' && c2[i] <= '9') { 1.53 + offset = c2[i] - '0'; 1.54 + *byteval |= offset << 4*(1-i); 1.55 + } else if (c2[i] >= 'a' && c2[i] <= 'f') { 1.56 + offset = c2[i] - 'a'; 1.57 + *byteval |= (offset + 10) << 4*(1-i); 1.58 + } else if (c2[i] >= 'A' && c2[i] <= 'F') { 1.59 + offset = c2[i] - 'A'; 1.60 + *byteval |= (offset + 10) << 4*(1-i); 1.61 + } else { 1.62 + return SECFailure; 1.63 + } 1.64 + } 1.65 + return SECSuccess; 1.66 +} 1.67 + 1.68 +SECStatus 1.69 +byteval_to_hex(unsigned char byteval, char *c2, char a) 1.70 +{ 1.71 + int i; 1.72 + unsigned char offset; 1.73 + for (i=0; i<2; i++) { 1.74 + offset = (byteval >> 4*(1-i)) & 0x0f; 1.75 + if (offset < 10) { 1.76 + c2[i] = '0' + offset; 1.77 + } else { 1.78 + c2[i] = a + offset - 10; 1.79 + } 1.80 + } 1.81 + return SECSuccess; 1.82 +} 1.83 + 1.84 +void 1.85 +to_hex_str(char *str, const unsigned char *buf, unsigned int len) 1.86 +{ 1.87 + unsigned int i; 1.88 + for (i=0; i<len; i++) { 1.89 + byteval_to_hex(buf[i], &str[2*i], 'a'); 1.90 + } 1.91 + str[2*len] = '\0'; 1.92 +} 1.93 + 1.94 +void 1.95 +to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len) 1.96 +{ 1.97 + unsigned int i; 1.98 + for (i=0; i<len; i++) { 1.99 + byteval_to_hex(buf[i], &str[2*i], 'A'); 1.100 + } 1.101 + str[2*len] = '\0'; 1.102 +} 1.103 + 1.104 +/* 1.105 + * Convert a string of hex digits (str) to an array (buf) of len bytes. 1.106 + * Return PR_TRUE if the hex string can fit in the byte array. Return 1.107 + * PR_FALSE if the hex string is empty or is too long. 1.108 + */ 1.109 +PRBool 1.110 +from_hex_str(unsigned char *buf, unsigned int len, const char *str) 1.111 +{ 1.112 + unsigned int nxdigit; /* number of hex digits in str */ 1.113 + unsigned int i; /* index into buf */ 1.114 + unsigned int j; /* index into str */ 1.115 + 1.116 + /* count the hex digits */ 1.117 + nxdigit = 0; 1.118 + for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) { 1.119 + /* empty body */ 1.120 + } 1.121 + if (nxdigit == 0) { 1.122 + return PR_FALSE; 1.123 + } 1.124 + if (nxdigit > 2*len) { 1.125 + /* 1.126 + * The input hex string is too long, but we allow it if the 1.127 + * extra digits are leading 0's. 1.128 + */ 1.129 + for (j = 0; j < nxdigit-2*len; j++) { 1.130 + if (str[j] != '0') { 1.131 + return PR_FALSE; 1.132 + } 1.133 + } 1.134 + /* skip leading 0's */ 1.135 + str += nxdigit-2*len; 1.136 + nxdigit = 2*len; 1.137 + } 1.138 + for (i=0, j=0; i< len; i++) { 1.139 + if (2*i < 2*len-nxdigit) { 1.140 + /* Handle a short input as if we padded it with leading 0's. */ 1.141 + if (2*i+1 < 2*len-nxdigit) { 1.142 + buf[i] = 0; 1.143 + } else { 1.144 + char tmp[2]; 1.145 + tmp[0] = '0'; 1.146 + tmp[1] = str[j]; 1.147 + hex_to_byteval(tmp, &buf[i]); 1.148 + j++; 1.149 + } 1.150 + } else { 1.151 + hex_to_byteval(&str[j], &buf[i]); 1.152 + j += 2; 1.153 + } 1.154 + } 1.155 + return PR_TRUE; 1.156 +} 1.157 + 1.158 +SECStatus 1.159 +tdea_encrypt_buf( 1.160 + int mode, 1.161 + const unsigned char *key, 1.162 + const unsigned char *iv, 1.163 + unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, 1.164 + const unsigned char *input, unsigned int inputlen) 1.165 +{ 1.166 + SECStatus rv = SECFailure; 1.167 + DESContext *cx; 1.168 + unsigned char doublecheck[8*20]; /* 1 to 20 blocks */ 1.169 + unsigned int doublechecklen = 0; 1.170 + 1.171 + cx = DES_CreateContext(key, iv, mode, PR_TRUE); 1.172 + if (cx == NULL) { 1.173 + goto loser; 1.174 + } 1.175 + rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen); 1.176 + if (rv != SECSuccess) { 1.177 + goto loser; 1.178 + } 1.179 + if (*outputlen != inputlen) { 1.180 + goto loser; 1.181 + } 1.182 + DES_DestroyContext(cx, PR_TRUE); 1.183 + cx = NULL; 1.184 + 1.185 + /* 1.186 + * Doublecheck our result by decrypting the ciphertext and 1.187 + * compare the output with the input plaintext. 1.188 + */ 1.189 + cx = DES_CreateContext(key, iv, mode, PR_FALSE); 1.190 + if (cx == NULL) { 1.191 + goto loser; 1.192 + } 1.193 + rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, 1.194 + output, *outputlen); 1.195 + if (rv != SECSuccess) { 1.196 + goto loser; 1.197 + } 1.198 + if (doublechecklen != *outputlen) { 1.199 + goto loser; 1.200 + } 1.201 + DES_DestroyContext(cx, PR_TRUE); 1.202 + cx = NULL; 1.203 + if (memcmp(doublecheck, input, inputlen) != 0) { 1.204 + goto loser; 1.205 + } 1.206 + rv = SECSuccess; 1.207 + 1.208 +loser: 1.209 + if (cx != NULL) { 1.210 + DES_DestroyContext(cx, PR_TRUE); 1.211 + } 1.212 + return rv; 1.213 +} 1.214 + 1.215 +SECStatus 1.216 +tdea_decrypt_buf( 1.217 + int mode, 1.218 + const unsigned char *key, 1.219 + const unsigned char *iv, 1.220 + unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, 1.221 + const unsigned char *input, unsigned int inputlen) 1.222 +{ 1.223 + SECStatus rv = SECFailure; 1.224 + DESContext *cx; 1.225 + unsigned char doublecheck[8*20]; /* 1 to 20 blocks */ 1.226 + unsigned int doublechecklen = 0; 1.227 + 1.228 + cx = DES_CreateContext(key, iv, mode, PR_FALSE); 1.229 + if (cx == NULL) { 1.230 + goto loser; 1.231 + } 1.232 + rv = DES_Decrypt(cx, output, outputlen, maxoutputlen, 1.233 + input, inputlen); 1.234 + if (rv != SECSuccess) { 1.235 + goto loser; 1.236 + } 1.237 + if (*outputlen != inputlen) { 1.238 + goto loser; 1.239 + } 1.240 + DES_DestroyContext(cx, PR_TRUE); 1.241 + cx = NULL; 1.242 + 1.243 + /* 1.244 + * Doublecheck our result by encrypting the plaintext and 1.245 + * compare the output with the input ciphertext. 1.246 + */ 1.247 + cx = DES_CreateContext(key, iv, mode, PR_TRUE); 1.248 + if (cx == NULL) { 1.249 + goto loser; 1.250 + } 1.251 + rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, 1.252 + output, *outputlen); 1.253 + if (rv != SECSuccess) { 1.254 + goto loser; 1.255 + } 1.256 + if (doublechecklen != *outputlen) { 1.257 + goto loser; 1.258 + } 1.259 + DES_DestroyContext(cx, PR_TRUE); 1.260 + cx = NULL; 1.261 + if (memcmp(doublecheck, input, inputlen) != 0) { 1.262 + goto loser; 1.263 + } 1.264 + rv = SECSuccess; 1.265 + 1.266 +loser: 1.267 + if (cx != NULL) { 1.268 + DES_DestroyContext(cx, PR_TRUE); 1.269 + } 1.270 + return rv; 1.271 +} 1.272 + 1.273 +/* 1.274 + * Perform the TDEA Known Answer Test (KAT) or Multi-block Message 1.275 + * Test (MMT) in ECB or CBC mode. The KAT (there are five types) 1.276 + * and MMT have the same structure: given the key and IV (CBC mode 1.277 + * only), encrypt the given plaintext or decrypt the given ciphertext. 1.278 + * So we can handle them the same way. 1.279 + * 1.280 + * reqfn is the pathname of the REQUEST file. 1.281 + * 1.282 + * The output RESPONSE file is written to stdout. 1.283 + */ 1.284 +void 1.285 +tdea_kat_mmt(char *reqfn) 1.286 +{ 1.287 + char buf[180]; /* holds one line from the input REQUEST file. 1.288 + * needs to be large enough to hold the longest 1.289 + * line "CIPHERTEXT = <180 hex digits>\n". 1.290 + */ 1.291 + FILE *req; /* input stream from the REQUEST file */ 1.292 + FILE *resp; /* output stream to the RESPONSE file */ 1.293 + int i, j; 1.294 + int mode; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */ 1.295 + int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */ 1.296 + unsigned char key[24]; /* TDEA 3 key bundle */ 1.297 + unsigned int numKeys = 0; 1.298 + unsigned char iv[8]; /* for all modes except ECB */ 1.299 + unsigned char plaintext[8*20]; /* 1 to 20 blocks */ 1.300 + unsigned int plaintextlen; 1.301 + unsigned char ciphertext[8*20]; /* 1 to 20 blocks */ 1.302 + unsigned int ciphertextlen; 1.303 + SECStatus rv; 1.304 + 1.305 + req = fopen(reqfn, "r"); 1.306 + resp = stdout; 1.307 + while (fgets(buf, sizeof buf, req) != NULL) { 1.308 + /* a comment or blank line */ 1.309 + if (buf[0] == '#' || buf[0] == '\n') { 1.310 + fputs(buf, resp); 1.311 + continue; 1.312 + } 1.313 + /* [ENCRYPT] or [DECRYPT] */ 1.314 + if (buf[0] == '[') { 1.315 + if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 1.316 + crypt = ENCRYPT; 1.317 + } else { 1.318 + crypt = DECRYPT; 1.319 + } 1.320 + fputs(buf, resp); 1.321 + continue; 1.322 + } 1.323 + /* NumKeys */ 1.324 + if (strncmp(&buf[0], "NumKeys", 7) == 0) { 1.325 + i = 7; 1.326 + while (isspace(buf[i]) || buf[i] == '=') { 1.327 + i++; 1.328 + } 1.329 + numKeys = buf[i]; 1.330 + fputs(buf, resp); 1.331 + continue; 1.332 + } 1.333 + /* "COUNT = x" begins a new data set */ 1.334 + if (strncmp(buf, "COUNT", 5) == 0) { 1.335 + /* mode defaults to ECB, if dataset has IV mode will be set CBC */ 1.336 + mode = NSS_DES_EDE3; 1.337 + /* zeroize the variables for the test with this data set */ 1.338 + memset(key, 0, sizeof key); 1.339 + memset(iv, 0, sizeof iv); 1.340 + memset(plaintext, 0, sizeof plaintext); 1.341 + plaintextlen = 0; 1.342 + memset(ciphertext, 0, sizeof ciphertext); 1.343 + ciphertextlen = 0; 1.344 + fputs(buf, resp); 1.345 + continue; 1.346 + } 1.347 + if (numKeys == 0) { 1.348 + if (strncmp(buf, "KEYs", 4) == 0) { 1.349 + i = 4; 1.350 + while (isspace(buf[i]) || buf[i] == '=') { 1.351 + i++; 1.352 + } 1.353 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.354 + hex_to_byteval(&buf[i], &key[j]); 1.355 + key[j+8] = key[j]; 1.356 + key[j+16] = key[j]; 1.357 + } 1.358 + fputs(buf, resp); 1.359 + continue; 1.360 + } 1.361 + } else { 1.362 + /* KEY1 = ... */ 1.363 + if (strncmp(buf, "KEY1", 4) == 0) { 1.364 + i = 4; 1.365 + while (isspace(buf[i]) || buf[i] == '=') { 1.366 + i++; 1.367 + } 1.368 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.369 + hex_to_byteval(&buf[i], &key[j]); 1.370 + } 1.371 + fputs(buf, resp); 1.372 + continue; 1.373 + } 1.374 + /* KEY2 = ... */ 1.375 + if (strncmp(buf, "KEY2", 4) == 0) { 1.376 + i = 4; 1.377 + while (isspace(buf[i]) || buf[i] == '=') { 1.378 + i++; 1.379 + } 1.380 + for (j=8; isxdigit(buf[i]); i+=2,j++) { 1.381 + hex_to_byteval(&buf[i], &key[j]); 1.382 + } 1.383 + fputs(buf, resp); 1.384 + continue; 1.385 + } 1.386 + /* KEY3 = ... */ 1.387 + if (strncmp(buf, "KEY3", 4) == 0) { 1.388 + i = 4; 1.389 + while (isspace(buf[i]) || buf[i] == '=') { 1.390 + i++; 1.391 + } 1.392 + for (j=16; isxdigit(buf[i]); i+=2,j++) { 1.393 + hex_to_byteval(&buf[i], &key[j]); 1.394 + } 1.395 + fputs(buf, resp); 1.396 + continue; 1.397 + } 1.398 + } 1.399 + 1.400 + /* IV = ... */ 1.401 + if (strncmp(buf, "IV", 2) == 0) { 1.402 + mode = NSS_DES_EDE3_CBC; 1.403 + i = 2; 1.404 + while (isspace(buf[i]) || buf[i] == '=') { 1.405 + i++; 1.406 + } 1.407 + for (j=0; j<sizeof iv; i+=2,j++) { 1.408 + hex_to_byteval(&buf[i], &iv[j]); 1.409 + } 1.410 + fputs(buf, resp); 1.411 + continue; 1.412 + } 1.413 + 1.414 + /* PLAINTEXT = ... */ 1.415 + if (strncmp(buf, "PLAINTEXT", 9) == 0) { 1.416 + /* sanity check */ 1.417 + if (crypt != ENCRYPT) { 1.418 + goto loser; 1.419 + } 1.420 + i = 9; 1.421 + while (isspace(buf[i]) || buf[i] == '=') { 1.422 + i++; 1.423 + } 1.424 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.425 + hex_to_byteval(&buf[i], &plaintext[j]); 1.426 + } 1.427 + plaintextlen = j; 1.428 + rv = tdea_encrypt_buf(mode, key, 1.429 + (mode == NSS_DES_EDE3) ? NULL : iv, 1.430 + ciphertext, &ciphertextlen, sizeof ciphertext, 1.431 + plaintext, plaintextlen); 1.432 + if (rv != SECSuccess) { 1.433 + goto loser; 1.434 + } 1.435 + 1.436 + fputs(buf, resp); 1.437 + fputs("CIPHERTEXT = ", resp); 1.438 + to_hex_str(buf, ciphertext, ciphertextlen); 1.439 + fputs(buf, resp); 1.440 + fputc('\n', resp); 1.441 + continue; 1.442 + } 1.443 + /* CIPHERTEXT = ... */ 1.444 + if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 1.445 + /* sanity check */ 1.446 + if (crypt != DECRYPT) { 1.447 + goto loser; 1.448 + } 1.449 + 1.450 + i = 10; 1.451 + while (isspace(buf[i]) || buf[i] == '=') { 1.452 + i++; 1.453 + } 1.454 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.455 + hex_to_byteval(&buf[i], &ciphertext[j]); 1.456 + } 1.457 + ciphertextlen = j; 1.458 + 1.459 + rv = tdea_decrypt_buf(mode, key, 1.460 + (mode == NSS_DES_EDE3) ? NULL : iv, 1.461 + plaintext, &plaintextlen, sizeof plaintext, 1.462 + ciphertext, ciphertextlen); 1.463 + if (rv != SECSuccess) { 1.464 + goto loser; 1.465 + } 1.466 + 1.467 + fputs(buf, resp); 1.468 + fputs("PLAINTEXT = ", resp); 1.469 + to_hex_str(buf, plaintext, plaintextlen); 1.470 + fputs(buf, resp); 1.471 + fputc('\n', resp); 1.472 + continue; 1.473 + } 1.474 + } 1.475 + 1.476 +loser: 1.477 + fclose(req); 1.478 +} 1.479 + 1.480 +/* 1.481 +* Set the parity bit for the given byte 1.482 +*/ 1.483 +BYTE odd_parity( BYTE in) 1.484 +{ 1.485 + BYTE out = in; 1.486 + in ^= in >> 4; 1.487 + in ^= in >> 2; 1.488 + in ^= in >> 1; 1.489 + return (BYTE)(out ^ !(in & 1)); 1.490 +} 1.491 + 1.492 +/* 1.493 + * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j] 1.494 + * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes. 1.495 + */ 1.496 +void 1.497 +tdea_mct_next_keys(unsigned char *key, 1.498 + const unsigned char *text_2, const unsigned char *text_1, 1.499 + const unsigned char *text, unsigned int numKeys) 1.500 +{ 1.501 + int k; 1.502 + 1.503 + /* key1[i+1] = key1[i] xor PT/CT[j] */ 1.504 + for (k=0; k<8; k++) { 1.505 + key[k] ^= text[k]; 1.506 + } 1.507 + /* key2 */ 1.508 + if (numKeys == 2 || numKeys == 3) { 1.509 + /* key2 independent */ 1.510 + for (k=8; k<16; k++) { 1.511 + /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */ 1.512 + key[k] ^= text_1[k-8]; 1.513 + } 1.514 + } else { 1.515 + /* key2 == key 1 */ 1.516 + for (k=8; k<16; k++) { 1.517 + /* key2[i+1] = KEY2[i] xor PT/CT[j] */ 1.518 + key[k] = key[k-8]; 1.519 + } 1.520 + } 1.521 + /* key3 */ 1.522 + if (numKeys == 1 || numKeys == 2) { 1.523 + /* key3 == key 1 */ 1.524 + for (k=16; k<24; k++) { 1.525 + /* key3[i+1] = KEY3[i] xor PT/CT[j] */ 1.526 + key[k] = key[k-16]; 1.527 + } 1.528 + } else { 1.529 + /* key3 independent */ 1.530 + for (k=16; k<24; k++) { 1.531 + /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */ 1.532 + key[k] ^= text_2[k-16]; 1.533 + } 1.534 + } 1.535 + /* set the parity bits */ 1.536 + for (k=0; k<24; k++) { 1.537 + key[k] = odd_parity(key[k]); 1.538 + } 1.539 +} 1.540 + 1.541 +/* 1.542 + * Perform the Monte Carlo Test 1.543 + * 1.544 + * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC 1.545 + * crypt = ENCRYPT || DECRYPT 1.546 + * inputtext = plaintext or Cyphertext depending on the value of crypt 1.547 + * inputlength is expected to be size 8 bytes 1.548 + * iv = needs to be set for NSS_DES_EDE3_CBC mode 1.549 + * resp = is the output response file. 1.550 + */ 1.551 + void 1.552 +tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys, 1.553 + unsigned int crypt, unsigned char* inputtext, 1.554 + unsigned int inputlength, unsigned char* iv, FILE *resp) { 1.555 + 1.556 + int i, j; 1.557 + unsigned char outputtext_1[8]; /* PT/CT[j-1] */ 1.558 + unsigned char outputtext_2[8]; /* PT/CT[j-2] */ 1.559 + char buf[80]; /* holds one line from the input REQUEST file. */ 1.560 + unsigned int outputlen; 1.561 + unsigned char outputtext[8]; 1.562 + 1.563 + 1.564 + SECStatus rv; 1.565 + 1.566 + if (mode == NSS_DES_EDE3 && iv != NULL) { 1.567 + printf("IV must be NULL for NSS_DES_EDE3 mode"); 1.568 + goto loser; 1.569 + } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) { 1.570 + printf("IV must not be NULL for NSS_DES_EDE3_CBC mode"); 1.571 + goto loser; 1.572 + } 1.573 + 1.574 + /* loop 400 times */ 1.575 + for (i=0; i<400; i++) { 1.576 + /* if i == 0 CV[0] = IV not necessary */ 1.577 + /* record the count and key values and plainText */ 1.578 + sprintf(buf, "COUNT = %d\n", i); 1.579 + fputs(buf, resp); 1.580 + /* Output KEY1[i] */ 1.581 + fputs("KEY1 = ", resp); 1.582 + to_hex_str(buf, key, 8); 1.583 + fputs(buf, resp); 1.584 + fputc('\n', resp); 1.585 + /* Output KEY2[i] */ 1.586 + fputs("KEY2 = ", resp); 1.587 + to_hex_str(buf, &key[8], 8); 1.588 + fputs(buf, resp); 1.589 + fputc('\n', resp); 1.590 + /* Output KEY3[i] */ 1.591 + fputs("KEY3 = ", resp); 1.592 + to_hex_str(buf, &key[16], 8); 1.593 + fputs(buf, resp); 1.594 + fputc('\n', resp); 1.595 + if (mode == NSS_DES_EDE3_CBC) { 1.596 + /* Output CV[i] */ 1.597 + fputs("IV = ", resp); 1.598 + to_hex_str(buf, iv, 8); 1.599 + fputs(buf, resp); 1.600 + fputc('\n', resp); 1.601 + } 1.602 + if (crypt == ENCRYPT) { 1.603 + /* Output PT[0] */ 1.604 + fputs("PLAINTEXT = ", resp); 1.605 + } else { 1.606 + /* Output CT[0] */ 1.607 + fputs("CIPHERTEXT = ", resp); 1.608 + } 1.609 + 1.610 + to_hex_str(buf, inputtext, inputlength); 1.611 + fputs(buf, resp); 1.612 + fputc('\n', resp); 1.613 + 1.614 + /* loop 10,000 times */ 1.615 + for (j=0; j<10000; j++) { 1.616 + 1.617 + outputlen = 0; 1.618 + if (crypt == ENCRYPT) { 1.619 + /* inputtext == ciphertext outputtext == plaintext*/ 1.620 + rv = tdea_encrypt_buf(mode, key, 1.621 + (mode == NSS_DES_EDE3) ? NULL : iv, 1.622 + outputtext, &outputlen, 8, 1.623 + inputtext, 8); 1.624 + } else { 1.625 + /* inputtext == plaintext outputtext == ciphertext */ 1.626 + rv = tdea_decrypt_buf(mode, key, 1.627 + (mode == NSS_DES_EDE3) ? NULL : iv, 1.628 + outputtext, &outputlen, 8, 1.629 + inputtext, 8); 1.630 + } 1.631 + 1.632 + if (rv != SECSuccess) { 1.633 + goto loser; 1.634 + } 1.635 + if (outputlen != inputlength) { 1.636 + goto loser; 1.637 + } 1.638 + 1.639 + if (mode == NSS_DES_EDE3_CBC) { 1.640 + if (crypt == ENCRYPT) { 1.641 + if (j == 0) { 1.642 + /*P[j+1] = CV[0] */ 1.643 + memcpy(inputtext, iv, 8); 1.644 + } else { 1.645 + /* p[j+1] = C[j-1] */ 1.646 + memcpy(inputtext, outputtext_1, 8); 1.647 + } 1.648 + /* CV[j+1] = C[j] */ 1.649 + memcpy(iv, outputtext, 8); 1.650 + if (j != 9999) { 1.651 + /* save C[j-1] */ 1.652 + memcpy(outputtext_1, outputtext, 8); 1.653 + } 1.654 + } else { /* DECRYPT */ 1.655 + /* CV[j+1] = C[j] */ 1.656 + memcpy(iv, inputtext, 8); 1.657 + /* C[j+1] = P[j] */ 1.658 + memcpy(inputtext, outputtext, 8); 1.659 + } 1.660 + } else { 1.661 + /* ECB mode PT/CT[j+1] = CT/PT[j] */ 1.662 + memcpy(inputtext, outputtext, 8); 1.663 + } 1.664 + 1.665 + /* Save PT/CT[j-2] and PT/CT[j-1] */ 1.666 + if (j==9997) memcpy(outputtext_2, outputtext, 8); 1.667 + if (j==9998) memcpy(outputtext_1, outputtext, 8); 1.668 + /* done at the end of the for(j) loop */ 1.669 + } 1.670 + 1.671 + 1.672 + if (crypt == ENCRYPT) { 1.673 + /* Output CT[j] */ 1.674 + fputs("CIPHERTEXT = ", resp); 1.675 + } else { 1.676 + /* Output PT[j] */ 1.677 + fputs("PLAINTEXT = ", resp); 1.678 + } 1.679 + to_hex_str(buf, outputtext, 8); 1.680 + fputs(buf, resp); 1.681 + fputc('\n', resp); 1.682 + 1.683 + /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2] 1.684 + * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j] 1.685 + */ 1.686 + tdea_mct_next_keys(key, outputtext_2, 1.687 + outputtext_1, outputtext, numKeys); 1.688 + 1.689 + if (mode == NSS_DES_EDE3_CBC) { 1.690 + /* taken care of in the j=9999 iteration */ 1.691 + if (crypt == ENCRYPT) { 1.692 + /* P[i] = C[j-1] */ 1.693 + /* CV[i] = C[j] */ 1.694 + } else { 1.695 + /* taken care of in the j=9999 iteration */ 1.696 + /* CV[i] = C[j] */ 1.697 + /* C[i] = P[j] */ 1.698 + } 1.699 + } else { 1.700 + /* ECB PT/CT[i] = PT/CT[j] */ 1.701 + memcpy(inputtext, outputtext, 8); 1.702 + } 1.703 + /* done at the end of the for(i) loop */ 1.704 + fputc('\n', resp); 1.705 + } 1.706 + 1.707 +loser: 1.708 + return; 1.709 +} 1.710 + 1.711 +/* 1.712 + * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes. 1.713 + * by gathering the input from the request file, and then 1.714 + * calling tdea_mct_test. 1.715 + * 1.716 + * reqfn is the pathname of the input REQUEST file. 1.717 + * 1.718 + * The output RESPONSE file is written to stdout. 1.719 + */ 1.720 +void 1.721 +tdea_mct(int mode, char *reqfn) 1.722 +{ 1.723 + int i, j; 1.724 + char buf[80]; /* holds one line from the input REQUEST file. */ 1.725 + FILE *req; /* input stream from the REQUEST file */ 1.726 + FILE *resp; /* output stream to the RESPONSE file */ 1.727 + unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */ 1.728 + unsigned char key[24]; /* TDEA 3 key bundle */ 1.729 + unsigned int numKeys = 0; 1.730 + unsigned char plaintext[8]; /* PT[j] */ 1.731 + unsigned char ciphertext[8]; /* CT[j] */ 1.732 + unsigned char iv[8]; 1.733 + 1.734 + /* zeroize the variables for the test with this data set */ 1.735 + memset(key, 0, sizeof key); 1.736 + memset(plaintext, 0, sizeof plaintext); 1.737 + memset(ciphertext, 0, sizeof ciphertext); 1.738 + memset(iv, 0, sizeof iv); 1.739 + 1.740 + req = fopen(reqfn, "r"); 1.741 + resp = stdout; 1.742 + while (fgets(buf, sizeof buf, req) != NULL) { 1.743 + /* a comment or blank line */ 1.744 + if (buf[0] == '#' || buf[0] == '\n') { 1.745 + fputs(buf, resp); 1.746 + continue; 1.747 + } 1.748 + /* [ENCRYPT] or [DECRYPT] */ 1.749 + if (buf[0] == '[') { 1.750 + if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 1.751 + crypt = ENCRYPT; 1.752 + } else { 1.753 + crypt = DECRYPT; 1.754 + } 1.755 + fputs(buf, resp); 1.756 + continue; 1.757 + } 1.758 + /* NumKeys */ 1.759 + if (strncmp(&buf[0], "NumKeys", 7) == 0) { 1.760 + i = 7; 1.761 + while (isspace(buf[i]) || buf[i] == '=') { 1.762 + i++; 1.763 + } 1.764 + numKeys = atoi(&buf[i]); 1.765 + continue; 1.766 + } 1.767 + /* KEY1 = ... */ 1.768 + if (strncmp(buf, "KEY1", 4) == 0) { 1.769 + i = 4; 1.770 + while (isspace(buf[i]) || buf[i] == '=') { 1.771 + i++; 1.772 + } 1.773 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.774 + hex_to_byteval(&buf[i], &key[j]); 1.775 + } 1.776 + continue; 1.777 + } 1.778 + /* KEY2 = ... */ 1.779 + if (strncmp(buf, "KEY2", 4) == 0) { 1.780 + i = 4; 1.781 + while (isspace(buf[i]) || buf[i] == '=') { 1.782 + i++; 1.783 + } 1.784 + for (j=8; isxdigit(buf[i]); i+=2,j++) { 1.785 + hex_to_byteval(&buf[i], &key[j]); 1.786 + } 1.787 + continue; 1.788 + } 1.789 + /* KEY3 = ... */ 1.790 + if (strncmp(buf, "KEY3", 4) == 0) { 1.791 + i = 4; 1.792 + while (isspace(buf[i]) || buf[i] == '=') { 1.793 + i++; 1.794 + } 1.795 + for (j=16; isxdigit(buf[i]); i+=2,j++) { 1.796 + hex_to_byteval(&buf[i], &key[j]); 1.797 + } 1.798 + continue; 1.799 + } 1.800 + 1.801 + /* IV = ... */ 1.802 + if (strncmp(buf, "IV", 2) == 0) { 1.803 + i = 2; 1.804 + while (isspace(buf[i]) || buf[i] == '=') { 1.805 + i++; 1.806 + } 1.807 + for (j=0; j<sizeof iv; i+=2,j++) { 1.808 + hex_to_byteval(&buf[i], &iv[j]); 1.809 + } 1.810 + continue; 1.811 + } 1.812 + 1.813 + /* PLAINTEXT = ... */ 1.814 + if (strncmp(buf, "PLAINTEXT", 9) == 0) { 1.815 + 1.816 + /* sanity check */ 1.817 + if (crypt != ENCRYPT) { 1.818 + goto loser; 1.819 + } 1.820 + /* PT[0] = PT */ 1.821 + i = 9; 1.822 + while (isspace(buf[i]) || buf[i] == '=') { 1.823 + i++; 1.824 + } 1.825 + for (j=0; j<sizeof plaintext; i+=2,j++) { 1.826 + hex_to_byteval(&buf[i], &plaintext[j]); 1.827 + } 1.828 + 1.829 + /* do the Monte Carlo test */ 1.830 + if (mode==NSS_DES_EDE3) { 1.831 + tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp); 1.832 + } else { 1.833 + tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp); 1.834 + } 1.835 + continue; 1.836 + } 1.837 + /* CIPHERTEXT = ... */ 1.838 + if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 1.839 + /* sanity check */ 1.840 + if (crypt != DECRYPT) { 1.841 + goto loser; 1.842 + } 1.843 + /* CT[0] = CT */ 1.844 + i = 10; 1.845 + while (isspace(buf[i]) || buf[i] == '=') { 1.846 + i++; 1.847 + } 1.848 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.849 + hex_to_byteval(&buf[i], &ciphertext[j]); 1.850 + } 1.851 + 1.852 + /* do the Monte Carlo test */ 1.853 + if (mode==NSS_DES_EDE3) { 1.854 + tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp); 1.855 + } else { 1.856 + tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp); 1.857 + } 1.858 + continue; 1.859 + } 1.860 + } 1.861 + 1.862 +loser: 1.863 + fclose(req); 1.864 +} 1.865 + 1.866 + 1.867 +SECStatus 1.868 +aes_encrypt_buf( 1.869 + int mode, 1.870 + const unsigned char *key, unsigned int keysize, 1.871 + const unsigned char *iv, 1.872 + unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, 1.873 + const unsigned char *input, unsigned int inputlen) 1.874 +{ 1.875 + SECStatus rv = SECFailure; 1.876 + AESContext *cx; 1.877 + unsigned char doublecheck[10*16]; /* 1 to 10 blocks */ 1.878 + unsigned int doublechecklen = 0; 1.879 + 1.880 + cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16); 1.881 + if (cx == NULL) { 1.882 + goto loser; 1.883 + } 1.884 + rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen); 1.885 + if (rv != SECSuccess) { 1.886 + goto loser; 1.887 + } 1.888 + if (*outputlen != inputlen) { 1.889 + goto loser; 1.890 + } 1.891 + AES_DestroyContext(cx, PR_TRUE); 1.892 + cx = NULL; 1.893 + 1.894 + /* 1.895 + * Doublecheck our result by decrypting the ciphertext and 1.896 + * compare the output with the input plaintext. 1.897 + */ 1.898 + cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16); 1.899 + if (cx == NULL) { 1.900 + goto loser; 1.901 + } 1.902 + rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, 1.903 + output, *outputlen); 1.904 + if (rv != SECSuccess) { 1.905 + goto loser; 1.906 + } 1.907 + if (doublechecklen != *outputlen) { 1.908 + goto loser; 1.909 + } 1.910 + AES_DestroyContext(cx, PR_TRUE); 1.911 + cx = NULL; 1.912 + if (memcmp(doublecheck, input, inputlen) != 0) { 1.913 + goto loser; 1.914 + } 1.915 + rv = SECSuccess; 1.916 + 1.917 +loser: 1.918 + if (cx != NULL) { 1.919 + AES_DestroyContext(cx, PR_TRUE); 1.920 + } 1.921 + return rv; 1.922 +} 1.923 + 1.924 +SECStatus 1.925 +aes_decrypt_buf( 1.926 + int mode, 1.927 + const unsigned char *key, unsigned int keysize, 1.928 + const unsigned char *iv, 1.929 + unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, 1.930 + const unsigned char *input, unsigned int inputlen) 1.931 +{ 1.932 + SECStatus rv = SECFailure; 1.933 + AESContext *cx; 1.934 + unsigned char doublecheck[10*16]; /* 1 to 10 blocks */ 1.935 + unsigned int doublechecklen = 0; 1.936 + 1.937 + cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16); 1.938 + if (cx == NULL) { 1.939 + goto loser; 1.940 + } 1.941 + rv = AES_Decrypt(cx, output, outputlen, maxoutputlen, 1.942 + input, inputlen); 1.943 + if (rv != SECSuccess) { 1.944 + goto loser; 1.945 + } 1.946 + if (*outputlen != inputlen) { 1.947 + goto loser; 1.948 + } 1.949 + AES_DestroyContext(cx, PR_TRUE); 1.950 + cx = NULL; 1.951 + 1.952 + /* 1.953 + * Doublecheck our result by encrypting the plaintext and 1.954 + * compare the output with the input ciphertext. 1.955 + */ 1.956 + cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16); 1.957 + if (cx == NULL) { 1.958 + goto loser; 1.959 + } 1.960 + rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, 1.961 + output, *outputlen); 1.962 + if (rv != SECSuccess) { 1.963 + goto loser; 1.964 + } 1.965 + if (doublechecklen != *outputlen) { 1.966 + goto loser; 1.967 + } 1.968 + AES_DestroyContext(cx, PR_TRUE); 1.969 + cx = NULL; 1.970 + if (memcmp(doublecheck, input, inputlen) != 0) { 1.971 + goto loser; 1.972 + } 1.973 + rv = SECSuccess; 1.974 + 1.975 +loser: 1.976 + if (cx != NULL) { 1.977 + AES_DestroyContext(cx, PR_TRUE); 1.978 + } 1.979 + return rv; 1.980 +} 1.981 + 1.982 +/* 1.983 + * Perform the AES Known Answer Test (KAT) or Multi-block Message 1.984 + * Test (MMT) in ECB or CBC mode. The KAT (there are four types) 1.985 + * and MMT have the same structure: given the key and IV (CBC mode 1.986 + * only), encrypt the given plaintext or decrypt the given ciphertext. 1.987 + * So we can handle them the same way. 1.988 + * 1.989 + * reqfn is the pathname of the REQUEST file. 1.990 + * 1.991 + * The output RESPONSE file is written to stdout. 1.992 + */ 1.993 +void 1.994 +aes_kat_mmt(char *reqfn) 1.995 +{ 1.996 + char buf[512]; /* holds one line from the input REQUEST file. 1.997 + * needs to be large enough to hold the longest 1.998 + * line "CIPHERTEXT = <320 hex digits>\n". 1.999 + */ 1.1000 + FILE *aesreq; /* input stream from the REQUEST file */ 1.1001 + FILE *aesresp; /* output stream to the RESPONSE file */ 1.1002 + int i, j; 1.1003 + int mode; /* NSS_AES (ECB) or NSS_AES_CBC */ 1.1004 + int encrypt = 0; /* 1 means encrypt, 0 means decrypt */ 1.1005 + unsigned char key[32]; /* 128, 192, or 256 bits */ 1.1006 + unsigned int keysize; 1.1007 + unsigned char iv[16]; /* for all modes except ECB */ 1.1008 + unsigned char plaintext[10*16]; /* 1 to 10 blocks */ 1.1009 + unsigned int plaintextlen; 1.1010 + unsigned char ciphertext[10*16]; /* 1 to 10 blocks */ 1.1011 + unsigned int ciphertextlen; 1.1012 + SECStatus rv; 1.1013 + 1.1014 + aesreq = fopen(reqfn, "r"); 1.1015 + aesresp = stdout; 1.1016 + while (fgets(buf, sizeof buf, aesreq) != NULL) { 1.1017 + /* a comment or blank line */ 1.1018 + if (buf[0] == '#' || buf[0] == '\n') { 1.1019 + fputs(buf, aesresp); 1.1020 + continue; 1.1021 + } 1.1022 + /* [ENCRYPT] or [DECRYPT] */ 1.1023 + if (buf[0] == '[') { 1.1024 + if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 1.1025 + encrypt = 1; 1.1026 + } else { 1.1027 + encrypt = 0; 1.1028 + } 1.1029 + fputs(buf, aesresp); 1.1030 + continue; 1.1031 + } 1.1032 + /* "COUNT = x" begins a new data set */ 1.1033 + if (strncmp(buf, "COUNT", 5) == 0) { 1.1034 + mode = NSS_AES; 1.1035 + /* zeroize the variables for the test with this data set */ 1.1036 + memset(key, 0, sizeof key); 1.1037 + keysize = 0; 1.1038 + memset(iv, 0, sizeof iv); 1.1039 + memset(plaintext, 0, sizeof plaintext); 1.1040 + plaintextlen = 0; 1.1041 + memset(ciphertext, 0, sizeof ciphertext); 1.1042 + ciphertextlen = 0; 1.1043 + fputs(buf, aesresp); 1.1044 + continue; 1.1045 + } 1.1046 + /* KEY = ... */ 1.1047 + if (strncmp(buf, "KEY", 3) == 0) { 1.1048 + i = 3; 1.1049 + while (isspace(buf[i]) || buf[i] == '=') { 1.1050 + i++; 1.1051 + } 1.1052 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.1053 + hex_to_byteval(&buf[i], &key[j]); 1.1054 + } 1.1055 + keysize = j; 1.1056 + fputs(buf, aesresp); 1.1057 + continue; 1.1058 + } 1.1059 + /* IV = ... */ 1.1060 + if (strncmp(buf, "IV", 2) == 0) { 1.1061 + mode = NSS_AES_CBC; 1.1062 + i = 2; 1.1063 + while (isspace(buf[i]) || buf[i] == '=') { 1.1064 + i++; 1.1065 + } 1.1066 + for (j=0; j<sizeof iv; i+=2,j++) { 1.1067 + hex_to_byteval(&buf[i], &iv[j]); 1.1068 + } 1.1069 + fputs(buf, aesresp); 1.1070 + continue; 1.1071 + } 1.1072 + /* PLAINTEXT = ... */ 1.1073 + if (strncmp(buf, "PLAINTEXT", 9) == 0) { 1.1074 + /* sanity check */ 1.1075 + if (!encrypt) { 1.1076 + goto loser; 1.1077 + } 1.1078 + 1.1079 + i = 9; 1.1080 + while (isspace(buf[i]) || buf[i] == '=') { 1.1081 + i++; 1.1082 + } 1.1083 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.1084 + hex_to_byteval(&buf[i], &plaintext[j]); 1.1085 + } 1.1086 + plaintextlen = j; 1.1087 + 1.1088 + rv = aes_encrypt_buf(mode, key, keysize, 1.1089 + (mode == NSS_AES) ? NULL : iv, 1.1090 + ciphertext, &ciphertextlen, sizeof ciphertext, 1.1091 + plaintext, plaintextlen); 1.1092 + if (rv != SECSuccess) { 1.1093 + goto loser; 1.1094 + } 1.1095 + 1.1096 + fputs(buf, aesresp); 1.1097 + fputs("CIPHERTEXT = ", aesresp); 1.1098 + to_hex_str(buf, ciphertext, ciphertextlen); 1.1099 + fputs(buf, aesresp); 1.1100 + fputc('\n', aesresp); 1.1101 + continue; 1.1102 + } 1.1103 + /* CIPHERTEXT = ... */ 1.1104 + if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 1.1105 + /* sanity check */ 1.1106 + if (encrypt) { 1.1107 + goto loser; 1.1108 + } 1.1109 + 1.1110 + i = 10; 1.1111 + while (isspace(buf[i]) || buf[i] == '=') { 1.1112 + i++; 1.1113 + } 1.1114 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.1115 + hex_to_byteval(&buf[i], &ciphertext[j]); 1.1116 + } 1.1117 + ciphertextlen = j; 1.1118 + 1.1119 + rv = aes_decrypt_buf(mode, key, keysize, 1.1120 + (mode == NSS_AES) ? NULL : iv, 1.1121 + plaintext, &plaintextlen, sizeof plaintext, 1.1122 + ciphertext, ciphertextlen); 1.1123 + if (rv != SECSuccess) { 1.1124 + goto loser; 1.1125 + } 1.1126 + 1.1127 + fputs(buf, aesresp); 1.1128 + fputs("PLAINTEXT = ", aesresp); 1.1129 + to_hex_str(buf, plaintext, plaintextlen); 1.1130 + fputs(buf, aesresp); 1.1131 + fputc('\n', aesresp); 1.1132 + continue; 1.1133 + } 1.1134 + } 1.1135 +loser: 1.1136 + fclose(aesreq); 1.1137 +} 1.1138 + 1.1139 +/* 1.1140 + * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo 1.1141 + * Test (MCT) in ECB and CBC modes. 1.1142 + */ 1.1143 +void 1.1144 +aes_mct_next_key(unsigned char *key, unsigned int keysize, 1.1145 + const unsigned char *ciphertext_1, const unsigned char *ciphertext) 1.1146 +{ 1.1147 + int k; 1.1148 + 1.1149 + switch (keysize) { 1.1150 + case 16: /* 128-bit key */ 1.1151 + /* Key[i+1] = Key[i] xor CT[j] */ 1.1152 + for (k=0; k<16; k++) { 1.1153 + key[k] ^= ciphertext[k]; 1.1154 + } 1.1155 + break; 1.1156 + case 24: /* 192-bit key */ 1.1157 + /* 1.1158 + * Key[i+1] = Key[i] xor (last 64-bits of 1.1159 + * CT[j-1] || CT[j]) 1.1160 + */ 1.1161 + for (k=0; k<8; k++) { 1.1162 + key[k] ^= ciphertext_1[k+8]; 1.1163 + } 1.1164 + for (k=8; k<24; k++) { 1.1165 + key[k] ^= ciphertext[k-8]; 1.1166 + } 1.1167 + break; 1.1168 + case 32: /* 256-bit key */ 1.1169 + /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */ 1.1170 + for (k=0; k<16; k++) { 1.1171 + key[k] ^= ciphertext_1[k]; 1.1172 + } 1.1173 + for (k=16; k<32; k++) { 1.1174 + key[k] ^= ciphertext[k-16]; 1.1175 + } 1.1176 + break; 1.1177 + } 1.1178 +} 1.1179 + 1.1180 +/* 1.1181 + * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises 1.1182 + * our AES code in streaming mode because the plaintext or ciphertext 1.1183 + * is generated block by block as we go, so we can't collect all the 1.1184 + * plaintext or ciphertext in one buffer and encrypt or decrypt it in 1.1185 + * one shot. 1.1186 + * 1.1187 + * reqfn is the pathname of the input REQUEST file. 1.1188 + * 1.1189 + * The output RESPONSE file is written to stdout. 1.1190 + */ 1.1191 +void 1.1192 +aes_ecb_mct(char *reqfn) 1.1193 +{ 1.1194 + char buf[80]; /* holds one line from the input REQUEST file. 1.1195 + * needs to be large enough to hold the longest 1.1196 + * line "KEY = <64 hex digits>\n". 1.1197 + */ 1.1198 + FILE *aesreq; /* input stream from the REQUEST file */ 1.1199 + FILE *aesresp; /* output stream to the RESPONSE file */ 1.1200 + int i, j; 1.1201 + int encrypt = 0; /* 1 means encrypt, 0 means decrypt */ 1.1202 + unsigned char key[32]; /* 128, 192, or 256 bits */ 1.1203 + unsigned int keysize; 1.1204 + unsigned char plaintext[16]; /* PT[j] */ 1.1205 + unsigned char plaintext_1[16]; /* PT[j-1] */ 1.1206 + unsigned char ciphertext[16]; /* CT[j] */ 1.1207 + unsigned char ciphertext_1[16]; /* CT[j-1] */ 1.1208 + unsigned char doublecheck[16]; 1.1209 + unsigned int outputlen; 1.1210 + AESContext *cx = NULL; /* the operation being tested */ 1.1211 + AESContext *cx2 = NULL; /* the inverse operation done in parallel 1.1212 + * to doublecheck our result. 1.1213 + */ 1.1214 + SECStatus rv; 1.1215 + 1.1216 + aesreq = fopen(reqfn, "r"); 1.1217 + aesresp = stdout; 1.1218 + while (fgets(buf, sizeof buf, aesreq) != NULL) { 1.1219 + /* a comment or blank line */ 1.1220 + if (buf[0] == '#' || buf[0] == '\n') { 1.1221 + fputs(buf, aesresp); 1.1222 + continue; 1.1223 + } 1.1224 + /* [ENCRYPT] or [DECRYPT] */ 1.1225 + if (buf[0] == '[') { 1.1226 + if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 1.1227 + encrypt = 1; 1.1228 + } else { 1.1229 + encrypt = 0; 1.1230 + } 1.1231 + fputs(buf, aesresp); 1.1232 + continue; 1.1233 + } 1.1234 + /* "COUNT = x" begins a new data set */ 1.1235 + if (strncmp(buf, "COUNT", 5) == 0) { 1.1236 + /* zeroize the variables for the test with this data set */ 1.1237 + memset(key, 0, sizeof key); 1.1238 + keysize = 0; 1.1239 + memset(plaintext, 0, sizeof plaintext); 1.1240 + memset(ciphertext, 0, sizeof ciphertext); 1.1241 + continue; 1.1242 + } 1.1243 + /* KEY = ... */ 1.1244 + if (strncmp(buf, "KEY", 3) == 0) { 1.1245 + /* Key[0] = Key */ 1.1246 + i = 3; 1.1247 + while (isspace(buf[i]) || buf[i] == '=') { 1.1248 + i++; 1.1249 + } 1.1250 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.1251 + hex_to_byteval(&buf[i], &key[j]); 1.1252 + } 1.1253 + keysize = j; 1.1254 + continue; 1.1255 + } 1.1256 + /* PLAINTEXT = ... */ 1.1257 + if (strncmp(buf, "PLAINTEXT", 9) == 0) { 1.1258 + /* sanity check */ 1.1259 + if (!encrypt) { 1.1260 + goto loser; 1.1261 + } 1.1262 + /* PT[0] = PT */ 1.1263 + i = 9; 1.1264 + while (isspace(buf[i]) || buf[i] == '=') { 1.1265 + i++; 1.1266 + } 1.1267 + for (j=0; j<sizeof plaintext; i+=2,j++) { 1.1268 + hex_to_byteval(&buf[i], &plaintext[j]); 1.1269 + } 1.1270 + 1.1271 + for (i=0; i<100; i++) { 1.1272 + sprintf(buf, "COUNT = %d\n", i); 1.1273 + fputs(buf, aesresp); 1.1274 + /* Output Key[i] */ 1.1275 + fputs("KEY = ", aesresp); 1.1276 + to_hex_str(buf, key, keysize); 1.1277 + fputs(buf, aesresp); 1.1278 + fputc('\n', aesresp); 1.1279 + /* Output PT[0] */ 1.1280 + fputs("PLAINTEXT = ", aesresp); 1.1281 + to_hex_str(buf, plaintext, sizeof plaintext); 1.1282 + fputs(buf, aesresp); 1.1283 + fputc('\n', aesresp); 1.1284 + 1.1285 + cx = AES_CreateContext(key, NULL, NSS_AES, 1.1286 + PR_TRUE, keysize, 16); 1.1287 + if (cx == NULL) { 1.1288 + goto loser; 1.1289 + } 1.1290 + /* 1.1291 + * doublecheck our result by decrypting the result 1.1292 + * and comparing the output with the plaintext. 1.1293 + */ 1.1294 + cx2 = AES_CreateContext(key, NULL, NSS_AES, 1.1295 + PR_FALSE, keysize, 16); 1.1296 + if (cx2 == NULL) { 1.1297 + goto loser; 1.1298 + } 1.1299 + for (j=0; j<1000; j++) { 1.1300 + /* Save CT[j-1] */ 1.1301 + memcpy(ciphertext_1, ciphertext, sizeof ciphertext); 1.1302 + 1.1303 + /* CT[j] = AES(Key[i], PT[j]) */ 1.1304 + outputlen = 0; 1.1305 + rv = AES_Encrypt(cx, 1.1306 + ciphertext, &outputlen, sizeof ciphertext, 1.1307 + plaintext, sizeof plaintext); 1.1308 + if (rv != SECSuccess) { 1.1309 + goto loser; 1.1310 + } 1.1311 + if (outputlen != sizeof plaintext) { 1.1312 + goto loser; 1.1313 + } 1.1314 + 1.1315 + /* doublecheck our result */ 1.1316 + outputlen = 0; 1.1317 + rv = AES_Decrypt(cx2, 1.1318 + doublecheck, &outputlen, sizeof doublecheck, 1.1319 + ciphertext, sizeof ciphertext); 1.1320 + if (rv != SECSuccess) { 1.1321 + goto loser; 1.1322 + } 1.1323 + if (outputlen != sizeof ciphertext) { 1.1324 + goto loser; 1.1325 + } 1.1326 + if (memcmp(doublecheck, plaintext, sizeof plaintext)) { 1.1327 + goto loser; 1.1328 + } 1.1329 + 1.1330 + /* PT[j+1] = CT[j] */ 1.1331 + memcpy(plaintext, ciphertext, sizeof plaintext); 1.1332 + } 1.1333 + AES_DestroyContext(cx, PR_TRUE); 1.1334 + cx = NULL; 1.1335 + AES_DestroyContext(cx2, PR_TRUE); 1.1336 + cx2 = NULL; 1.1337 + 1.1338 + /* Output CT[j] */ 1.1339 + fputs("CIPHERTEXT = ", aesresp); 1.1340 + to_hex_str(buf, ciphertext, sizeof ciphertext); 1.1341 + fputs(buf, aesresp); 1.1342 + fputc('\n', aesresp); 1.1343 + 1.1344 + /* Key[i+1] = Key[i] xor ... */ 1.1345 + aes_mct_next_key(key, keysize, ciphertext_1, ciphertext); 1.1346 + /* PT[0] = CT[j] */ 1.1347 + /* done at the end of the for(j) loop */ 1.1348 + 1.1349 + fputc('\n', aesresp); 1.1350 + } 1.1351 + 1.1352 + continue; 1.1353 + } 1.1354 + /* CIPHERTEXT = ... */ 1.1355 + if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 1.1356 + /* sanity check */ 1.1357 + if (encrypt) { 1.1358 + goto loser; 1.1359 + } 1.1360 + /* CT[0] = CT */ 1.1361 + i = 10; 1.1362 + while (isspace(buf[i]) || buf[i] == '=') { 1.1363 + i++; 1.1364 + } 1.1365 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.1366 + hex_to_byteval(&buf[i], &ciphertext[j]); 1.1367 + } 1.1368 + 1.1369 + for (i=0; i<100; i++) { 1.1370 + sprintf(buf, "COUNT = %d\n", i); 1.1371 + fputs(buf, aesresp); 1.1372 + /* Output Key[i] */ 1.1373 + fputs("KEY = ", aesresp); 1.1374 + to_hex_str(buf, key, keysize); 1.1375 + fputs(buf, aesresp); 1.1376 + fputc('\n', aesresp); 1.1377 + /* Output CT[0] */ 1.1378 + fputs("CIPHERTEXT = ", aesresp); 1.1379 + to_hex_str(buf, ciphertext, sizeof ciphertext); 1.1380 + fputs(buf, aesresp); 1.1381 + fputc('\n', aesresp); 1.1382 + 1.1383 + cx = AES_CreateContext(key, NULL, NSS_AES, 1.1384 + PR_FALSE, keysize, 16); 1.1385 + if (cx == NULL) { 1.1386 + goto loser; 1.1387 + } 1.1388 + /* 1.1389 + * doublecheck our result by encrypting the result 1.1390 + * and comparing the output with the ciphertext. 1.1391 + */ 1.1392 + cx2 = AES_CreateContext(key, NULL, NSS_AES, 1.1393 + PR_TRUE, keysize, 16); 1.1394 + if (cx2 == NULL) { 1.1395 + goto loser; 1.1396 + } 1.1397 + for (j=0; j<1000; j++) { 1.1398 + /* Save PT[j-1] */ 1.1399 + memcpy(plaintext_1, plaintext, sizeof plaintext); 1.1400 + 1.1401 + /* PT[j] = AES(Key[i], CT[j]) */ 1.1402 + outputlen = 0; 1.1403 + rv = AES_Decrypt(cx, 1.1404 + plaintext, &outputlen, sizeof plaintext, 1.1405 + ciphertext, sizeof ciphertext); 1.1406 + if (rv != SECSuccess) { 1.1407 + goto loser; 1.1408 + } 1.1409 + if (outputlen != sizeof ciphertext) { 1.1410 + goto loser; 1.1411 + } 1.1412 + 1.1413 + /* doublecheck our result */ 1.1414 + outputlen = 0; 1.1415 + rv = AES_Encrypt(cx2, 1.1416 + doublecheck, &outputlen, sizeof doublecheck, 1.1417 + plaintext, sizeof plaintext); 1.1418 + if (rv != SECSuccess) { 1.1419 + goto loser; 1.1420 + } 1.1421 + if (outputlen != sizeof plaintext) { 1.1422 + goto loser; 1.1423 + } 1.1424 + if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) { 1.1425 + goto loser; 1.1426 + } 1.1427 + 1.1428 + /* CT[j+1] = PT[j] */ 1.1429 + memcpy(ciphertext, plaintext, sizeof ciphertext); 1.1430 + } 1.1431 + AES_DestroyContext(cx, PR_TRUE); 1.1432 + cx = NULL; 1.1433 + AES_DestroyContext(cx2, PR_TRUE); 1.1434 + cx2 = NULL; 1.1435 + 1.1436 + /* Output PT[j] */ 1.1437 + fputs("PLAINTEXT = ", aesresp); 1.1438 + to_hex_str(buf, plaintext, sizeof plaintext); 1.1439 + fputs(buf, aesresp); 1.1440 + fputc('\n', aesresp); 1.1441 + 1.1442 + /* Key[i+1] = Key[i] xor ... */ 1.1443 + aes_mct_next_key(key, keysize, plaintext_1, plaintext); 1.1444 + /* CT[0] = PT[j] */ 1.1445 + /* done at the end of the for(j) loop */ 1.1446 + 1.1447 + fputc('\n', aesresp); 1.1448 + } 1.1449 + 1.1450 + continue; 1.1451 + } 1.1452 + } 1.1453 +loser: 1.1454 + if (cx != NULL) { 1.1455 + AES_DestroyContext(cx, PR_TRUE); 1.1456 + } 1.1457 + if (cx2 != NULL) { 1.1458 + AES_DestroyContext(cx2, PR_TRUE); 1.1459 + } 1.1460 + fclose(aesreq); 1.1461 +} 1.1462 + 1.1463 +/* 1.1464 + * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises 1.1465 + * our AES code in streaming mode because the plaintext or ciphertext 1.1466 + * is generated block by block as we go, so we can't collect all the 1.1467 + * plaintext or ciphertext in one buffer and encrypt or decrypt it in 1.1468 + * one shot. 1.1469 + * 1.1470 + * reqfn is the pathname of the input REQUEST file. 1.1471 + * 1.1472 + * The output RESPONSE file is written to stdout. 1.1473 + */ 1.1474 +void 1.1475 +aes_cbc_mct(char *reqfn) 1.1476 +{ 1.1477 + char buf[80]; /* holds one line from the input REQUEST file. 1.1478 + * needs to be large enough to hold the longest 1.1479 + * line "KEY = <64 hex digits>\n". 1.1480 + */ 1.1481 + FILE *aesreq; /* input stream from the REQUEST file */ 1.1482 + FILE *aesresp; /* output stream to the RESPONSE file */ 1.1483 + int i, j; 1.1484 + int encrypt = 0; /* 1 means encrypt, 0 means decrypt */ 1.1485 + unsigned char key[32]; /* 128, 192, or 256 bits */ 1.1486 + unsigned int keysize; 1.1487 + unsigned char iv[16]; 1.1488 + unsigned char plaintext[16]; /* PT[j] */ 1.1489 + unsigned char plaintext_1[16]; /* PT[j-1] */ 1.1490 + unsigned char ciphertext[16]; /* CT[j] */ 1.1491 + unsigned char ciphertext_1[16]; /* CT[j-1] */ 1.1492 + unsigned char doublecheck[16]; 1.1493 + unsigned int outputlen; 1.1494 + AESContext *cx = NULL; /* the operation being tested */ 1.1495 + AESContext *cx2 = NULL; /* the inverse operation done in parallel 1.1496 + * to doublecheck our result. 1.1497 + */ 1.1498 + SECStatus rv; 1.1499 + 1.1500 + aesreq = fopen(reqfn, "r"); 1.1501 + aesresp = stdout; 1.1502 + while (fgets(buf, sizeof buf, aesreq) != NULL) { 1.1503 + /* a comment or blank line */ 1.1504 + if (buf[0] == '#' || buf[0] == '\n') { 1.1505 + fputs(buf, aesresp); 1.1506 + continue; 1.1507 + } 1.1508 + /* [ENCRYPT] or [DECRYPT] */ 1.1509 + if (buf[0] == '[') { 1.1510 + if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 1.1511 + encrypt = 1; 1.1512 + } else { 1.1513 + encrypt = 0; 1.1514 + } 1.1515 + fputs(buf, aesresp); 1.1516 + continue; 1.1517 + } 1.1518 + /* "COUNT = x" begins a new data set */ 1.1519 + if (strncmp(buf, "COUNT", 5) == 0) { 1.1520 + /* zeroize the variables for the test with this data set */ 1.1521 + memset(key, 0, sizeof key); 1.1522 + keysize = 0; 1.1523 + memset(iv, 0, sizeof iv); 1.1524 + memset(plaintext, 0, sizeof plaintext); 1.1525 + memset(ciphertext, 0, sizeof ciphertext); 1.1526 + continue; 1.1527 + } 1.1528 + /* KEY = ... */ 1.1529 + if (strncmp(buf, "KEY", 3) == 0) { 1.1530 + /* Key[0] = Key */ 1.1531 + i = 3; 1.1532 + while (isspace(buf[i]) || buf[i] == '=') { 1.1533 + i++; 1.1534 + } 1.1535 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.1536 + hex_to_byteval(&buf[i], &key[j]); 1.1537 + } 1.1538 + keysize = j; 1.1539 + continue; 1.1540 + } 1.1541 + /* IV = ... */ 1.1542 + if (strncmp(buf, "IV", 2) == 0) { 1.1543 + /* IV[0] = IV */ 1.1544 + i = 2; 1.1545 + while (isspace(buf[i]) || buf[i] == '=') { 1.1546 + i++; 1.1547 + } 1.1548 + for (j=0; j<sizeof iv; i+=2,j++) { 1.1549 + hex_to_byteval(&buf[i], &iv[j]); 1.1550 + } 1.1551 + continue; 1.1552 + } 1.1553 + /* PLAINTEXT = ... */ 1.1554 + if (strncmp(buf, "PLAINTEXT", 9) == 0) { 1.1555 + /* sanity check */ 1.1556 + if (!encrypt) { 1.1557 + goto loser; 1.1558 + } 1.1559 + /* PT[0] = PT */ 1.1560 + i = 9; 1.1561 + while (isspace(buf[i]) || buf[i] == '=') { 1.1562 + i++; 1.1563 + } 1.1564 + for (j=0; j<sizeof plaintext; i+=2,j++) { 1.1565 + hex_to_byteval(&buf[i], &plaintext[j]); 1.1566 + } 1.1567 + 1.1568 + for (i=0; i<100; i++) { 1.1569 + sprintf(buf, "COUNT = %d\n", i); 1.1570 + fputs(buf, aesresp); 1.1571 + /* Output Key[i] */ 1.1572 + fputs("KEY = ", aesresp); 1.1573 + to_hex_str(buf, key, keysize); 1.1574 + fputs(buf, aesresp); 1.1575 + fputc('\n', aesresp); 1.1576 + /* Output IV[i] */ 1.1577 + fputs("IV = ", aesresp); 1.1578 + to_hex_str(buf, iv, sizeof iv); 1.1579 + fputs(buf, aesresp); 1.1580 + fputc('\n', aesresp); 1.1581 + /* Output PT[0] */ 1.1582 + fputs("PLAINTEXT = ", aesresp); 1.1583 + to_hex_str(buf, plaintext, sizeof plaintext); 1.1584 + fputs(buf, aesresp); 1.1585 + fputc('\n', aesresp); 1.1586 + 1.1587 + cx = AES_CreateContext(key, iv, NSS_AES_CBC, 1.1588 + PR_TRUE, keysize, 16); 1.1589 + if (cx == NULL) { 1.1590 + goto loser; 1.1591 + } 1.1592 + /* 1.1593 + * doublecheck our result by decrypting the result 1.1594 + * and comparing the output with the plaintext. 1.1595 + */ 1.1596 + cx2 = AES_CreateContext(key, iv, NSS_AES_CBC, 1.1597 + PR_FALSE, keysize, 16); 1.1598 + if (cx2 == NULL) { 1.1599 + goto loser; 1.1600 + } 1.1601 + /* CT[-1] = IV[i] */ 1.1602 + memcpy(ciphertext, iv, sizeof ciphertext); 1.1603 + for (j=0; j<1000; j++) { 1.1604 + /* Save CT[j-1] */ 1.1605 + memcpy(ciphertext_1, ciphertext, sizeof ciphertext); 1.1606 + /* 1.1607 + * If ( j=0 ) 1.1608 + * CT[j] = AES(Key[i], IV[i], PT[j]) 1.1609 + * PT[j+1] = IV[i] (= CT[j-1]) 1.1610 + * Else 1.1611 + * CT[j] = AES(Key[i], PT[j]) 1.1612 + * PT[j+1] = CT[j-1] 1.1613 + */ 1.1614 + outputlen = 0; 1.1615 + rv = AES_Encrypt(cx, 1.1616 + ciphertext, &outputlen, sizeof ciphertext, 1.1617 + plaintext, sizeof plaintext); 1.1618 + if (rv != SECSuccess) { 1.1619 + goto loser; 1.1620 + } 1.1621 + if (outputlen != sizeof plaintext) { 1.1622 + goto loser; 1.1623 + } 1.1624 + 1.1625 + /* doublecheck our result */ 1.1626 + outputlen = 0; 1.1627 + rv = AES_Decrypt(cx2, 1.1628 + doublecheck, &outputlen, sizeof doublecheck, 1.1629 + ciphertext, sizeof ciphertext); 1.1630 + if (rv != SECSuccess) { 1.1631 + goto loser; 1.1632 + } 1.1633 + if (outputlen != sizeof ciphertext) { 1.1634 + goto loser; 1.1635 + } 1.1636 + if (memcmp(doublecheck, plaintext, sizeof plaintext)) { 1.1637 + goto loser; 1.1638 + } 1.1639 + 1.1640 + memcpy(plaintext, ciphertext_1, sizeof plaintext); 1.1641 + } 1.1642 + AES_DestroyContext(cx, PR_TRUE); 1.1643 + cx = NULL; 1.1644 + AES_DestroyContext(cx2, PR_TRUE); 1.1645 + cx2 = NULL; 1.1646 + 1.1647 + /* Output CT[j] */ 1.1648 + fputs("CIPHERTEXT = ", aesresp); 1.1649 + to_hex_str(buf, ciphertext, sizeof ciphertext); 1.1650 + fputs(buf, aesresp); 1.1651 + fputc('\n', aesresp); 1.1652 + 1.1653 + /* Key[i+1] = Key[i] xor ... */ 1.1654 + aes_mct_next_key(key, keysize, ciphertext_1, ciphertext); 1.1655 + /* IV[i+1] = CT[j] */ 1.1656 + memcpy(iv, ciphertext, sizeof iv); 1.1657 + /* PT[0] = CT[j-1] */ 1.1658 + /* done at the end of the for(j) loop */ 1.1659 + 1.1660 + fputc('\n', aesresp); 1.1661 + } 1.1662 + 1.1663 + continue; 1.1664 + } 1.1665 + /* CIPHERTEXT = ... */ 1.1666 + if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 1.1667 + /* sanity check */ 1.1668 + if (encrypt) { 1.1669 + goto loser; 1.1670 + } 1.1671 + /* CT[0] = CT */ 1.1672 + i = 10; 1.1673 + while (isspace(buf[i]) || buf[i] == '=') { 1.1674 + i++; 1.1675 + } 1.1676 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.1677 + hex_to_byteval(&buf[i], &ciphertext[j]); 1.1678 + } 1.1679 + 1.1680 + for (i=0; i<100; i++) { 1.1681 + sprintf(buf, "COUNT = %d\n", i); 1.1682 + fputs(buf, aesresp); 1.1683 + /* Output Key[i] */ 1.1684 + fputs("KEY = ", aesresp); 1.1685 + to_hex_str(buf, key, keysize); 1.1686 + fputs(buf, aesresp); 1.1687 + fputc('\n', aesresp); 1.1688 + /* Output IV[i] */ 1.1689 + fputs("IV = ", aesresp); 1.1690 + to_hex_str(buf, iv, sizeof iv); 1.1691 + fputs(buf, aesresp); 1.1692 + fputc('\n', aesresp); 1.1693 + /* Output CT[0] */ 1.1694 + fputs("CIPHERTEXT = ", aesresp); 1.1695 + to_hex_str(buf, ciphertext, sizeof ciphertext); 1.1696 + fputs(buf, aesresp); 1.1697 + fputc('\n', aesresp); 1.1698 + 1.1699 + cx = AES_CreateContext(key, iv, NSS_AES_CBC, 1.1700 + PR_FALSE, keysize, 16); 1.1701 + if (cx == NULL) { 1.1702 + goto loser; 1.1703 + } 1.1704 + /* 1.1705 + * doublecheck our result by encrypting the result 1.1706 + * and comparing the output with the ciphertext. 1.1707 + */ 1.1708 + cx2 = AES_CreateContext(key, iv, NSS_AES_CBC, 1.1709 + PR_TRUE, keysize, 16); 1.1710 + if (cx2 == NULL) { 1.1711 + goto loser; 1.1712 + } 1.1713 + /* PT[-1] = IV[i] */ 1.1714 + memcpy(plaintext, iv, sizeof plaintext); 1.1715 + for (j=0; j<1000; j++) { 1.1716 + /* Save PT[j-1] */ 1.1717 + memcpy(plaintext_1, plaintext, sizeof plaintext); 1.1718 + /* 1.1719 + * If ( j=0 ) 1.1720 + * PT[j] = AES(Key[i], IV[i], CT[j]) 1.1721 + * CT[j+1] = IV[i] (= PT[j-1]) 1.1722 + * Else 1.1723 + * PT[j] = AES(Key[i], CT[j]) 1.1724 + * CT[j+1] = PT[j-1] 1.1725 + */ 1.1726 + outputlen = 0; 1.1727 + rv = AES_Decrypt(cx, 1.1728 + plaintext, &outputlen, sizeof plaintext, 1.1729 + ciphertext, sizeof ciphertext); 1.1730 + if (rv != SECSuccess) { 1.1731 + goto loser; 1.1732 + } 1.1733 + if (outputlen != sizeof ciphertext) { 1.1734 + goto loser; 1.1735 + } 1.1736 + 1.1737 + /* doublecheck our result */ 1.1738 + outputlen = 0; 1.1739 + rv = AES_Encrypt(cx2, 1.1740 + doublecheck, &outputlen, sizeof doublecheck, 1.1741 + plaintext, sizeof plaintext); 1.1742 + if (rv != SECSuccess) { 1.1743 + goto loser; 1.1744 + } 1.1745 + if (outputlen != sizeof plaintext) { 1.1746 + goto loser; 1.1747 + } 1.1748 + if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) { 1.1749 + goto loser; 1.1750 + } 1.1751 + 1.1752 + memcpy(ciphertext, plaintext_1, sizeof ciphertext); 1.1753 + } 1.1754 + AES_DestroyContext(cx, PR_TRUE); 1.1755 + cx = NULL; 1.1756 + AES_DestroyContext(cx2, PR_TRUE); 1.1757 + cx2 = NULL; 1.1758 + 1.1759 + /* Output PT[j] */ 1.1760 + fputs("PLAINTEXT = ", aesresp); 1.1761 + to_hex_str(buf, plaintext, sizeof plaintext); 1.1762 + fputs(buf, aesresp); 1.1763 + fputc('\n', aesresp); 1.1764 + 1.1765 + /* Key[i+1] = Key[i] xor ... */ 1.1766 + aes_mct_next_key(key, keysize, plaintext_1, plaintext); 1.1767 + /* IV[i+1] = PT[j] */ 1.1768 + memcpy(iv, plaintext, sizeof iv); 1.1769 + /* CT[0] = PT[j-1] */ 1.1770 + /* done at the end of the for(j) loop */ 1.1771 + 1.1772 + fputc('\n', aesresp); 1.1773 + } 1.1774 + 1.1775 + continue; 1.1776 + } 1.1777 + } 1.1778 +loser: 1.1779 + if (cx != NULL) { 1.1780 + AES_DestroyContext(cx, PR_TRUE); 1.1781 + } 1.1782 + if (cx2 != NULL) { 1.1783 + AES_DestroyContext(cx2, PR_TRUE); 1.1784 + } 1.1785 + fclose(aesreq); 1.1786 +} 1.1787 + 1.1788 +void write_compact_string(FILE *out, unsigned char *hash, unsigned int len) 1.1789 +{ 1.1790 + unsigned int i; 1.1791 + int j, count = 0, last = -1, z = 0; 1.1792 + long start = ftell(out); 1.1793 + for (i=0; i<len; i++) { 1.1794 + for (j=7; j>=0; j--) { 1.1795 + if (last < 0) { 1.1796 + last = (hash[i] & (1 << j)) ? 1 : 0; 1.1797 + fprintf(out, "%d ", last); 1.1798 + count = 1; 1.1799 + } else if (hash[i] & (1 << j)) { 1.1800 + if (last) { 1.1801 + count++; 1.1802 + } else { 1.1803 + last = 0; 1.1804 + fprintf(out, "%d ", count); 1.1805 + count = 1; 1.1806 + z++; 1.1807 + } 1.1808 + } else { 1.1809 + if (!last) { 1.1810 + count++; 1.1811 + } else { 1.1812 + last = 1; 1.1813 + fprintf(out, "%d ", count); 1.1814 + count = 1; 1.1815 + z++; 1.1816 + } 1.1817 + } 1.1818 + } 1.1819 + } 1.1820 + fprintf(out, "^\n"); 1.1821 + fseek(out, start, SEEK_SET); 1.1822 + fprintf(out, "%d ", z); 1.1823 + fseek(out, 0, SEEK_END); 1.1824 +} 1.1825 + 1.1826 +int get_next_line(FILE *req, char *key, char *val, FILE *rsp) 1.1827 +{ 1.1828 + int ignore = 0; 1.1829 + char *writeto = key; 1.1830 + int w = 0; 1.1831 + int c; 1.1832 + while ((c = fgetc(req)) != EOF) { 1.1833 + if (ignore) { 1.1834 + fprintf(rsp, "%c", c); 1.1835 + if (c == '\n') return ignore; 1.1836 + } else if (c == '\n') { 1.1837 + break; 1.1838 + } else if (c == '#') { 1.1839 + ignore = 1; 1.1840 + fprintf(rsp, "%c", c); 1.1841 + } else if (c == '=') { 1.1842 + writeto[w] = '\0'; 1.1843 + w = 0; 1.1844 + writeto = val; 1.1845 + } else if (c == ' ' || c == '[' || c == ']') { 1.1846 + continue; 1.1847 + } else { 1.1848 + writeto[w++] = c; 1.1849 + } 1.1850 + } 1.1851 + writeto[w] = '\0'; 1.1852 + return (c == EOF) ? -1 : ignore; 1.1853 +} 1.1854 + 1.1855 +#ifndef NSS_DISABLE_ECC 1.1856 +typedef struct curveNameTagPairStr { 1.1857 + char *curveName; 1.1858 + SECOidTag curveOidTag; 1.1859 +} CurveNameTagPair; 1.1860 + 1.1861 +#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 1.1862 +/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ 1.1863 + 1.1864 +static CurveNameTagPair nameTagPair[] = 1.1865 +{ 1.1866 + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, 1.1867 + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, 1.1868 + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, 1.1869 + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, 1.1870 + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, 1.1871 + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, 1.1872 + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, 1.1873 + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, 1.1874 + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, 1.1875 + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, 1.1876 + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, 1.1877 + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, 1.1878 + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, 1.1879 + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, 1.1880 + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, 1.1881 + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, 1.1882 + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, 1.1883 + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, 1.1884 + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, 1.1885 + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, 1.1886 + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, 1.1887 + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, 1.1888 + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, 1.1889 + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, 1.1890 + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, 1.1891 + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, 1.1892 + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, 1.1893 + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, 1.1894 + { "secp192r1", SEC_OID_SECG_EC_SECP192R1}, 1.1895 + { "nistp192", SEC_OID_SECG_EC_SECP192R1}, 1.1896 + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, 1.1897 + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, 1.1898 + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, 1.1899 + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, 1.1900 + { "secp256r1", SEC_OID_SECG_EC_SECP256R1}, 1.1901 + { "nistp256", SEC_OID_SECG_EC_SECP256R1}, 1.1902 + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, 1.1903 + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, 1.1904 + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, 1.1905 + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, 1.1906 + 1.1907 + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, 1.1908 + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, 1.1909 + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, 1.1910 + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, 1.1911 + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, 1.1912 + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, 1.1913 + 1.1914 + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, 1.1915 + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, 1.1916 + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, 1.1917 + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, 1.1918 + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, 1.1919 + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, 1.1920 + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, 1.1921 + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, 1.1922 + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, 1.1923 + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, 1.1924 + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, 1.1925 + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, 1.1926 + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, 1.1927 + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, 1.1928 + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, 1.1929 + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, 1.1930 + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, 1.1931 + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, 1.1932 + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, 1.1933 + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, 1.1934 + 1.1935 + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, 1.1936 + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, 1.1937 + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, 1.1938 + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, 1.1939 + 1.1940 + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, 1.1941 + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, 1.1942 + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, 1.1943 + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, 1.1944 +}; 1.1945 + 1.1946 +static SECItem * 1.1947 +getECParams(const char *curve) 1.1948 +{ 1.1949 + SECItem *ecparams; 1.1950 + SECOidData *oidData = NULL; 1.1951 + SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ 1.1952 + int i, numCurves; 1.1953 + 1.1954 + if (curve != NULL) { 1.1955 + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); 1.1956 + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 1.1957 + i++) { 1.1958 + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) 1.1959 + curveOidTag = nameTagPair[i].curveOidTag; 1.1960 + } 1.1961 + } 1.1962 + 1.1963 + /* Return NULL if curve name is not recognized */ 1.1964 + if ((curveOidTag == SEC_OID_UNKNOWN) || 1.1965 + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { 1.1966 + fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); 1.1967 + return NULL; 1.1968 + } 1.1969 + 1.1970 + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); 1.1971 + 1.1972 + /* 1.1973 + * ecparams->data needs to contain the ASN encoding of an object ID (OID) 1.1974 + * representing the named curve. The actual OID is in 1.1975 + * oidData->oid.data so we simply prepend 0x06 and OID length 1.1976 + */ 1.1977 + ecparams->data[0] = SEC_ASN1_OBJECT_ID; 1.1978 + ecparams->data[1] = oidData->oid.len; 1.1979 + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); 1.1980 + 1.1981 + return ecparams; 1.1982 +} 1.1983 + 1.1984 +/* 1.1985 + * Perform the ECDSA Key Pair Generation Test. 1.1986 + * 1.1987 + * reqfn is the pathname of the REQUEST file. 1.1988 + * 1.1989 + * The output RESPONSE file is written to stdout. 1.1990 + */ 1.1991 +void 1.1992 +ecdsa_keypair_test(char *reqfn) 1.1993 +{ 1.1994 + char buf[256]; /* holds one line from the input REQUEST file 1.1995 + * or to the output RESPONSE file. 1.1996 + * needs to be large enough to hold the longest 1.1997 + * line "Qx = <144 hex digits>\n". 1.1998 + */ 1.1999 + FILE *ecdsareq; /* input stream from the REQUEST file */ 1.2000 + FILE *ecdsaresp; /* output stream to the RESPONSE file */ 1.2001 + char curve[16]; /* "nistxddd" */ 1.2002 + ECParams *ecparams; 1.2003 + int N; 1.2004 + int i; 1.2005 + unsigned int len; 1.2006 + 1.2007 + ecdsareq = fopen(reqfn, "r"); 1.2008 + ecdsaresp = stdout; 1.2009 + strcpy(curve, "nist"); 1.2010 + while (fgets(buf, sizeof buf, ecdsareq) != NULL) { 1.2011 + /* a comment or blank line */ 1.2012 + if (buf[0] == '#' || buf[0] == '\n') { 1.2013 + fputs(buf, ecdsaresp); 1.2014 + continue; 1.2015 + } 1.2016 + /* [X-ddd] */ 1.2017 + if (buf[0] == '[') { 1.2018 + const char *src; 1.2019 + char *dst; 1.2020 + SECItem *encodedparams; 1.2021 + 1.2022 + src = &buf[1]; 1.2023 + dst = &curve[4]; 1.2024 + *dst++ = tolower(*src); 1.2025 + src += 2; /* skip the hyphen */ 1.2026 + *dst++ = *src++; 1.2027 + *dst++ = *src++; 1.2028 + *dst++ = *src++; 1.2029 + *dst = '\0'; 1.2030 + encodedparams = getECParams(curve); 1.2031 + if (encodedparams == NULL) { 1.2032 + goto loser; 1.2033 + } 1.2034 + if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { 1.2035 + goto loser; 1.2036 + } 1.2037 + SECITEM_FreeItem(encodedparams, PR_TRUE); 1.2038 + fputs(buf, ecdsaresp); 1.2039 + continue; 1.2040 + } 1.2041 + /* N = x */ 1.2042 + if (buf[0] == 'N') { 1.2043 + if (sscanf(buf, "N = %d", &N) != 1) { 1.2044 + goto loser; 1.2045 + } 1.2046 + for (i = 0; i < N; i++) { 1.2047 + ECPrivateKey *ecpriv; 1.2048 + 1.2049 + if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) { 1.2050 + goto loser; 1.2051 + } 1.2052 + fputs("d = ", ecdsaresp); 1.2053 + to_hex_str(buf, ecpriv->privateValue.data, 1.2054 + ecpriv->privateValue.len); 1.2055 + fputs(buf, ecdsaresp); 1.2056 + fputc('\n', ecdsaresp); 1.2057 + if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) 1.2058 + != SECSuccess) { 1.2059 + goto loser; 1.2060 + } 1.2061 + len = ecpriv->publicValue.len; 1.2062 + if (len%2 == 0) { 1.2063 + goto loser; 1.2064 + } 1.2065 + len = (len-1)/2; 1.2066 + if (ecpriv->publicValue.data[0] 1.2067 + != EC_POINT_FORM_UNCOMPRESSED) { 1.2068 + goto loser; 1.2069 + } 1.2070 + fputs("Qx = ", ecdsaresp); 1.2071 + to_hex_str(buf, &ecpriv->publicValue.data[1], len); 1.2072 + fputs(buf, ecdsaresp); 1.2073 + fputc('\n', ecdsaresp); 1.2074 + fputs("Qy = ", ecdsaresp); 1.2075 + to_hex_str(buf, &ecpriv->publicValue.data[1+len], len); 1.2076 + fputs(buf, ecdsaresp); 1.2077 + fputc('\n', ecdsaresp); 1.2078 + fputc('\n', ecdsaresp); 1.2079 + PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); 1.2080 + } 1.2081 + PORT_FreeArena(ecparams->arena, PR_FALSE); 1.2082 + continue; 1.2083 + } 1.2084 + } 1.2085 +loser: 1.2086 + fclose(ecdsareq); 1.2087 +} 1.2088 + 1.2089 +/* 1.2090 + * Perform the ECDSA Public Key Validation Test. 1.2091 + * 1.2092 + * reqfn is the pathname of the REQUEST file. 1.2093 + * 1.2094 + * The output RESPONSE file is written to stdout. 1.2095 + */ 1.2096 +void 1.2097 +ecdsa_pkv_test(char *reqfn) 1.2098 +{ 1.2099 + char buf[256]; /* holds one line from the input REQUEST file. 1.2100 + * needs to be large enough to hold the longest 1.2101 + * line "Qx = <144 hex digits>\n". 1.2102 + */ 1.2103 + FILE *ecdsareq; /* input stream from the REQUEST file */ 1.2104 + FILE *ecdsaresp; /* output stream to the RESPONSE file */ 1.2105 + char curve[16]; /* "nistxddd" */ 1.2106 + ECParams *ecparams = NULL; 1.2107 + SECItem pubkey; 1.2108 + unsigned int i; 1.2109 + unsigned int len; 1.2110 + PRBool keyvalid = PR_TRUE; 1.2111 + 1.2112 + ecdsareq = fopen(reqfn, "r"); 1.2113 + ecdsaresp = stdout; 1.2114 + strcpy(curve, "nist"); 1.2115 + pubkey.data = NULL; 1.2116 + while (fgets(buf, sizeof buf, ecdsareq) != NULL) { 1.2117 + /* a comment or blank line */ 1.2118 + if (buf[0] == '#' || buf[0] == '\n') { 1.2119 + fputs(buf, ecdsaresp); 1.2120 + continue; 1.2121 + } 1.2122 + /* [X-ddd] */ 1.2123 + if (buf[0] == '[') { 1.2124 + const char *src; 1.2125 + char *dst; 1.2126 + SECItem *encodedparams; 1.2127 + 1.2128 + src = &buf[1]; 1.2129 + dst = &curve[4]; 1.2130 + *dst++ = tolower(*src); 1.2131 + src += 2; /* skip the hyphen */ 1.2132 + *dst++ = *src++; 1.2133 + *dst++ = *src++; 1.2134 + *dst++ = *src++; 1.2135 + *dst = '\0'; 1.2136 + if (ecparams != NULL) { 1.2137 + PORT_FreeArena(ecparams->arena, PR_FALSE); 1.2138 + ecparams = NULL; 1.2139 + } 1.2140 + encodedparams = getECParams(curve); 1.2141 + if (encodedparams == NULL) { 1.2142 + goto loser; 1.2143 + } 1.2144 + if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { 1.2145 + goto loser; 1.2146 + } 1.2147 + SECITEM_FreeItem(encodedparams, PR_TRUE); 1.2148 + len = (ecparams->fieldID.size + 7) >> 3; 1.2149 + if (pubkey.data != NULL) { 1.2150 + PORT_Free(pubkey.data); 1.2151 + pubkey.data = NULL; 1.2152 + } 1.2153 + SECITEM_AllocItem(NULL, &pubkey, 2*len+1); 1.2154 + if (pubkey.data == NULL) { 1.2155 + goto loser; 1.2156 + } 1.2157 + pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; 1.2158 + fputs(buf, ecdsaresp); 1.2159 + continue; 1.2160 + } 1.2161 + /* Qx = ... */ 1.2162 + if (strncmp(buf, "Qx", 2) == 0) { 1.2163 + fputs(buf, ecdsaresp); 1.2164 + i = 2; 1.2165 + while (isspace(buf[i]) || buf[i] == '=') { 1.2166 + i++; 1.2167 + } 1.2168 + keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]); 1.2169 + continue; 1.2170 + } 1.2171 + /* Qy = ... */ 1.2172 + if (strncmp(buf, "Qy", 2) == 0) { 1.2173 + fputs(buf, ecdsaresp); 1.2174 + if (!keyvalid) { 1.2175 + fputs("Result = F\n", ecdsaresp); 1.2176 + continue; 1.2177 + } 1.2178 + i = 2; 1.2179 + while (isspace(buf[i]) || buf[i] == '=') { 1.2180 + i++; 1.2181 + } 1.2182 + keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]); 1.2183 + if (!keyvalid) { 1.2184 + fputs("Result = F\n", ecdsaresp); 1.2185 + continue; 1.2186 + } 1.2187 + if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) { 1.2188 + fputs("Result = P\n", ecdsaresp); 1.2189 + } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) { 1.2190 + fputs("Result = F\n", ecdsaresp); 1.2191 + } else { 1.2192 + goto loser; 1.2193 + } 1.2194 + continue; 1.2195 + } 1.2196 + } 1.2197 +loser: 1.2198 + if (ecparams != NULL) { 1.2199 + PORT_FreeArena(ecparams->arena, PR_FALSE); 1.2200 + } 1.2201 + if (pubkey.data != NULL) { 1.2202 + PORT_Free(pubkey.data); 1.2203 + } 1.2204 + fclose(ecdsareq); 1.2205 +} 1.2206 + 1.2207 +/* 1.2208 + * Perform the ECDSA Signature Generation Test. 1.2209 + * 1.2210 + * reqfn is the pathname of the REQUEST file. 1.2211 + * 1.2212 + * The output RESPONSE file is written to stdout. 1.2213 + */ 1.2214 +void 1.2215 +ecdsa_siggen_test(char *reqfn) 1.2216 +{ 1.2217 + char buf[1024]; /* holds one line from the input REQUEST file 1.2218 + * or to the output RESPONSE file. 1.2219 + * needs to be large enough to hold the longest 1.2220 + * line "Msg = <256 hex digits>\n". 1.2221 + */ 1.2222 + FILE *ecdsareq; /* input stream from the REQUEST file */ 1.2223 + FILE *ecdsaresp; /* output stream to the RESPONSE file */ 1.2224 + char curve[16]; /* "nistxddd" */ 1.2225 + ECParams *ecparams = NULL; 1.2226 + int i, j; 1.2227 + unsigned int len; 1.2228 + unsigned char msg[512]; /* message to be signed (<= 128 bytes) */ 1.2229 + unsigned int msglen; 1.2230 + unsigned char sha1[20]; /* SHA-1 hash (160 bits) */ 1.2231 + unsigned char sig[2*MAX_ECKEY_LEN]; 1.2232 + SECItem signature, digest; 1.2233 + 1.2234 + ecdsareq = fopen(reqfn, "r"); 1.2235 + ecdsaresp = stdout; 1.2236 + strcpy(curve, "nist"); 1.2237 + while (fgets(buf, sizeof buf, ecdsareq) != NULL) { 1.2238 + /* a comment or blank line */ 1.2239 + if (buf[0] == '#' || buf[0] == '\n') { 1.2240 + fputs(buf, ecdsaresp); 1.2241 + continue; 1.2242 + } 1.2243 + /* [X-ddd] */ 1.2244 + if (buf[0] == '[') { 1.2245 + const char *src; 1.2246 + char *dst; 1.2247 + SECItem *encodedparams; 1.2248 + 1.2249 + src = &buf[1]; 1.2250 + dst = &curve[4]; 1.2251 + *dst++ = tolower(*src); 1.2252 + src += 2; /* skip the hyphen */ 1.2253 + *dst++ = *src++; 1.2254 + *dst++ = *src++; 1.2255 + *dst++ = *src++; 1.2256 + *dst = '\0'; 1.2257 + if (ecparams != NULL) { 1.2258 + PORT_FreeArena(ecparams->arena, PR_FALSE); 1.2259 + ecparams = NULL; 1.2260 + } 1.2261 + encodedparams = getECParams(curve); 1.2262 + if (encodedparams == NULL) { 1.2263 + goto loser; 1.2264 + } 1.2265 + if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { 1.2266 + goto loser; 1.2267 + } 1.2268 + SECITEM_FreeItem(encodedparams, PR_TRUE); 1.2269 + fputs(buf, ecdsaresp); 1.2270 + continue; 1.2271 + } 1.2272 + /* Msg = ... */ 1.2273 + if (strncmp(buf, "Msg", 3) == 0) { 1.2274 + ECPrivateKey *ecpriv; 1.2275 + 1.2276 + i = 3; 1.2277 + while (isspace(buf[i]) || buf[i] == '=') { 1.2278 + i++; 1.2279 + } 1.2280 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.2281 + hex_to_byteval(&buf[i], &msg[j]); 1.2282 + } 1.2283 + msglen = j; 1.2284 + if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) { 1.2285 + goto loser; 1.2286 + } 1.2287 + fputs(buf, ecdsaresp); 1.2288 + 1.2289 + if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) { 1.2290 + goto loser; 1.2291 + } 1.2292 + if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) 1.2293 + != SECSuccess) { 1.2294 + goto loser; 1.2295 + } 1.2296 + len = ecpriv->publicValue.len; 1.2297 + if (len%2 == 0) { 1.2298 + goto loser; 1.2299 + } 1.2300 + len = (len-1)/2; 1.2301 + if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { 1.2302 + goto loser; 1.2303 + } 1.2304 + fputs("Qx = ", ecdsaresp); 1.2305 + to_hex_str(buf, &ecpriv->publicValue.data[1], len); 1.2306 + fputs(buf, ecdsaresp); 1.2307 + fputc('\n', ecdsaresp); 1.2308 + fputs("Qy = ", ecdsaresp); 1.2309 + to_hex_str(buf, &ecpriv->publicValue.data[1+len], len); 1.2310 + fputs(buf, ecdsaresp); 1.2311 + fputc('\n', ecdsaresp); 1.2312 + 1.2313 + digest.type = siBuffer; 1.2314 + digest.data = sha1; 1.2315 + digest.len = sizeof sha1; 1.2316 + signature.type = siBuffer; 1.2317 + signature.data = sig; 1.2318 + signature.len = sizeof sig; 1.2319 + if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) { 1.2320 + goto loser; 1.2321 + } 1.2322 + len = signature.len; 1.2323 + if (len%2 != 0) { 1.2324 + goto loser; 1.2325 + } 1.2326 + len = len/2; 1.2327 + fputs("R = ", ecdsaresp); 1.2328 + to_hex_str(buf, &signature.data[0], len); 1.2329 + fputs(buf, ecdsaresp); 1.2330 + fputc('\n', ecdsaresp); 1.2331 + fputs("S = ", ecdsaresp); 1.2332 + to_hex_str(buf, &signature.data[len], len); 1.2333 + fputs(buf, ecdsaresp); 1.2334 + fputc('\n', ecdsaresp); 1.2335 + 1.2336 + PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); 1.2337 + continue; 1.2338 + } 1.2339 + } 1.2340 +loser: 1.2341 + if (ecparams != NULL) { 1.2342 + PORT_FreeArena(ecparams->arena, PR_FALSE); 1.2343 + } 1.2344 + fclose(ecdsareq); 1.2345 +} 1.2346 + 1.2347 +/* 1.2348 + * Perform the ECDSA Signature Verification Test. 1.2349 + * 1.2350 + * reqfn is the pathname of the REQUEST file. 1.2351 + * 1.2352 + * The output RESPONSE file is written to stdout. 1.2353 + */ 1.2354 +void 1.2355 +ecdsa_sigver_test(char *reqfn) 1.2356 +{ 1.2357 + char buf[1024]; /* holds one line from the input REQUEST file. 1.2358 + * needs to be large enough to hold the longest 1.2359 + * line "Msg = <256 hex digits>\n". 1.2360 + */ 1.2361 + FILE *ecdsareq; /* input stream from the REQUEST file */ 1.2362 + FILE *ecdsaresp; /* output stream to the RESPONSE file */ 1.2363 + char curve[16]; /* "nistxddd" */ 1.2364 + ECPublicKey ecpub; 1.2365 + unsigned int i, j; 1.2366 + unsigned int flen; /* length in bytes of the field size */ 1.2367 + unsigned int olen; /* length in bytes of the base point order */ 1.2368 + unsigned char msg[512]; /* message that was signed (<= 128 bytes) */ 1.2369 + unsigned int msglen; 1.2370 + unsigned char sha1[20]; /* SHA-1 hash (160 bits) */ 1.2371 + unsigned char sig[2*MAX_ECKEY_LEN]; 1.2372 + SECItem signature, digest; 1.2373 + PRBool keyvalid = PR_TRUE; 1.2374 + PRBool sigvalid = PR_TRUE; 1.2375 + 1.2376 + ecdsareq = fopen(reqfn, "r"); 1.2377 + ecdsaresp = stdout; 1.2378 + ecpub.ecParams.arena = NULL; 1.2379 + strcpy(curve, "nist"); 1.2380 + while (fgets(buf, sizeof buf, ecdsareq) != NULL) { 1.2381 + /* a comment or blank line */ 1.2382 + if (buf[0] == '#' || buf[0] == '\n') { 1.2383 + fputs(buf, ecdsaresp); 1.2384 + continue; 1.2385 + } 1.2386 + /* [X-ddd] */ 1.2387 + if (buf[0] == '[') { 1.2388 + const char *src; 1.2389 + char *dst; 1.2390 + SECItem *encodedparams; 1.2391 + ECParams *ecparams; 1.2392 + 1.2393 + src = &buf[1]; 1.2394 + dst = &curve[4]; 1.2395 + *dst++ = tolower(*src); 1.2396 + src += 2; /* skip the hyphen */ 1.2397 + *dst++ = *src++; 1.2398 + *dst++ = *src++; 1.2399 + *dst++ = *src++; 1.2400 + *dst = '\0'; 1.2401 + encodedparams = getECParams(curve); 1.2402 + if (encodedparams == NULL) { 1.2403 + goto loser; 1.2404 + } 1.2405 + if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { 1.2406 + goto loser; 1.2407 + } 1.2408 + SECITEM_FreeItem(encodedparams, PR_TRUE); 1.2409 + if (ecpub.ecParams.arena != NULL) { 1.2410 + PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE); 1.2411 + } 1.2412 + ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.2413 + if (ecpub.ecParams.arena == NULL) { 1.2414 + goto loser; 1.2415 + } 1.2416 + if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams) 1.2417 + != SECSuccess) { 1.2418 + goto loser; 1.2419 + } 1.2420 + PORT_FreeArena(ecparams->arena, PR_FALSE); 1.2421 + flen = (ecpub.ecParams.fieldID.size + 7) >> 3; 1.2422 + olen = ecpub.ecParams.order.len; 1.2423 + if (2*olen > sizeof sig) { 1.2424 + goto loser; 1.2425 + } 1.2426 + ecpub.publicValue.type = siBuffer; 1.2427 + ecpub.publicValue.data = NULL; 1.2428 + ecpub.publicValue.len = 0; 1.2429 + SECITEM_AllocItem(ecpub.ecParams.arena, 1.2430 + &ecpub.publicValue, 2*flen+1); 1.2431 + if (ecpub.publicValue.data == NULL) { 1.2432 + goto loser; 1.2433 + } 1.2434 + ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED; 1.2435 + fputs(buf, ecdsaresp); 1.2436 + continue; 1.2437 + } 1.2438 + /* Msg = ... */ 1.2439 + if (strncmp(buf, "Msg", 3) == 0) { 1.2440 + i = 3; 1.2441 + while (isspace(buf[i]) || buf[i] == '=') { 1.2442 + i++; 1.2443 + } 1.2444 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.2445 + hex_to_byteval(&buf[i], &msg[j]); 1.2446 + } 1.2447 + msglen = j; 1.2448 + if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) { 1.2449 + goto loser; 1.2450 + } 1.2451 + fputs(buf, ecdsaresp); 1.2452 + 1.2453 + digest.type = siBuffer; 1.2454 + digest.data = sha1; 1.2455 + digest.len = sizeof sha1; 1.2456 + 1.2457 + continue; 1.2458 + } 1.2459 + /* Qx = ... */ 1.2460 + if (strncmp(buf, "Qx", 2) == 0) { 1.2461 + fputs(buf, ecdsaresp); 1.2462 + i = 2; 1.2463 + while (isspace(buf[i]) || buf[i] == '=') { 1.2464 + i++; 1.2465 + } 1.2466 + keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen, 1.2467 + &buf[i]); 1.2468 + continue; 1.2469 + } 1.2470 + /* Qy = ... */ 1.2471 + if (strncmp(buf, "Qy", 2) == 0) { 1.2472 + fputs(buf, ecdsaresp); 1.2473 + if (!keyvalid) { 1.2474 + continue; 1.2475 + } 1.2476 + i = 2; 1.2477 + while (isspace(buf[i]) || buf[i] == '=') { 1.2478 + i++; 1.2479 + } 1.2480 + keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen, 1.2481 + &buf[i]); 1.2482 + if (!keyvalid) { 1.2483 + continue; 1.2484 + } 1.2485 + if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue) 1.2486 + != SECSuccess) { 1.2487 + if (PORT_GetError() == SEC_ERROR_BAD_KEY) { 1.2488 + keyvalid = PR_FALSE; 1.2489 + } else { 1.2490 + goto loser; 1.2491 + } 1.2492 + } 1.2493 + continue; 1.2494 + } 1.2495 + /* R = ... */ 1.2496 + if (buf[0] == 'R') { 1.2497 + fputs(buf, ecdsaresp); 1.2498 + i = 1; 1.2499 + while (isspace(buf[i]) || buf[i] == '=') { 1.2500 + i++; 1.2501 + } 1.2502 + sigvalid = from_hex_str(sig, olen, &buf[i]); 1.2503 + continue; 1.2504 + } 1.2505 + /* S = ... */ 1.2506 + if (buf[0] == 'S') { 1.2507 + fputs(buf, ecdsaresp); 1.2508 + i = 1; 1.2509 + while (isspace(buf[i]) || buf[i] == '=') { 1.2510 + i++; 1.2511 + } 1.2512 + if (sigvalid) { 1.2513 + sigvalid = from_hex_str(&sig[olen], olen, &buf[i]); 1.2514 + } 1.2515 + signature.type = siBuffer; 1.2516 + signature.data = sig; 1.2517 + signature.len = 2*olen; 1.2518 + 1.2519 + if (!keyvalid || !sigvalid) { 1.2520 + fputs("Result = F\n", ecdsaresp); 1.2521 + } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest) 1.2522 + == SECSuccess) { 1.2523 + fputs("Result = P\n", ecdsaresp); 1.2524 + } else { 1.2525 + fputs("Result = F\n", ecdsaresp); 1.2526 + } 1.2527 + continue; 1.2528 + } 1.2529 + } 1.2530 +loser: 1.2531 + if (ecpub.ecParams.arena != NULL) { 1.2532 + PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE); 1.2533 + } 1.2534 + fclose(ecdsareq); 1.2535 +} 1.2536 +#endif /* NSS_DISABLE_ECC */ 1.2537 + 1.2538 + 1.2539 +/* 1.2540 + * Read a value from the test and allocate the result. 1.2541 + */ 1.2542 +static unsigned char * 1.2543 +alloc_value(char *buf, int *len) 1.2544 +{ 1.2545 + unsigned char * value; 1.2546 + int i, count; 1.2547 + 1.2548 + if (strncmp(buf, "<None>", 6) == 0) { 1.2549 + *len = 0; 1.2550 + return NULL; 1.2551 + } 1.2552 + 1.2553 + /* find the length of the number */ 1.2554 + for (count = 0; isxdigit(buf[count]); count++); 1.2555 + *len = count/2; 1.2556 + 1.2557 + if (*len == 0) { 1.2558 + return NULL; 1.2559 + } 1.2560 + 1.2561 + value = PORT_Alloc(*len); 1.2562 + if (!value) { 1.2563 + *len = 0; 1.2564 + return NULL; 1.2565 + } 1.2566 + 1.2567 + for (i=0; i<*len; buf+=2 , i++) { 1.2568 + hex_to_byteval(buf, &value[i]); 1.2569 + } 1.2570 + 1.2571 + 1.2572 + return value; 1.2573 +} 1.2574 + 1.2575 +PRBool 1.2576 +isblankline(char *b) 1.2577 +{ 1.2578 + while (isspace(*b)) b++; 1.2579 + if ((*b == '\n') || (*b == 0)) { 1.2580 + return PR_TRUE; 1.2581 + } 1.2582 + return PR_FALSE; 1.2583 +} 1.2584 + 1.2585 +static int debug = 0; 1.2586 + 1.2587 +/* 1.2588 + * Perform the Hash_DRBG (CAVS) for the RNG algorithm 1.2589 + * 1.2590 + * reqfn is the pathname of the REQUEST file. 1.2591 + * 1.2592 + * The output RESPONSE file is written to stdout. 1.2593 + */ 1.2594 +void 1.2595 +drbg(char *reqfn) 1.2596 +{ 1.2597 + char buf[2000]; /* test case has some very long lines, returned bits 1.2598 + * as high as 800 bytes (6400 bits). That 1600 byte 1.2599 + * plus a tag */ 1.2600 + char buf2[2000]; 1.2601 + FILE *rngreq; /* input stream from the REQUEST file */ 1.2602 + FILE *rngresp; /* output stream to the RESPONSE file */ 1.2603 + 1.2604 + unsigned int i, j; 1.2605 + PRBool predictionResistance = PR_FALSE; 1.2606 + unsigned char *nonce = NULL; 1.2607 + int nonceLen = 0; 1.2608 + unsigned char *personalizationString = NULL; 1.2609 + int personalizationStringLen = 0; 1.2610 + unsigned char *additionalInput = NULL; 1.2611 + int additionalInputLen = 0; 1.2612 + unsigned char *entropyInput = NULL; 1.2613 + int entropyInputLen = 0; 1.2614 + unsigned char predictedreturn_bytes[SHA256_LENGTH]; 1.2615 + unsigned char return_bytes[SHA256_LENGTH]; 1.2616 + int return_bytes_len = SHA256_LENGTH; 1.2617 + enum { NONE, INSTANTIATE, GENERATE, RESEED, RESULT } command = 1.2618 + NONE; 1.2619 + PRBool genResult = PR_FALSE; 1.2620 + SECStatus rv; 1.2621 + 1.2622 + rngreq = fopen(reqfn, "r"); 1.2623 + rngresp = stdout; 1.2624 + while (fgets(buf, sizeof buf, rngreq) != NULL) { 1.2625 + switch (command) { 1.2626 + case INSTANTIATE: 1.2627 + if (debug) { 1.2628 + fputs("# PRNGTEST_Instantiate(",rngresp); 1.2629 + to_hex_str(buf2,entropyInput, entropyInputLen); 1.2630 + fputs(buf2,rngresp); 1.2631 + fprintf(rngresp,",%d,",entropyInputLen); 1.2632 + to_hex_str(buf2,nonce, nonceLen); 1.2633 + fputs(buf2,rngresp); 1.2634 + fprintf(rngresp,",%d,",nonceLen); 1.2635 + to_hex_str(buf2,personalizationString, 1.2636 + personalizationStringLen); 1.2637 + fputs(buf2,rngresp); 1.2638 + fprintf(rngresp,",%d)\n", personalizationStringLen); 1.2639 + } 1.2640 + rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen, 1.2641 + nonce, nonceLen, 1.2642 + personalizationString, 1.2643 + personalizationStringLen); 1.2644 + if (rv != SECSuccess) { 1.2645 + goto loser; 1.2646 + } 1.2647 + break; 1.2648 + 1.2649 + case GENERATE: 1.2650 + case RESULT: 1.2651 + memset(return_bytes, 0, return_bytes_len); 1.2652 + if (debug) { 1.2653 + fputs("# PRNGTEST_Generate(returnbytes",rngresp); 1.2654 + fprintf(rngresp,",%d,", return_bytes_len); 1.2655 + to_hex_str(buf2,additionalInput, additionalInputLen); 1.2656 + fputs(buf2,rngresp); 1.2657 + fprintf(rngresp,",%d)\n",additionalInputLen); 1.2658 + } 1.2659 + rv = PRNGTEST_Generate((PRUint8 *) return_bytes, 1.2660 + return_bytes_len, 1.2661 + (PRUint8 *) additionalInput, 1.2662 + additionalInputLen); 1.2663 + if (rv != SECSuccess) { 1.2664 + goto loser; 1.2665 + } 1.2666 + 1.2667 + if (command == RESULT) { 1.2668 + fputs("ReturnedBits = ", rngresp); 1.2669 + to_hex_str(buf2, return_bytes, return_bytes_len); 1.2670 + fputs(buf2, rngresp); 1.2671 + fputc('\n', rngresp); 1.2672 + if (debug) { 1.2673 + fputs("# PRNGTEST_Uninstantiate()\n",rngresp); 1.2674 + } 1.2675 + rv = PRNGTEST_Uninstantiate(); 1.2676 + if (rv != SECSuccess) { 1.2677 + goto loser; 1.2678 + } 1.2679 + } else if (debug) { 1.2680 + fputs("#ReturnedBits = ", rngresp); 1.2681 + to_hex_str(buf2, return_bytes, return_bytes_len); 1.2682 + fputs(buf2, rngresp); 1.2683 + fputc('\n', rngresp); 1.2684 + } 1.2685 + 1.2686 + memset(additionalInput, 0, additionalInputLen); 1.2687 + break; 1.2688 + 1.2689 + case RESEED: 1.2690 + if (entropyInput || additionalInput) { 1.2691 + if (debug) { 1.2692 + fputs("# PRNGTEST_Reseed(",rngresp); 1.2693 + fprintf(rngresp,",%d,", return_bytes_len); 1.2694 + to_hex_str(buf2,entropyInput, entropyInputLen); 1.2695 + fputs(buf2,rngresp); 1.2696 + fprintf(rngresp,",%d,", entropyInputLen); 1.2697 + to_hex_str(buf2,additionalInput, additionalInputLen); 1.2698 + fputs(buf2,rngresp); 1.2699 + fprintf(rngresp,",%d)\n",additionalInputLen); 1.2700 + } 1.2701 + rv = PRNGTEST_Reseed(entropyInput, entropyInputLen, 1.2702 + additionalInput, additionalInputLen); 1.2703 + if (rv != SECSuccess) { 1.2704 + goto loser; 1.2705 + } 1.2706 + } 1.2707 + memset(entropyInput, 0, entropyInputLen); 1.2708 + memset(additionalInput, 0, additionalInputLen); 1.2709 + break; 1.2710 + case NONE: 1.2711 + break; 1.2712 + 1.2713 + } 1.2714 + command = NONE; 1.2715 + 1.2716 + /* a comment or blank line */ 1.2717 + if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r' ) { 1.2718 + fputs(buf, rngresp); 1.2719 + continue; 1.2720 + } 1.2721 + 1.2722 + /* [Hash - SHA256] */ 1.2723 + if (strncmp(buf, "[SHA-256]", 9) == 0) { 1.2724 + fputs(buf, rngresp); 1.2725 + continue; 1.2726 + } 1.2727 + 1.2728 + if (strncmp(buf, "[PredictionResistance", 21) == 0) { 1.2729 + i = 21; 1.2730 + while (isspace(buf[i]) || buf[i] == '=') { 1.2731 + i++; 1.2732 + } 1.2733 + if (strncmp(buf, "False", 5) == 0) { 1.2734 + predictionResistance = PR_FALSE; 1.2735 + } else { 1.2736 + predictionResistance = PR_TRUE; 1.2737 + } 1.2738 + 1.2739 + fputs(buf, rngresp); 1.2740 + continue; 1.2741 + } 1.2742 + 1.2743 + if (strncmp(buf, "[EntropyInputLen", 16) == 0) { 1.2744 + if (entropyInput) { 1.2745 + PORT_ZFree(entropyInput, entropyInputLen); 1.2746 + entropyInput = NULL; 1.2747 + entropyInputLen = 0; 1.2748 + } 1.2749 + if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) { 1.2750 + goto loser; 1.2751 + } 1.2752 + entropyInputLen = entropyInputLen/8; 1.2753 + if (entropyInputLen > 0) { 1.2754 + entropyInput = PORT_Alloc(entropyInputLen); 1.2755 + } 1.2756 + fputs(buf, rngresp); 1.2757 + continue; 1.2758 + } 1.2759 + 1.2760 + if (strncmp(buf, "[NonceLen", 9) == 0) { 1.2761 + if (nonce) { 1.2762 + PORT_ZFree(nonce, nonceLen); 1.2763 + nonce = NULL; 1.2764 + nonceLen = 0; 1.2765 + } 1.2766 + 1.2767 + if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) { 1.2768 + goto loser; 1.2769 + } 1.2770 + nonceLen = nonceLen/8; 1.2771 + if (nonceLen > 0) { 1.2772 + nonce = PORT_Alloc(nonceLen); 1.2773 + } 1.2774 + fputs(buf, rngresp); 1.2775 + continue; 1.2776 + } 1.2777 + 1.2778 + if (strncmp(buf, "[PersonalizationStringLen", 16) == 0) { 1.2779 + if (personalizationString) { 1.2780 + PORT_ZFree(personalizationString, personalizationStringLen); 1.2781 + personalizationString = NULL; 1.2782 + personalizationStringLen = 0; 1.2783 + } 1.2784 + 1.2785 + if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) { 1.2786 + goto loser; 1.2787 + } 1.2788 + personalizationStringLen = personalizationStringLen / 8; 1.2789 + if (personalizationStringLen > 0) { 1.2790 + personalizationString = PORT_Alloc(personalizationStringLen); 1.2791 + } 1.2792 + fputs(buf, rngresp); 1.2793 + 1.2794 + continue; 1.2795 + } 1.2796 + 1.2797 + if (strncmp(buf, "[AdditionalInputLen", 16) == 0) { 1.2798 + if (additionalInput) { 1.2799 + PORT_ZFree(additionalInput, additionalInputLen); 1.2800 + additionalInput = NULL; 1.2801 + additionalInputLen = 0; 1.2802 + } 1.2803 + 1.2804 + if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) { 1.2805 + goto loser; 1.2806 + } 1.2807 + additionalInputLen = additionalInputLen/8; 1.2808 + if (additionalInputLen > 0) { 1.2809 + additionalInput = PORT_Alloc(additionalInputLen); 1.2810 + } 1.2811 + fputs(buf, rngresp); 1.2812 + continue; 1.2813 + } 1.2814 + 1.2815 + if (strncmp(buf, "COUNT", 5) == 0) { 1.2816 + /* zeroize the variables for the test with this data set */ 1.2817 + if (entropyInput) { 1.2818 + memset(entropyInput, 0, entropyInputLen); 1.2819 + } 1.2820 + if (nonce) { 1.2821 + memset(nonce, 0, nonceLen); 1.2822 + } 1.2823 + if (personalizationString) { 1.2824 + memset(personalizationString, 0, personalizationStringLen); 1.2825 + } 1.2826 + if (additionalInput) { 1.2827 + memset(additionalInput, 0, additionalInputLen); 1.2828 + } 1.2829 + genResult = PR_FALSE; 1.2830 + 1.2831 + fputs(buf, rngresp); 1.2832 + continue; 1.2833 + } 1.2834 + 1.2835 + /* EntropyInputReseed = ... */ 1.2836 + if (strncmp(buf, "EntropyInputReseed", 18) == 0) { 1.2837 + if (entropyInput) { 1.2838 + memset(entropyInput, 0, entropyInputLen); 1.2839 + i = 18; 1.2840 + while (isspace(buf[i]) || buf[i] == '=') { 1.2841 + i++; 1.2842 + } 1.2843 + 1.2844 + for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<entropyInputLen*/ 1.2845 + hex_to_byteval(&buf[i], &entropyInput[j]); 1.2846 + } 1.2847 + } 1.2848 + fputs(buf, rngresp); 1.2849 + continue; 1.2850 + } 1.2851 + 1.2852 + /* AttionalInputReseed = ... */ 1.2853 + if (strncmp(buf, "AdditionalInputReseed", 21) == 0) { 1.2854 + if (additionalInput) { 1.2855 + memset(additionalInput, 0, additionalInputLen); 1.2856 + i = 21; 1.2857 + while (isspace(buf[i]) || buf[i] == '=') { 1.2858 + i++; 1.2859 + } 1.2860 + for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/ 1.2861 + hex_to_byteval(&buf[i], &additionalInput[j]); 1.2862 + } 1.2863 + } 1.2864 + command = RESEED; 1.2865 + fputs(buf, rngresp); 1.2866 + continue; 1.2867 + } 1.2868 + 1.2869 + /* Entropy input = ... */ 1.2870 + if (strncmp(buf, "EntropyInput", 12) == 0) { 1.2871 + i = 12; 1.2872 + while (isspace(buf[i]) || buf[i] == '=') { 1.2873 + i++; 1.2874 + } 1.2875 + for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<entropyInputLen*/ 1.2876 + hex_to_byteval(&buf[i], &entropyInput[j]); 1.2877 + } 1.2878 + fputs(buf, rngresp); 1.2879 + continue; 1.2880 + } 1.2881 + 1.2882 + /* nouce = ... */ 1.2883 + if (strncmp(buf, "Nonce", 5) == 0) { 1.2884 + i = 5; 1.2885 + while (isspace(buf[i]) || buf[i] == '=') { 1.2886 + i++; 1.2887 + } 1.2888 + for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<nonceLen*/ 1.2889 + hex_to_byteval(&buf[i], &nonce[j]); 1.2890 + } 1.2891 + fputs(buf, rngresp); 1.2892 + continue; 1.2893 + } 1.2894 + 1.2895 + /* Personalization string = ... */ 1.2896 + if (strncmp(buf, "PersonalizationString", 21) == 0) { 1.2897 + if (personalizationString) { 1.2898 + i = 21; 1.2899 + while (isspace(buf[i]) || buf[i] == '=') { 1.2900 + i++; 1.2901 + } 1.2902 + for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<personalizationStringLen*/ 1.2903 + hex_to_byteval(&buf[i], &personalizationString[j]); 1.2904 + } 1.2905 + } 1.2906 + fputs(buf, rngresp); 1.2907 + command = INSTANTIATE; 1.2908 + continue; 1.2909 + } 1.2910 + 1.2911 + /* Additional input = ... */ 1.2912 + if (strncmp(buf, "AdditionalInput", 15) == 0) { 1.2913 + if (additionalInput) { 1.2914 + i = 15; 1.2915 + while (isspace(buf[i]) || buf[i] == '=') { 1.2916 + i++; 1.2917 + } 1.2918 + for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/ 1.2919 + hex_to_byteval(&buf[i], &additionalInput[j]); 1.2920 + } 1.2921 + } 1.2922 + if (genResult) { 1.2923 + command = RESULT; 1.2924 + } else { 1.2925 + command = GENERATE; 1.2926 + genResult = PR_TRUE; /* next time generate result */ 1.2927 + } 1.2928 + fputs(buf, rngresp); 1.2929 + continue; 1.2930 + } 1.2931 + 1.2932 + /* Returned bits = ... */ 1.2933 + if (strncmp(buf, "ReturnedBits", 12) == 0) { 1.2934 + i = 12; 1.2935 + while (isspace(buf[i]) || buf[i] == '=') { 1.2936 + i++; 1.2937 + } 1.2938 + for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/ 1.2939 + hex_to_byteval(&buf[i], &predictedreturn_bytes[j]); 1.2940 + } 1.2941 + 1.2942 + if (memcmp(return_bytes, 1.2943 + predictedreturn_bytes, return_bytes_len) != 0) { 1.2944 + if (debug) { 1.2945 + fprintf(rngresp, "# Generate failed:\n"); 1.2946 + fputs( "# predicted=", rngresp); 1.2947 + to_hex_str(buf, predictedreturn_bytes, 1.2948 + return_bytes_len); 1.2949 + fputs(buf, rngresp); 1.2950 + fputs("\n# actual = ", rngresp); 1.2951 + fputs(buf2, rngresp); 1.2952 + fputc('\n', rngresp); 1.2953 + 1.2954 + } else { 1.2955 + fprintf(stderr, "Generate failed:\n"); 1.2956 + fputs( " predicted=", stderr); 1.2957 + to_hex_str(buf, predictedreturn_bytes, 1.2958 + return_bytes_len); 1.2959 + fputs(buf, stderr); 1.2960 + fputs("\n actual = ", stderr); 1.2961 + fputs(buf2, stderr); 1.2962 + fputc('\n', stderr); 1.2963 + } 1.2964 + } 1.2965 + memset(predictedreturn_bytes, 0 , sizeof predictedreturn_bytes); 1.2966 + 1.2967 + continue; 1.2968 + } 1.2969 + } 1.2970 +loser: 1.2971 + fclose(rngreq); 1.2972 +} 1.2973 + 1.2974 +/* 1.2975 + * Perform the RNG Variable Seed Test (VST) for the RNG algorithm 1.2976 + * "DSA - Generation of X", used both as specified and as a generic 1.2977 + * purpose RNG. The presence of "Q = ..." in the REQUEST file 1.2978 + * indicates we are using the algorithm as specified. 1.2979 + * 1.2980 + * reqfn is the pathname of the REQUEST file. 1.2981 + * 1.2982 + * The output RESPONSE file is written to stdout. 1.2983 + */ 1.2984 +void 1.2985 +rng_vst(char *reqfn) 1.2986 +{ 1.2987 + char buf[256]; /* holds one line from the input REQUEST file. 1.2988 + * needs to be large enough to hold the longest 1.2989 + * line "XSeed = <128 hex digits>\n". 1.2990 + */ 1.2991 + FILE *rngreq; /* input stream from the REQUEST file */ 1.2992 + FILE *rngresp; /* output stream to the RESPONSE file */ 1.2993 + unsigned int i, j; 1.2994 + unsigned char Q[DSA1_SUBPRIME_LEN]; 1.2995 + PRBool hasQ = PR_FALSE; 1.2996 + unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */ 1.2997 + unsigned char XKey[512/8]; 1.2998 + unsigned char XSeed[512/8]; 1.2999 + unsigned char GENX[DSA1_SIGNATURE_LEN]; 1.3000 + unsigned char DSAX[DSA1_SUBPRIME_LEN]; 1.3001 + SECStatus rv; 1.3002 + 1.3003 + rngreq = fopen(reqfn, "r"); 1.3004 + rngresp = stdout; 1.3005 + while (fgets(buf, sizeof buf, rngreq) != NULL) { 1.3006 + /* a comment or blank line */ 1.3007 + if (buf[0] == '#' || buf[0] == '\n') { 1.3008 + fputs(buf, rngresp); 1.3009 + continue; 1.3010 + } 1.3011 + /* [Xchange - SHA1] */ 1.3012 + if (buf[0] == '[') { 1.3013 + fputs(buf, rngresp); 1.3014 + continue; 1.3015 + } 1.3016 + /* Q = ... */ 1.3017 + if (buf[0] == 'Q') { 1.3018 + i = 1; 1.3019 + while (isspace(buf[i]) || buf[i] == '=') { 1.3020 + i++; 1.3021 + } 1.3022 + for (j=0; j<sizeof Q; i+=2,j++) { 1.3023 + hex_to_byteval(&buf[i], &Q[j]); 1.3024 + } 1.3025 + fputs(buf, rngresp); 1.3026 + hasQ = PR_TRUE; 1.3027 + continue; 1.3028 + } 1.3029 + /* "COUNT = x" begins a new data set */ 1.3030 + if (strncmp(buf, "COUNT", 5) == 0) { 1.3031 + /* zeroize the variables for the test with this data set */ 1.3032 + b = 0; 1.3033 + memset(XKey, 0, sizeof XKey); 1.3034 + memset(XSeed, 0, sizeof XSeed); 1.3035 + fputs(buf, rngresp); 1.3036 + continue; 1.3037 + } 1.3038 + /* b = ... */ 1.3039 + if (buf[0] == 'b') { 1.3040 + i = 1; 1.3041 + while (isspace(buf[i]) || buf[i] == '=') { 1.3042 + i++; 1.3043 + } 1.3044 + b = atoi(&buf[i]); 1.3045 + if (b < 160 || b > 512 || b%8 != 0) { 1.3046 + goto loser; 1.3047 + } 1.3048 + fputs(buf, rngresp); 1.3049 + continue; 1.3050 + } 1.3051 + /* XKey = ... */ 1.3052 + if (strncmp(buf, "XKey", 4) == 0) { 1.3053 + i = 4; 1.3054 + while (isspace(buf[i]) || buf[i] == '=') { 1.3055 + i++; 1.3056 + } 1.3057 + for (j=0; j<b/8; i+=2,j++) { 1.3058 + hex_to_byteval(&buf[i], &XKey[j]); 1.3059 + } 1.3060 + fputs(buf, rngresp); 1.3061 + continue; 1.3062 + } 1.3063 + /* XSeed = ... */ 1.3064 + if (strncmp(buf, "XSeed", 5) == 0) { 1.3065 + i = 5; 1.3066 + while (isspace(buf[i]) || buf[i] == '=') { 1.3067 + i++; 1.3068 + } 1.3069 + for (j=0; j<b/8; i+=2,j++) { 1.3070 + hex_to_byteval(&buf[i], &XSeed[j]); 1.3071 + } 1.3072 + fputs(buf, rngresp); 1.3073 + 1.3074 + rv = FIPS186Change_GenerateX(XKey, XSeed, GENX); 1.3075 + if (rv != SECSuccess) { 1.3076 + goto loser; 1.3077 + } 1.3078 + fputs("X = ", rngresp); 1.3079 + if (hasQ) { 1.3080 + rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX); 1.3081 + if (rv != SECSuccess) { 1.3082 + goto loser; 1.3083 + } 1.3084 + to_hex_str(buf, DSAX, sizeof DSAX); 1.3085 + } else { 1.3086 + to_hex_str(buf, GENX, sizeof GENX); 1.3087 + } 1.3088 + fputs(buf, rngresp); 1.3089 + fputc('\n', rngresp); 1.3090 + continue; 1.3091 + } 1.3092 + } 1.3093 +loser: 1.3094 + fclose(rngreq); 1.3095 +} 1.3096 + 1.3097 +/* 1.3098 + * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm 1.3099 + * "DSA - Generation of X", used both as specified and as a generic 1.3100 + * purpose RNG. The presence of "Q = ..." in the REQUEST file 1.3101 + * indicates we are using the algorithm as specified. 1.3102 + * 1.3103 + * reqfn is the pathname of the REQUEST file. 1.3104 + * 1.3105 + * The output RESPONSE file is written to stdout. 1.3106 + */ 1.3107 +void 1.3108 +rng_mct(char *reqfn) 1.3109 +{ 1.3110 + char buf[256]; /* holds one line from the input REQUEST file. 1.3111 + * needs to be large enough to hold the longest 1.3112 + * line "XSeed = <128 hex digits>\n". 1.3113 + */ 1.3114 + FILE *rngreq; /* input stream from the REQUEST file */ 1.3115 + FILE *rngresp; /* output stream to the RESPONSE file */ 1.3116 + unsigned int i, j; 1.3117 + unsigned char Q[DSA1_SUBPRIME_LEN]; 1.3118 + PRBool hasQ = PR_FALSE; 1.3119 + unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */ 1.3120 + unsigned char XKey[512/8]; 1.3121 + unsigned char XSeed[512/8]; 1.3122 + unsigned char GENX[2*SHA1_LENGTH]; 1.3123 + unsigned char DSAX[DSA1_SUBPRIME_LEN]; 1.3124 + SECStatus rv; 1.3125 + 1.3126 + rngreq = fopen(reqfn, "r"); 1.3127 + rngresp = stdout; 1.3128 + while (fgets(buf, sizeof buf, rngreq) != NULL) { 1.3129 + /* a comment or blank line */ 1.3130 + if (buf[0] == '#' || buf[0] == '\n') { 1.3131 + fputs(buf, rngresp); 1.3132 + continue; 1.3133 + } 1.3134 + /* [Xchange - SHA1] */ 1.3135 + if (buf[0] == '[') { 1.3136 + fputs(buf, rngresp); 1.3137 + continue; 1.3138 + } 1.3139 + /* Q = ... */ 1.3140 + if (buf[0] == 'Q') { 1.3141 + i = 1; 1.3142 + while (isspace(buf[i]) || buf[i] == '=') { 1.3143 + i++; 1.3144 + } 1.3145 + for (j=0; j<sizeof Q; i+=2,j++) { 1.3146 + hex_to_byteval(&buf[i], &Q[j]); 1.3147 + } 1.3148 + fputs(buf, rngresp); 1.3149 + hasQ = PR_TRUE; 1.3150 + continue; 1.3151 + } 1.3152 + /* "COUNT = x" begins a new data set */ 1.3153 + if (strncmp(buf, "COUNT", 5) == 0) { 1.3154 + /* zeroize the variables for the test with this data set */ 1.3155 + b = 0; 1.3156 + memset(XKey, 0, sizeof XKey); 1.3157 + memset(XSeed, 0, sizeof XSeed); 1.3158 + fputs(buf, rngresp); 1.3159 + continue; 1.3160 + } 1.3161 + /* b = ... */ 1.3162 + if (buf[0] == 'b') { 1.3163 + i = 1; 1.3164 + while (isspace(buf[i]) || buf[i] == '=') { 1.3165 + i++; 1.3166 + } 1.3167 + b = atoi(&buf[i]); 1.3168 + if (b < 160 || b > 512 || b%8 != 0) { 1.3169 + goto loser; 1.3170 + } 1.3171 + fputs(buf, rngresp); 1.3172 + continue; 1.3173 + } 1.3174 + /* XKey = ... */ 1.3175 + if (strncmp(buf, "XKey", 4) == 0) { 1.3176 + i = 4; 1.3177 + while (isspace(buf[i]) || buf[i] == '=') { 1.3178 + i++; 1.3179 + } 1.3180 + for (j=0; j<b/8; i+=2,j++) { 1.3181 + hex_to_byteval(&buf[i], &XKey[j]); 1.3182 + } 1.3183 + fputs(buf, rngresp); 1.3184 + continue; 1.3185 + } 1.3186 + /* XSeed = ... */ 1.3187 + if (strncmp(buf, "XSeed", 5) == 0) { 1.3188 + unsigned int k; 1.3189 + i = 5; 1.3190 + while (isspace(buf[i]) || buf[i] == '=') { 1.3191 + i++; 1.3192 + } 1.3193 + for (j=0; j<b/8; i+=2,j++) { 1.3194 + hex_to_byteval(&buf[i], &XSeed[j]); 1.3195 + } 1.3196 + fputs(buf, rngresp); 1.3197 + 1.3198 + for (k = 0; k < 10000; k++) { 1.3199 + rv = FIPS186Change_GenerateX(XKey, XSeed, GENX); 1.3200 + if (rv != SECSuccess) { 1.3201 + goto loser; 1.3202 + } 1.3203 + } 1.3204 + fputs("X = ", rngresp); 1.3205 + if (hasQ) { 1.3206 + rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX); 1.3207 + if (rv != SECSuccess) { 1.3208 + goto loser; 1.3209 + } 1.3210 + to_hex_str(buf, DSAX, sizeof DSAX); 1.3211 + } else { 1.3212 + to_hex_str(buf, GENX, sizeof GENX); 1.3213 + } 1.3214 + fputs(buf, rngresp); 1.3215 + fputc('\n', rngresp); 1.3216 + continue; 1.3217 + } 1.3218 + } 1.3219 +loser: 1.3220 + fclose(rngreq); 1.3221 +} 1.3222 + 1.3223 +/* 1.3224 + * HASH_ functions are available to full NSS apps and internally inside 1.3225 + * freebl, but not exported to users of freebl. Create short stubs to 1.3226 + * replace the functionality for fipstest. 1.3227 + */ 1.3228 +SECStatus 1.3229 +fips_hashBuf(HASH_HashType type, unsigned char *hashBuf, 1.3230 + unsigned char *msg, int len) 1.3231 +{ 1.3232 + SECStatus rv = SECFailure; 1.3233 + 1.3234 + switch (type) { 1.3235 + case HASH_AlgSHA1: 1.3236 + rv = SHA1_HashBuf(hashBuf, msg, len); 1.3237 + break; 1.3238 + case HASH_AlgSHA224: 1.3239 + rv = SHA224_HashBuf(hashBuf, msg, len); 1.3240 + break; 1.3241 + case HASH_AlgSHA256: 1.3242 + rv = SHA256_HashBuf(hashBuf, msg, len); 1.3243 + break; 1.3244 + case HASH_AlgSHA384: 1.3245 + rv = SHA384_HashBuf(hashBuf, msg, len); 1.3246 + break; 1.3247 + case HASH_AlgSHA512: 1.3248 + rv = SHA512_HashBuf(hashBuf, msg, len); 1.3249 + break; 1.3250 + default: 1.3251 + break; 1.3252 + } 1.3253 + return rv; 1.3254 +} 1.3255 + 1.3256 +int 1.3257 +fips_hashLen(HASH_HashType type) 1.3258 +{ 1.3259 + int len = 0; 1.3260 + 1.3261 + switch (type) { 1.3262 + case HASH_AlgSHA1: 1.3263 + len = SHA1_LENGTH; 1.3264 + break; 1.3265 + case HASH_AlgSHA224: 1.3266 + len = SHA224_LENGTH; 1.3267 + break; 1.3268 + case HASH_AlgSHA256: 1.3269 + len = SHA256_LENGTH; 1.3270 + break; 1.3271 + case HASH_AlgSHA384: 1.3272 + len = SHA384_LENGTH; 1.3273 + break; 1.3274 + case HASH_AlgSHA512: 1.3275 + len = SHA512_LENGTH; 1.3276 + break; 1.3277 + default: 1.3278 + break; 1.3279 + } 1.3280 + return len; 1.3281 +} 1.3282 + 1.3283 +SECOidTag 1.3284 +fips_hashOid(HASH_HashType type) 1.3285 +{ 1.3286 + SECOidTag oid = SEC_OID_UNKNOWN; 1.3287 + 1.3288 + switch (type) { 1.3289 + case HASH_AlgSHA1: 1.3290 + oid = SEC_OID_SHA1; 1.3291 + break; 1.3292 + case HASH_AlgSHA224: 1.3293 + oid = SEC_OID_SHA224; 1.3294 + break; 1.3295 + case HASH_AlgSHA256: 1.3296 + oid = SEC_OID_SHA256; 1.3297 + break; 1.3298 + case HASH_AlgSHA384: 1.3299 + oid = SEC_OID_SHA384; 1.3300 + break; 1.3301 + case HASH_AlgSHA512: 1.3302 + oid = SEC_OID_SHA512; 1.3303 + break; 1.3304 + default: 1.3305 + break; 1.3306 + } 1.3307 + return oid; 1.3308 +} 1.3309 + 1.3310 +HASH_HashType 1.3311 +sha_get_hashType(int hashbits) 1.3312 +{ 1.3313 + HASH_HashType hashType = HASH_AlgNULL; 1.3314 + 1.3315 + switch (hashbits) { 1.3316 + case 1: 1.3317 + case (SHA1_LENGTH*PR_BITS_PER_BYTE): 1.3318 + hashType = HASH_AlgSHA1; 1.3319 + break; 1.3320 + case (SHA224_LENGTH*PR_BITS_PER_BYTE): 1.3321 + hashType = HASH_AlgSHA224; 1.3322 + break; 1.3323 + case (SHA256_LENGTH*PR_BITS_PER_BYTE): 1.3324 + hashType = HASH_AlgSHA256; 1.3325 + break; 1.3326 + case (SHA384_LENGTH*PR_BITS_PER_BYTE): 1.3327 + hashType = HASH_AlgSHA384; 1.3328 + break; 1.3329 + case (SHA512_LENGTH*PR_BITS_PER_BYTE): 1.3330 + hashType = HASH_AlgSHA512; 1.3331 + break; 1.3332 + default: 1.3333 + break; 1.3334 + } 1.3335 + return hashType; 1.3336 +} 1.3337 + 1.3338 +/* 1.3339 + * Calculate the SHA Message Digest 1.3340 + * 1.3341 + * MD = Message digest 1.3342 + * MDLen = length of Message Digest and SHA_Type 1.3343 + * msg = message to digest 1.3344 + * msgLen = length of message to digest 1.3345 + */ 1.3346 +SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen) 1.3347 +{ 1.3348 + HASH_HashType hashType = sha_get_hashType(MDLen*PR_BITS_PER_BYTE); 1.3349 + 1.3350 + return fips_hashBuf(hashType, MD, msg, msgLen); 1.3351 +} 1.3352 + 1.3353 +/* 1.3354 + * Perform the SHA Monte Carlo Test 1.3355 + * 1.3356 + * MDLen = length of Message Digest and SHA_Type 1.3357 + * seed = input seed value 1.3358 + * resp = is the output response file. 1.3359 + */ 1.3360 +SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp) 1.3361 +{ 1.3362 + int i, j; 1.3363 + unsigned int msgLen = MDLen*3; 1.3364 + unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */ 1.3365 + unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */ 1.3366 + unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */ 1.3367 + unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */ 1.3368 + unsigned char msg[HASH_LENGTH_MAX*3]; 1.3369 + char buf[HASH_LENGTH_MAX*2 + 1]; /* MAX buf MD_i as a hex string */ 1.3370 + 1.3371 + for (j=0; j<100; j++) { 1.3372 + /* MD_0 = MD_1 = MD_2 = seed */ 1.3373 + memcpy(MD_i3, seed, MDLen); 1.3374 + memcpy(MD_i2, seed, MDLen); 1.3375 + memcpy(MD_i1, seed, MDLen); 1.3376 + 1.3377 + for (i=3; i < 1003; i++) { 1.3378 + /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */ 1.3379 + memcpy(msg, MD_i3, MDLen); 1.3380 + memcpy(&msg[MDLen], MD_i2, MDLen); 1.3381 + memcpy(&msg[MDLen*2], MD_i1,MDLen); 1.3382 + 1.3383 + /* MDi = SHA(Msg) */ 1.3384 + if (sha_calcMD(MD_i, MDLen, 1.3385 + msg, msgLen) != SECSuccess) { 1.3386 + return SECFailure; 1.3387 + } 1.3388 + 1.3389 + /* save MD[i-3] MD[i-2] MD[i-1] */ 1.3390 + memcpy(MD_i3, MD_i2, MDLen); 1.3391 + memcpy(MD_i2, MD_i1, MDLen); 1.3392 + memcpy(MD_i1, MD_i, MDLen); 1.3393 + 1.3394 + } 1.3395 + 1.3396 + /* seed = MD_i */ 1.3397 + memcpy(seed, MD_i, MDLen); 1.3398 + 1.3399 + sprintf(buf, "COUNT = %d\n", j); 1.3400 + fputs(buf, resp); 1.3401 + 1.3402 + /* output MD_i */ 1.3403 + fputs("MD = ", resp); 1.3404 + to_hex_str(buf, MD_i, MDLen); 1.3405 + fputs(buf, resp); 1.3406 + fputc('\n', resp); 1.3407 + } 1.3408 + 1.3409 + return SECSuccess; 1.3410 +} 1.3411 + 1.3412 +/* 1.3413 + * Perform the SHA Tests. 1.3414 + * 1.3415 + * reqfn is the pathname of the input REQUEST file. 1.3416 + * 1.3417 + * The output RESPONSE file is written to stdout. 1.3418 + */ 1.3419 +void sha_test(char *reqfn) 1.3420 +{ 1.3421 + unsigned int i, j; 1.3422 + unsigned int MDlen; /* the length of the Message Digest in Bytes */ 1.3423 + unsigned int msgLen; /* the length of the input Message in Bytes */ 1.3424 + unsigned char *msg = NULL; /* holds the message to digest.*/ 1.3425 + size_t bufSize = 25608; /*MAX buffer size */ 1.3426 + char *buf = NULL; /* holds one line from the input REQUEST file.*/ 1.3427 + unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */ 1.3428 + unsigned char MD[HASH_LENGTH_MAX]; /* message digest */ 1.3429 + 1.3430 + FILE *req = NULL; /* input stream from the REQUEST file */ 1.3431 + FILE *resp; /* output stream to the RESPONSE file */ 1.3432 + 1.3433 + buf = PORT_ZAlloc(bufSize); 1.3434 + if (buf == NULL) { 1.3435 + goto loser; 1.3436 + } 1.3437 + 1.3438 + /* zeroize the variables for the test with this data set */ 1.3439 + memset(seed, 0, sizeof seed); 1.3440 + 1.3441 + req = fopen(reqfn, "r"); 1.3442 + resp = stdout; 1.3443 + while (fgets(buf, bufSize, req) != NULL) { 1.3444 + 1.3445 + /* a comment or blank line */ 1.3446 + if (buf[0] == '#' || buf[0] == '\n') { 1.3447 + fputs(buf, resp); 1.3448 + continue; 1.3449 + } 1.3450 + /* [L = Length of the Message Digest and sha_type */ 1.3451 + if (buf[0] == '[') { 1.3452 + if (strncmp(&buf[1], "L ", 1) == 0) { 1.3453 + i = 2; 1.3454 + while (isspace(buf[i]) || buf[i] == '=') { 1.3455 + i++; 1.3456 + } 1.3457 + MDlen = atoi(&buf[i]); 1.3458 + fputs(buf, resp); 1.3459 + continue; 1.3460 + } 1.3461 + } 1.3462 + /* Len = Length of the Input Message Length ... */ 1.3463 + if (strncmp(buf, "Len", 3) == 0) { 1.3464 + i = 3; 1.3465 + while (isspace(buf[i]) || buf[i] == '=') { 1.3466 + i++; 1.3467 + } 1.3468 + if (msg) { 1.3469 + PORT_ZFree(msg,msgLen); 1.3470 + msg = NULL; 1.3471 + } 1.3472 + msgLen = atoi(&buf[i]); /* in bits */ 1.3473 + if (msgLen%8 != 0) { 1.3474 + fprintf(stderr, "SHA tests are incorrectly configured for " 1.3475 + "BIT oriented implementations\n"); 1.3476 + goto loser; 1.3477 + } 1.3478 + msgLen = msgLen/8; /* convert to bytes */ 1.3479 + fputs(buf, resp); 1.3480 + msg = PORT_ZAlloc(msgLen); 1.3481 + if (msg == NULL && msgLen != 0) { 1.3482 + goto loser; 1.3483 + } 1.3484 + continue; 1.3485 + } 1.3486 + /* MSG = ... */ 1.3487 + if (strncmp(buf, "Msg", 3) == 0) { 1.3488 + i = 3; 1.3489 + while (isspace(buf[i]) || buf[i] == '=') { 1.3490 + i++; 1.3491 + } 1.3492 + for (j=0; j< msgLen; i+=2,j++) { 1.3493 + hex_to_byteval(&buf[i], &msg[j]); 1.3494 + } 1.3495 + fputs(buf, resp); 1.3496 + /* calculate the Message Digest */ 1.3497 + memset(MD, 0, sizeof MD); 1.3498 + if (sha_calcMD(MD, MDlen, 1.3499 + msg, msgLen) != SECSuccess) { 1.3500 + goto loser; 1.3501 + } 1.3502 + 1.3503 + fputs("MD = ", resp); 1.3504 + to_hex_str(buf, MD, MDlen); 1.3505 + fputs(buf, resp); 1.3506 + fputc('\n', resp); 1.3507 + 1.3508 + continue; 1.3509 + } 1.3510 + /* Seed = ... */ 1.3511 + if (strncmp(buf, "Seed", 4) == 0) { 1.3512 + i = 4; 1.3513 + while (isspace(buf[i]) || buf[i] == '=') { 1.3514 + i++; 1.3515 + } 1.3516 + for (j=0; j<sizeof seed; i+=2,j++) { 1.3517 + hex_to_byteval(&buf[i], &seed[j]); 1.3518 + } 1.3519 + 1.3520 + fputs(buf, resp); 1.3521 + fputc('\n', resp); 1.3522 + 1.3523 + /* do the Monte Carlo test */ 1.3524 + if (sha_mct_test(MDlen, seed, resp) != SECSuccess) { 1.3525 + goto loser; 1.3526 + } 1.3527 + 1.3528 + continue; 1.3529 + } 1.3530 + } 1.3531 +loser: 1.3532 + if (req) { 1.3533 + fclose(req); 1.3534 + } 1.3535 + if (buf) { 1.3536 + PORT_ZFree(buf, bufSize); 1.3537 + } 1.3538 + if (msg) { 1.3539 + PORT_ZFree(msg, msgLen); 1.3540 + } 1.3541 +} 1.3542 + 1.3543 +/****************************************************/ 1.3544 +/* HMAC SHA-X calc */ 1.3545 +/* hmac_computed - the computed HMAC */ 1.3546 +/* hmac_length - the length of the computed HMAC */ 1.3547 +/* secret_key - secret key to HMAC */ 1.3548 +/* secret_key_length - length of secret key, */ 1.3549 +/* message - message to HMAC */ 1.3550 +/* message_length - length ofthe message */ 1.3551 +/****************************************************/ 1.3552 +static SECStatus 1.3553 +hmac_calc(unsigned char *hmac_computed, 1.3554 + const unsigned int hmac_length, 1.3555 + const unsigned char *secret_key, 1.3556 + const unsigned int secret_key_length, 1.3557 + const unsigned char *message, 1.3558 + const unsigned int message_length, 1.3559 + const HASH_HashType hashAlg ) 1.3560 +{ 1.3561 + SECStatus hmac_status = SECFailure; 1.3562 + HMACContext *cx = NULL; 1.3563 + SECHashObject *hashObj = NULL; 1.3564 + unsigned int bytes_hashed = 0; 1.3565 + 1.3566 + hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg); 1.3567 + 1.3568 + if (!hashObj) 1.3569 + return( SECFailure ); 1.3570 + 1.3571 + cx = HMAC_Create(hashObj, secret_key, 1.3572 + secret_key_length, 1.3573 + PR_TRUE); /* PR_TRUE for in FIPS mode */ 1.3574 + 1.3575 + if (cx == NULL) 1.3576 + return( SECFailure ); 1.3577 + 1.3578 + HMAC_Begin(cx); 1.3579 + HMAC_Update(cx, message, message_length); 1.3580 + hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed, 1.3581 + hmac_length); 1.3582 + 1.3583 + HMAC_Destroy(cx, PR_TRUE); 1.3584 + 1.3585 + return( hmac_status ); 1.3586 +} 1.3587 + 1.3588 +/* 1.3589 + * Perform the HMAC Tests. 1.3590 + * 1.3591 + * reqfn is the pathname of the input REQUEST file. 1.3592 + * 1.3593 + * The output RESPONSE file is written to stdout. 1.3594 + */ 1.3595 +void hmac_test(char *reqfn) 1.3596 +{ 1.3597 + unsigned int i, j; 1.3598 + size_t bufSize = 400; /* MAX buffer size */ 1.3599 + char *buf = NULL; /* holds one line from the input REQUEST file.*/ 1.3600 + unsigned int keyLen; /* Key Length */ 1.3601 + unsigned char key[200]; /* key MAX size = 184 */ 1.3602 + unsigned int msgLen = 128; /* the length of the input */ 1.3603 + /* Message is always 128 Bytes */ 1.3604 + unsigned char *msg = NULL; /* holds the message to digest.*/ 1.3605 + unsigned int HMACLen; /* the length of the HMAC Bytes */ 1.3606 + unsigned int TLen; /* the length of the requested */ 1.3607 + /* truncated HMAC Bytes */ 1.3608 + unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */ 1.3609 + unsigned char expectedHMAC[HASH_LENGTH_MAX]; /* for .fax files that have */ 1.3610 + /* supplied known answer */ 1.3611 + HASH_HashType hash_alg; /* HMAC type */ 1.3612 + 1.3613 + 1.3614 + FILE *req = NULL; /* input stream from the REQUEST file */ 1.3615 + FILE *resp; /* output stream to the RESPONSE file */ 1.3616 + 1.3617 + buf = PORT_ZAlloc(bufSize); 1.3618 + if (buf == NULL) { 1.3619 + goto loser; 1.3620 + } 1.3621 + msg = PORT_ZAlloc(msgLen); 1.3622 + if (msg == NULL) { 1.3623 + goto loser; 1.3624 + } 1.3625 + 1.3626 + req = fopen(reqfn, "r"); 1.3627 + resp = stdout; 1.3628 + while (fgets(buf, bufSize, req) != NULL) { 1.3629 + if (strncmp(buf, "Mac", 3) == 0) { 1.3630 + i = 3; 1.3631 + while (isspace(buf[i]) || buf[i] == '=') { 1.3632 + i++; 1.3633 + } 1.3634 + memset(expectedHMAC, 0, HASH_LENGTH_MAX); 1.3635 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.3636 + hex_to_byteval(&buf[i], &expectedHMAC[j]); 1.3637 + } 1.3638 + if (memcmp(HMAC, expectedHMAC, TLen) != 0) { 1.3639 + fprintf(stderr, "Generate failed:\n"); 1.3640 + fputs( " expected=", stderr); 1.3641 + to_hex_str(buf, expectedHMAC, 1.3642 + TLen); 1.3643 + fputs(buf, stderr); 1.3644 + fputs("\n generated=", stderr); 1.3645 + to_hex_str(buf, HMAC, 1.3646 + TLen); 1.3647 + fputs(buf, stderr); 1.3648 + fputc('\n', stderr); 1.3649 + } 1.3650 + } 1.3651 + 1.3652 + /* a comment or blank line */ 1.3653 + if (buf[0] == '#' || buf[0] == '\n') { 1.3654 + fputs(buf, resp); 1.3655 + continue; 1.3656 + } 1.3657 + /* [L = Length of the MAC and HASH_type */ 1.3658 + if (buf[0] == '[') { 1.3659 + if (strncmp(&buf[1], "L ", 1) == 0) { 1.3660 + i = 2; 1.3661 + while (isspace(buf[i]) || buf[i] == '=') { 1.3662 + i++; 1.3663 + } 1.3664 + /* HMACLen will get reused for Tlen */ 1.3665 + HMACLen = atoi(&buf[i]); 1.3666 + hash_alg = sha_get_hashType(HMACLen*PR_BITS_PER_BYTE); 1.3667 + if (hash_alg == HASH_AlgNULL) { 1.3668 + goto loser; 1.3669 + } 1.3670 + fputs(buf, resp); 1.3671 + continue; 1.3672 + } 1.3673 + } 1.3674 + /* Count = test iteration number*/ 1.3675 + if (strncmp(buf, "Count ", 5) == 0) { 1.3676 + /* count can just be put into resp file */ 1.3677 + fputs(buf, resp); 1.3678 + /* zeroize the variables for the test with this data set */ 1.3679 + keyLen = 0; 1.3680 + TLen = 0; 1.3681 + memset(key, 0, sizeof key); 1.3682 + memset(msg, 0, msgLen); 1.3683 + memset(HMAC, 0, sizeof HMAC); 1.3684 + continue; 1.3685 + } 1.3686 + /* KLen = Length of the Input Secret Key ... */ 1.3687 + if (strncmp(buf, "Klen", 4) == 0) { 1.3688 + i = 4; 1.3689 + while (isspace(buf[i]) || buf[i] == '=') { 1.3690 + i++; 1.3691 + } 1.3692 + keyLen = atoi(&buf[i]); /* in bytes */ 1.3693 + fputs(buf, resp); 1.3694 + continue; 1.3695 + } 1.3696 + /* key = the secret key for the key to MAC */ 1.3697 + if (strncmp(buf, "Key", 3) == 0) { 1.3698 + i = 3; 1.3699 + while (isspace(buf[i]) || buf[i] == '=') { 1.3700 + i++; 1.3701 + } 1.3702 + for (j=0; j< keyLen; i+=2,j++) { 1.3703 + hex_to_byteval(&buf[i], &key[j]); 1.3704 + } 1.3705 + fputs(buf, resp); 1.3706 + } 1.3707 + /* TLen = Length of the calculated HMAC */ 1.3708 + if (strncmp(buf, "Tlen", 4) == 0) { 1.3709 + i = 4; 1.3710 + while (isspace(buf[i]) || buf[i] == '=') { 1.3711 + i++; 1.3712 + } 1.3713 + TLen = atoi(&buf[i]); /* in bytes */ 1.3714 + fputs(buf, resp); 1.3715 + continue; 1.3716 + } 1.3717 + /* MSG = to HMAC always 128 bytes for these tests */ 1.3718 + if (strncmp(buf, "Msg", 3) == 0) { 1.3719 + i = 3; 1.3720 + while (isspace(buf[i]) || buf[i] == '=') { 1.3721 + i++; 1.3722 + } 1.3723 + for (j=0; j< msgLen; i+=2,j++) { 1.3724 + hex_to_byteval(&buf[i], &msg[j]); 1.3725 + } 1.3726 + fputs(buf, resp); 1.3727 + /* calculate the HMAC and output */ 1.3728 + if (hmac_calc(HMAC, HMACLen, key, keyLen, 1.3729 + msg, msgLen, hash_alg) != SECSuccess) { 1.3730 + goto loser; 1.3731 + } 1.3732 + fputs("MAC = ", resp); 1.3733 + to_hex_str(buf, HMAC, TLen); 1.3734 + fputs(buf, resp); 1.3735 + fputc('\n', resp); 1.3736 + continue; 1.3737 + } 1.3738 + } 1.3739 +loser: 1.3740 + if (req) { 1.3741 + fclose(req); 1.3742 + } 1.3743 + if (buf) { 1.3744 + PORT_ZFree(buf, bufSize); 1.3745 + } 1.3746 + if (msg) { 1.3747 + PORT_ZFree(msg, msgLen); 1.3748 + } 1.3749 +} 1.3750 + 1.3751 +/* 1.3752 + * Perform the DSA Key Pair Generation Test. 1.3753 + * 1.3754 + * reqfn is the pathname of the REQUEST file. 1.3755 + * 1.3756 + * The output RESPONSE file is written to stdout. 1.3757 + */ 1.3758 +void 1.3759 +dsa_keypair_test(char *reqfn) 1.3760 +{ 1.3761 + char buf[800]; /* holds one line from the input REQUEST file 1.3762 + * or to the output RESPONSE file. 1.3763 + * 800 to hold (384 public key (x2 for HEX) + 1'\n' 1.3764 + */ 1.3765 + FILE *dsareq; /* input stream from the REQUEST file */ 1.3766 + FILE *dsaresp; /* output stream to the RESPONSE file */ 1.3767 + int count; 1.3768 + int N; 1.3769 + int L; 1.3770 + int i; 1.3771 + PQGParams *pqg = NULL; 1.3772 + PQGVerify *vfy = NULL; 1.3773 + PRBool use_dsa1 = PR_FALSE; 1.3774 + int keySizeIndex; /* index for valid key sizes */ 1.3775 + 1.3776 + dsareq = fopen(reqfn, "r"); 1.3777 + dsaresp = stdout; 1.3778 + while (fgets(buf, sizeof buf, dsareq) != NULL) { 1.3779 + /* a comment or blank line */ 1.3780 + if (buf[0] == '#' || buf[0] == '\n') { 1.3781 + fputs(buf, dsaresp); 1.3782 + continue; 1.3783 + } 1.3784 + 1.3785 + /* [Mod = x] */ 1.3786 + if (buf[0] == '[') { 1.3787 + if(pqg!=NULL) { 1.3788 + PQG_DestroyParams(pqg); 1.3789 + pqg = NULL; 1.3790 + } 1.3791 + if(vfy!=NULL) { 1.3792 + PQG_DestroyVerify(vfy); 1.3793 + vfy = NULL; 1.3794 + } 1.3795 + 1.3796 + if (sscanf(buf, "[mod = L=%d, N=%d]", &L, &N) != 2) { 1.3797 + use_dsa1 = PR_TRUE; 1.3798 + if (sscanf(buf, "[mod = %d]", &L) != 1) { 1.3799 + goto loser; 1.3800 + } 1.3801 + } 1.3802 + fputs(buf, dsaresp); 1.3803 + fputc('\n', dsaresp); 1.3804 + 1.3805 + if (use_dsa1) { 1.3806 + /************************************************************* 1.3807 + * PQG_ParamGenSeedLen doesn't take a key size, it takes an 1.3808 + * index that points to a valid key size. 1.3809 + */ 1.3810 + keySizeIndex = PQG_PBITS_TO_INDEX(L); 1.3811 + if(keySizeIndex == -1 || L<512 || L>1024) { 1.3812 + fprintf(dsaresp, 1.3813 + "DSA key size must be a multiple of 64 between 512 " 1.3814 + "and 1024, inclusive"); 1.3815 + goto loser; 1.3816 + } 1.3817 + 1.3818 + /* Generate the parameters P, Q, and G */ 1.3819 + if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, 1.3820 + &pqg, &vfy) != SECSuccess) { 1.3821 + fprintf(dsaresp, 1.3822 + "ERROR: Unable to generate PQG parameters"); 1.3823 + goto loser; 1.3824 + } 1.3825 + } else { 1.3826 + if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) { 1.3827 + fprintf(dsaresp, 1.3828 + "ERROR: Unable to generate PQG parameters"); 1.3829 + goto loser; 1.3830 + } 1.3831 + } 1.3832 + 1.3833 + /* output P, Q, and G */ 1.3834 + to_hex_str(buf, pqg->prime.data, pqg->prime.len); 1.3835 + fprintf(dsaresp, "P = %s\n", buf); 1.3836 + to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); 1.3837 + fprintf(dsaresp, "Q = %s\n", buf); 1.3838 + to_hex_str(buf, pqg->base.data, pqg->base.len); 1.3839 + fprintf(dsaresp, "G = %s\n\n", buf); 1.3840 + continue; 1.3841 + } 1.3842 + /* N = ...*/ 1.3843 + if (buf[0] == 'N') { 1.3844 + 1.3845 + if (sscanf(buf, "N = %d", &count) != 1) { 1.3846 + goto loser; 1.3847 + } 1.3848 + /* Generate a DSA key, and output the key pair for N times */ 1.3849 + for (i = 0; i < count; i++) { 1.3850 + DSAPrivateKey *dsakey = NULL; 1.3851 + if (DSA_NewKey(pqg, &dsakey) != SECSuccess) { 1.3852 + fprintf(dsaresp, "ERROR: Unable to generate DSA key"); 1.3853 + goto loser; 1.3854 + } 1.3855 + to_hex_str(buf, dsakey->privateValue.data, 1.3856 + dsakey->privateValue.len); 1.3857 + fprintf(dsaresp, "X = %s\n", buf); 1.3858 + to_hex_str(buf, dsakey->publicValue.data, 1.3859 + dsakey->publicValue.len); 1.3860 + fprintf(dsaresp, "Y = %s\n\n", buf); 1.3861 + PORT_FreeArena(dsakey->params.arena, PR_TRUE); 1.3862 + dsakey = NULL; 1.3863 + } 1.3864 + continue; 1.3865 + } 1.3866 + 1.3867 + } 1.3868 +loser: 1.3869 + fclose(dsareq); 1.3870 +} 1.3871 + 1.3872 +/* 1.3873 + * pqg generation type 1.3874 + */ 1.3875 +typedef enum { 1.3876 + FIPS186_1,/* Generate/Verify P,Q & G according to FIPS 186-1 */ 1.3877 + A_1_1_2, /* Generate Probable P & Q */ 1.3878 + A_1_1_3, /* Verify Probable P & Q */ 1.3879 + A_1_2_2, /* Verify Provable P & Q */ 1.3880 + A_2_1, /* Generate Unverifiable G */ 1.3881 + A_2_2, /* Assure Unverifiable G */ 1.3882 + A_2_3, /* Generate Verifiable G */ 1.3883 + A_2_4 /* Verify Verifiable G */ 1.3884 +} dsa_pqg_type; 1.3885 + 1.3886 +/* 1.3887 + * Perform the DSA Domain Parameter Validation Test. 1.3888 + * 1.3889 + * reqfn is the pathname of the REQUEST file. 1.3890 + * 1.3891 + * The output RESPONSE file is written to stdout. 1.3892 + */ 1.3893 +void 1.3894 +dsa_pqgver_test(char *reqfn) 1.3895 +{ 1.3896 + char buf[800]; /* holds one line from the input REQUEST file 1.3897 + * or to the output RESPONSE file. 1.3898 + * 800 to hold (384 public key (x2 for HEX) + P = ... 1.3899 + */ 1.3900 + FILE *dsareq; /* input stream from the REQUEST file */ 1.3901 + FILE *dsaresp; /* output stream to the RESPONSE file */ 1.3902 + int N; 1.3903 + int L; 1.3904 + unsigned int i, j; 1.3905 + PQGParams pqg; 1.3906 + PQGVerify vfy; 1.3907 + unsigned int pghSize; /* size for p, g, and h */ 1.3908 + dsa_pqg_type type = FIPS186_1; 1.3909 + 1.3910 + dsareq = fopen(reqfn, "r"); 1.3911 + dsaresp = stdout; 1.3912 + memset(&pqg, 0, sizeof(pqg)); 1.3913 + memset(&vfy, 0, sizeof(vfy)); 1.3914 + 1.3915 + while (fgets(buf, sizeof buf, dsareq) != NULL) { 1.3916 + /* a comment or blank line */ 1.3917 + if (buf[0] == '#' || buf[0] == '\n') { 1.3918 + fputs(buf, dsaresp); 1.3919 + continue; 1.3920 + } 1.3921 + 1.3922 + /* [A.xxxxx ] */ 1.3923 + if (buf[0] == '[' && buf[1] == 'A') { 1.3924 + 1.3925 + if (strncmp(&buf[1],"A.1.1.3",7) == 0) { 1.3926 + type = A_1_1_3; 1.3927 + } else if (strncmp(&buf[1],"A.2.2",5) == 0) { 1.3928 + type = A_2_2; 1.3929 + } else if (strncmp(&buf[1],"A.2.4",5) == 0) { 1.3930 + type = A_2_4; 1.3931 + } else if (strncmp(&buf[1],"A.1.2.2",7) == 0) { 1.3932 + type = A_1_2_2; 1.3933 + /* validate our output from PQGGEN */ 1.3934 + } else if (strncmp(&buf[1],"A.1.1.2",7) == 0) { 1.3935 + type = A_2_4; /* validate PQ and G together */ 1.3936 + } else { 1.3937 + fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]); 1.3938 + exit(1); 1.3939 + } 1.3940 + 1.3941 + fputs(buf, dsaresp); 1.3942 + continue; 1.3943 + } 1.3944 + 1.3945 + 1.3946 + /* [Mod = x] */ 1.3947 + if (buf[0] == '[') { 1.3948 + 1.3949 + if (type == FIPS186_1) { 1.3950 + N=160; 1.3951 + if (sscanf(buf, "[mod = %d]", &L) != 1) { 1.3952 + goto loser; 1.3953 + } 1.3954 + } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) { 1.3955 + goto loser; 1.3956 + } 1.3957 + 1.3958 + if (pqg.prime.data) { /* P */ 1.3959 + SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); 1.3960 + } 1.3961 + if (pqg.subPrime.data) { /* Q */ 1.3962 + SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); 1.3963 + } 1.3964 + if (pqg.base.data) { /* G */ 1.3965 + SECITEM_ZfreeItem(&pqg.base, PR_FALSE); 1.3966 + } 1.3967 + if (vfy.seed.data) { /* seed */ 1.3968 + SECITEM_ZfreeItem(&vfy.seed, PR_FALSE); 1.3969 + } 1.3970 + if (vfy.h.data) { /* H */ 1.3971 + SECITEM_ZfreeItem(&vfy.h, PR_FALSE); 1.3972 + } 1.3973 + 1.3974 + fputs(buf, dsaresp); 1.3975 + 1.3976 + /*calculate the size of p, g, and h then allocate items */ 1.3977 + pghSize = L/8; 1.3978 + 1.3979 + pqg.base.data = vfy.h.data = NULL; 1.3980 + vfy.seed.len = pqg.base.len = vfy.h.len = 0; 1.3981 + SECITEM_AllocItem(NULL, &pqg.prime, pghSize); 1.3982 + SECITEM_AllocItem(NULL, &vfy.seed, pghSize*3); 1.3983 + if (type == A_2_2) { 1.3984 + SECITEM_AllocItem(NULL, &vfy.h, pghSize); 1.3985 + vfy.h.len = pghSize; 1.3986 + } else if (type == A_2_4) { 1.3987 + SECITEM_AllocItem(NULL, &vfy.h, 1); 1.3988 + vfy.h.len = 1; 1.3989 + } 1.3990 + pqg.prime.len = pghSize; 1.3991 + /* q is always N bits */ 1.3992 + SECITEM_AllocItem(NULL, &pqg.subPrime, N/8); 1.3993 + pqg.subPrime.len = N/8; 1.3994 + vfy.counter = -1; 1.3995 + 1.3996 + continue; 1.3997 + } 1.3998 + /* P = ... */ 1.3999 + if (buf[0] == 'P') { 1.4000 + i = 1; 1.4001 + while (isspace(buf[i]) || buf[i] == '=') { 1.4002 + i++; 1.4003 + } 1.4004 + for (j=0; j< pqg.prime.len; i+=2,j++) { 1.4005 + hex_to_byteval(&buf[i], &pqg.prime.data[j]); 1.4006 + } 1.4007 + 1.4008 + fputs(buf, dsaresp); 1.4009 + continue; 1.4010 + } 1.4011 + 1.4012 + /* Q = ... */ 1.4013 + if (buf[0] == 'Q') { 1.4014 + i = 1; 1.4015 + while (isspace(buf[i]) || buf[i] == '=') { 1.4016 + i++; 1.4017 + } 1.4018 + for (j=0; j< pqg.subPrime.len; i+=2,j++) { 1.4019 + hex_to_byteval(&buf[i], &pqg.subPrime.data[j]); 1.4020 + } 1.4021 + 1.4022 + fputs(buf, dsaresp); 1.4023 + continue; 1.4024 + } 1.4025 + 1.4026 + /* G = ... */ 1.4027 + if (buf[0] == 'G') { 1.4028 + i = 1; 1.4029 + if (pqg.base.data) { 1.4030 + SECITEM_ZfreeItem(&pqg.base, PR_FALSE); 1.4031 + } 1.4032 + SECITEM_AllocItem(NULL, &pqg.base, pghSize); 1.4033 + while (isspace(buf[i]) || buf[i] == '=') { 1.4034 + i++; 1.4035 + } 1.4036 + for (j=0; j< pqg.base.len; i+=2,j++) { 1.4037 + hex_to_byteval(&buf[i], &pqg.base.data[j]); 1.4038 + } 1.4039 + 1.4040 + fputs(buf, dsaresp); 1.4041 + continue; 1.4042 + } 1.4043 + 1.4044 + /* Seed = ... or domain_parameter_seed = ... */ 1.4045 + if (strncmp(buf, "Seed", 4) == 0) { 1.4046 + i = 4; 1.4047 + } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) { 1.4048 + i = 21; 1.4049 + } else if (strncmp(buf,"firstseed",9) == 0) { 1.4050 + i = 9; 1.4051 + } else { 1.4052 + i = 0; 1.4053 + } 1.4054 + if (i) { 1.4055 + while (isspace(buf[i]) || buf[i] == '=') { 1.4056 + i++; 1.4057 + } 1.4058 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.4059 + hex_to_byteval(&buf[i], &vfy.seed.data[j]); 1.4060 + } 1.4061 + vfy.seed.len = j; 1.4062 + 1.4063 + fputs(buf, dsaresp); 1.4064 + if (type == A_2_4) { 1.4065 + SECStatus result; 1.4066 + 1.4067 + /* Verify the Parameters */ 1.4068 + SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result); 1.4069 + if (rv != SECSuccess) { 1.4070 + goto loser; 1.4071 + } 1.4072 + if (result == SECSuccess) { 1.4073 + fprintf(dsaresp, "Result = P\n"); 1.4074 + } else { 1.4075 + fprintf(dsaresp, "Result = F\n"); 1.4076 + } 1.4077 + } 1.4078 + continue; 1.4079 + } 1.4080 + if ((strncmp(buf,"pseed",5) == 0) || 1.4081 + (strncmp(buf,"qseed",5) == 0)) 1.4082 + { 1.4083 + i = 5; 1.4084 + while (isspace(buf[i]) || buf[i] == '=') { 1.4085 + i++; 1.4086 + } 1.4087 + for (j=vfy.seed.len; isxdigit(buf[i]); i+=2,j++) { 1.4088 + hex_to_byteval(&buf[i], &vfy.seed.data[j]); 1.4089 + } 1.4090 + vfy.seed.len = j; 1.4091 + fputs(buf, dsaresp); 1.4092 + 1.4093 + continue; 1.4094 + } 1.4095 + if (strncmp(buf, "index", 4) == 0) { 1.4096 + i=5; 1.4097 + while (isspace(buf[i]) || buf[i] == '=') { 1.4098 + i++; 1.4099 + } 1.4100 + hex_to_byteval(&buf[i], &vfy.h.data[0]); 1.4101 + vfy.h.len = 1; 1.4102 + fputs(buf, dsaresp); 1.4103 + } 1.4104 + 1.4105 + /* c = ... or counter=*/ 1.4106 + if (buf[0] == 'c') { 1.4107 + if (strncmp(buf,"counter", 7) == 0) { 1.4108 + if (sscanf(buf, "counter = %u", &vfy.counter) != 1) { 1.4109 + goto loser; 1.4110 + } 1.4111 + } else { 1.4112 + if (sscanf(buf, "c = %u", &vfy.counter) != 1) { 1.4113 + goto loser; 1.4114 + } 1.4115 + } 1.4116 + 1.4117 + fputs(buf, dsaresp); 1.4118 + if (type == A_1_1_3) { 1.4119 + SECStatus result; 1.4120 + /* only verify P and Q, we have everything now. do it */ 1.4121 + SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result); 1.4122 + if (rv != SECSuccess) { 1.4123 + goto loser; 1.4124 + } 1.4125 + if (result == SECSuccess) { 1.4126 + fprintf(dsaresp, "Result = P\n"); 1.4127 + } else { 1.4128 + fprintf(dsaresp, "Result = F\n"); 1.4129 + } 1.4130 + fprintf(dsaresp, "\n"); 1.4131 + } 1.4132 + continue; 1.4133 + } 1.4134 + if (strncmp(buf,"pgen_counter", 12) == 0) { 1.4135 + if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) { 1.4136 + goto loser; 1.4137 + } 1.4138 + fputs(buf, dsaresp); 1.4139 + continue; 1.4140 + } 1.4141 + if (strncmp(buf,"qgen_counter", 12) == 0) { 1.4142 + fputs(buf, dsaresp); 1.4143 + if (type == A_1_2_2) { 1.4144 + SECStatus result; 1.4145 + /* only verify P and Q, we have everything now. do it */ 1.4146 + SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result); 1.4147 + if (rv != SECSuccess) { 1.4148 + goto loser; 1.4149 + } 1.4150 + if (result == SECSuccess) { 1.4151 + fprintf(dsaresp, "Result = P\n"); 1.4152 + } else { 1.4153 + fprintf(dsaresp, "Result = F\n"); 1.4154 + } 1.4155 + fprintf(dsaresp, "\n"); 1.4156 + } 1.4157 + continue; 1.4158 + } 1.4159 + /* H = ... */ 1.4160 + if (buf[0] == 'H') { 1.4161 + SECStatus rv, result = SECFailure; 1.4162 + 1.4163 + i = 1; 1.4164 + while (isspace(buf[i]) || buf[i] == '=') { 1.4165 + i++; 1.4166 + } 1.4167 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.4168 + hex_to_byteval(&buf[i], &vfy.h.data[j]); 1.4169 + } 1.4170 + vfy.h.len = j; 1.4171 + fputs(buf, dsaresp); 1.4172 + 1.4173 + /* this should be a byte value. Remove the leading zeros. If 1.4174 + * it doesn't reduce to a byte, PQG_VerifyParams will catch it 1.4175 + if (type == A_2_2) { 1.4176 + data_save = vfy.h.data; 1.4177 + while(vfy.h.data[0] && (vfy.h.len > 1)) { 1.4178 + vfy.h.data++; 1.4179 + vfy.h.len--; 1.4180 + } 1.4181 + } */ 1.4182 + 1.4183 + /* Verify the Parameters */ 1.4184 + rv = PQG_VerifyParams(&pqg, &vfy, &result); 1.4185 + if (rv != SECSuccess) { 1.4186 + goto loser; 1.4187 + } 1.4188 + if (result == SECSuccess) { 1.4189 + fprintf(dsaresp, "Result = P\n"); 1.4190 + } else { 1.4191 + fprintf(dsaresp, "Result = F\n"); 1.4192 + } 1.4193 + fprintf(dsaresp, "\n"); 1.4194 + continue; 1.4195 + } 1.4196 + } 1.4197 +loser: 1.4198 + fclose(dsareq); 1.4199 + if (pqg.prime.data) { /* P */ 1.4200 + SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); 1.4201 + } 1.4202 + if (pqg.subPrime.data) { /* Q */ 1.4203 + SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); 1.4204 + } 1.4205 + if (pqg.base.data) { /* G */ 1.4206 + SECITEM_ZfreeItem(&pqg.base, PR_FALSE); 1.4207 + } 1.4208 + if (vfy.seed.data) { /* seed */ 1.4209 + SECITEM_ZfreeItem(&vfy.seed, PR_FALSE); 1.4210 + } 1.4211 + if (vfy.h.data) { /* H */ 1.4212 + SECITEM_ZfreeItem(&vfy.h, PR_FALSE); 1.4213 + } 1.4214 + 1.4215 +} 1.4216 + 1.4217 +/* 1.4218 + * Perform the DSA Public Key Validation Test. 1.4219 + * 1.4220 + * reqfn is the pathname of the REQUEST file. 1.4221 + * 1.4222 + * The output RESPONSE file is written to stdout. 1.4223 + */ 1.4224 +void 1.4225 +dsa_pqggen_test(char *reqfn) 1.4226 +{ 1.4227 + char buf[800]; /* holds one line from the input REQUEST file 1.4228 + * or to the output RESPONSE file. 1.4229 + * 800 to hold seed = (384 public key (x2 for HEX) 1.4230 + */ 1.4231 + FILE *dsareq; /* input stream from the REQUEST file */ 1.4232 + FILE *dsaresp; /* output stream to the RESPONSE file */ 1.4233 + int count; /* number of times to generate parameters */ 1.4234 + int N; 1.4235 + int L; 1.4236 + int i; 1.4237 + unsigned int j; 1.4238 + PQGParams *pqg = NULL; 1.4239 + PQGVerify *vfy = NULL; 1.4240 + unsigned int keySizeIndex; 1.4241 + dsa_pqg_type type = FIPS186_1; 1.4242 + 1.4243 + dsareq = fopen(reqfn, "r"); 1.4244 + dsaresp = stdout; 1.4245 + while (fgets(buf, sizeof buf, dsareq) != NULL) { 1.4246 + /* a comment or blank line */ 1.4247 + if (buf[0] == '#' || buf[0] == '\n') { 1.4248 + fputs(buf, dsaresp); 1.4249 + continue; 1.4250 + } 1.4251 + 1.4252 + /* [A.xxxxx ] */ 1.4253 + if (buf[0] == '[' && buf[1] == 'A') { 1.4254 + if (strncmp(&buf[1],"A.1.1.2",7) == 0) { 1.4255 + type = A_1_1_2; 1.4256 + } else if (strncmp(&buf[1],"A.2.1",5) == 0) { 1.4257 + fprintf(stderr, "NSS only Generates G with P&Q\n"); 1.4258 + exit(1); 1.4259 + } else if (strncmp(&buf[1],"A.2.3",5) == 0) { 1.4260 + fprintf(stderr, "NSS only Generates G with P&Q\n"); 1.4261 + exit(1); 1.4262 + } else if (strncmp(&buf[1],"A.1.2.1",7) == 0) { 1.4263 + fprintf(stderr, "NSS does not support Shawe-Taylor Primes\n"); 1.4264 + exit(1); 1.4265 + } else { 1.4266 + fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]); 1.4267 + exit(1); 1.4268 + } 1.4269 + fputs(buf, dsaresp); 1.4270 + continue; 1.4271 + } 1.4272 + 1.4273 + /* [Mod = ... ] */ 1.4274 + if (buf[0] == '[') { 1.4275 + 1.4276 + if (type == FIPS186_1) { 1.4277 + N=160; 1.4278 + if (sscanf(buf, "[mod = %d]", &L) != 1) { 1.4279 + goto loser; 1.4280 + } 1.4281 + } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) { 1.4282 + goto loser; 1.4283 + } 1.4284 + 1.4285 + fputs(buf, dsaresp); 1.4286 + fputc('\n', dsaresp); 1.4287 + 1.4288 + if (type == FIPS186_1) { 1.4289 + /************************************************************ 1.4290 + * PQG_ParamGenSeedLen doesn't take a key size, it takes an 1.4291 + * index that points to a valid key size. 1.4292 + */ 1.4293 + keySizeIndex = PQG_PBITS_TO_INDEX(L); 1.4294 + if(keySizeIndex == -1 || L<512 || L>1024) { 1.4295 + fprintf(dsaresp, 1.4296 + "DSA key size must be a multiple of 64 between 512 " 1.4297 + "and 1024, inclusive"); 1.4298 + goto loser; 1.4299 + } 1.4300 + } 1.4301 + continue; 1.4302 + } 1.4303 + /* N = ... */ 1.4304 + if (buf[0] == 'N') { 1.4305 + if (sscanf(buf, "N = %d", &count) != 1) { 1.4306 + goto loser; 1.4307 + } 1.4308 + for (i = 0; i < count; i++) { 1.4309 + SECStatus rv; 1.4310 + 1.4311 + if (type == FIPS186_1) { 1.4312 + rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, 1.4313 + &pqg, &vfy); 1.4314 + } else { 1.4315 + rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy); 1.4316 + } 1.4317 + if (rv != SECSuccess) { 1.4318 + fprintf(dsaresp, 1.4319 + "ERROR: Unable to generate PQG parameters"); 1.4320 + goto loser; 1.4321 + } 1.4322 + to_hex_str(buf, pqg->prime.data, pqg->prime.len); 1.4323 + fprintf(dsaresp, "P = %s\n", buf); 1.4324 + to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); 1.4325 + fprintf(dsaresp, "Q = %s\n", buf); 1.4326 + to_hex_str(buf, pqg->base.data, pqg->base.len); 1.4327 + fprintf(dsaresp, "G = %s\n", buf); 1.4328 + if (type == FIPS186_1) { 1.4329 + to_hex_str(buf, vfy->seed.data, vfy->seed.len); 1.4330 + fprintf(dsaresp, "Seed = %s\n", buf); 1.4331 + fprintf(dsaresp, "c = %d\n", vfy->counter); 1.4332 + to_hex_str(buf, vfy->h.data, vfy->h.len); 1.4333 + fputs("H = ", dsaresp); 1.4334 + for (j=vfy->h.len; j< pqg->prime.len; j++) { 1.4335 + fprintf(dsaresp, "00"); 1.4336 + } 1.4337 + fprintf(dsaresp, "%s\n", buf); 1.4338 + } else { 1.4339 + fprintf(dsaresp, "counter = %d\n", vfy->counter); 1.4340 + fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]); 1.4341 + to_hex_str(buf, vfy->seed.data, vfy->seed.len); 1.4342 + fprintf(dsaresp, "domain_parameter_seed = %s\n", buf); 1.4343 + } 1.4344 + fputc('\n', dsaresp); 1.4345 + if(pqg!=NULL) { 1.4346 + PQG_DestroyParams(pqg); 1.4347 + pqg = NULL; 1.4348 + } 1.4349 + if(vfy!=NULL) { 1.4350 + PQG_DestroyVerify(vfy); 1.4351 + vfy = NULL; 1.4352 + } 1.4353 + } 1.4354 + 1.4355 + continue; 1.4356 + } 1.4357 + 1.4358 + } 1.4359 +loser: 1.4360 + fclose(dsareq); 1.4361 + if(pqg!=NULL) { 1.4362 + PQG_DestroyParams(pqg); 1.4363 + } 1.4364 + if(vfy!=NULL) { 1.4365 + PQG_DestroyVerify(vfy); 1.4366 + } 1.4367 +} 1.4368 + 1.4369 + 1.4370 +/* 1.4371 + * Perform the DSA Signature Generation Test. 1.4372 + * 1.4373 + * reqfn is the pathname of the REQUEST file. 1.4374 + * 1.4375 + * The output RESPONSE file is written to stdout. 1.4376 + */ 1.4377 +void 1.4378 +dsa_siggen_test(char *reqfn) 1.4379 +{ 1.4380 + char buf[800]; /* holds one line from the input REQUEST file 1.4381 + * or to the output RESPONSE file. 1.4382 + * max for Msg = .... 1.4383 + */ 1.4384 + FILE *dsareq; /* input stream from the REQUEST file */ 1.4385 + FILE *dsaresp; /* output stream to the RESPONSE file */ 1.4386 + int modulus; 1.4387 + int L; 1.4388 + int N; 1.4389 + int i, j; 1.4390 + PRBool use_dsa1 = PR_FALSE; 1.4391 + PQGParams *pqg = NULL; 1.4392 + PQGVerify *vfy = NULL; 1.4393 + DSAPrivateKey *dsakey = NULL; 1.4394 + int keySizeIndex; /* index for valid key sizes */ 1.4395 + unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */ 1.4396 + unsigned char sig[DSA_MAX_SIGNATURE_LEN]; 1.4397 + SECItem digest, signature; 1.4398 + HASH_HashType hashType = HASH_AlgNULL; 1.4399 + int hashNum = 0; 1.4400 + 1.4401 + dsareq = fopen(reqfn, "r"); 1.4402 + dsaresp = stdout; 1.4403 + 1.4404 + while (fgets(buf, sizeof buf, dsareq) != NULL) { 1.4405 + /* a comment or blank line */ 1.4406 + if (buf[0] == '#' || buf[0] == '\n') { 1.4407 + fputs(buf, dsaresp); 1.4408 + continue; 1.4409 + } 1.4410 + 1.4411 + /* [Mod = x] */ 1.4412 + if (buf[0] == '[') { 1.4413 + if(pqg!=NULL) { 1.4414 + PQG_DestroyParams(pqg); 1.4415 + pqg = NULL; 1.4416 + } 1.4417 + if(vfy!=NULL) { 1.4418 + PQG_DestroyVerify(vfy); 1.4419 + vfy = NULL; 1.4420 + } 1.4421 + if (dsakey != NULL) { 1.4422 + PORT_FreeArena(dsakey->params.arena, PR_TRUE); 1.4423 + dsakey = NULL; 1.4424 + } 1.4425 + 1.4426 + if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, & N, 1.4427 + &hashNum) != 3) { 1.4428 + use_dsa1 = PR_TRUE; 1.4429 + hashNum = 1; 1.4430 + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { 1.4431 + goto loser; 1.4432 + } 1.4433 + } 1.4434 + fputs(buf, dsaresp); 1.4435 + fputc('\n', dsaresp); 1.4436 + 1.4437 + /**************************************************************** 1.4438 + * PQG_ParamGenSeedLen doesn't take a key size, it takes an index 1.4439 + * that points to a valid key size. 1.4440 + */ 1.4441 + if (use_dsa1) { 1.4442 + keySizeIndex = PQG_PBITS_TO_INDEX(modulus); 1.4443 + if(keySizeIndex == -1 || modulus<512 || modulus>1024) { 1.4444 + fprintf(dsaresp, 1.4445 + "DSA key size must be a multiple of 64 between 512 " 1.4446 + "and 1024, inclusive"); 1.4447 + goto loser; 1.4448 + } 1.4449 + /* Generate PQG and output PQG */ 1.4450 + if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, 1.4451 + &pqg, &vfy) != SECSuccess) { 1.4452 + fprintf(dsaresp, 1.4453 + "ERROR: Unable to generate PQG parameters"); 1.4454 + goto loser; 1.4455 + } 1.4456 + } else { 1.4457 + if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) { 1.4458 + fprintf(dsaresp, 1.4459 + "ERROR: Unable to generate PQG parameters"); 1.4460 + goto loser; 1.4461 + } 1.4462 + } 1.4463 + to_hex_str(buf, pqg->prime.data, pqg->prime.len); 1.4464 + fprintf(dsaresp, "P = %s\n", buf); 1.4465 + to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); 1.4466 + fprintf(dsaresp, "Q = %s\n", buf); 1.4467 + to_hex_str(buf, pqg->base.data, pqg->base.len); 1.4468 + fprintf(dsaresp, "G = %s\n", buf); 1.4469 + 1.4470 + /* create DSA Key */ 1.4471 + if (DSA_NewKey(pqg, &dsakey) != SECSuccess) { 1.4472 + fprintf(dsaresp, "ERROR: Unable to generate DSA key"); 1.4473 + goto loser; 1.4474 + } 1.4475 + 1.4476 + hashType = sha_get_hashType(hashNum); 1.4477 + if (hashType == HASH_AlgNULL) { 1.4478 + fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)",hashNum); 1.4479 + goto loser; 1.4480 + } 1.4481 + continue; 1.4482 + } 1.4483 + 1.4484 + /* Msg = ... */ 1.4485 + if (strncmp(buf, "Msg", 3) == 0) { 1.4486 + unsigned char msg[128]; /* MAX msg 128 */ 1.4487 + unsigned int len = 0; 1.4488 + 1.4489 + if (hashType == HASH_AlgNULL) { 1.4490 + fprintf(dsaresp, "ERROR: Hash Alg not set"); 1.4491 + goto loser; 1.4492 + } 1.4493 + 1.4494 + memset(hashBuf, 0, sizeof hashBuf); 1.4495 + memset(sig, 0, sizeof sig); 1.4496 + 1.4497 + i = 3; 1.4498 + while (isspace(buf[i]) || buf[i] == '=') { 1.4499 + i++; 1.4500 + } 1.4501 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.4502 + hex_to_byteval(&buf[i], &msg[j]); 1.4503 + } 1.4504 + if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) { 1.4505 + fprintf(dsaresp, "ERROR: Unable to generate SHA% digest", 1.4506 + hashNum); 1.4507 + goto loser; 1.4508 + } 1.4509 + 1.4510 + 1.4511 + digest.type = siBuffer; 1.4512 + digest.data = hashBuf; 1.4513 + digest.len = fips_hashLen(hashType); 1.4514 + signature.type = siBuffer; 1.4515 + signature.data = sig; 1.4516 + signature.len = sizeof sig; 1.4517 + 1.4518 + if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) { 1.4519 + fprintf(dsaresp, "ERROR: Unable to generate DSA signature"); 1.4520 + goto loser; 1.4521 + } 1.4522 + len = signature.len; 1.4523 + if (len%2 != 0) { 1.4524 + goto loser; 1.4525 + } 1.4526 + len = len/2; 1.4527 + 1.4528 + /* output the orginal Msg, and generated Y, R, and S */ 1.4529 + fputs(buf, dsaresp); 1.4530 + to_hex_str(buf, dsakey->publicValue.data, 1.4531 + dsakey->publicValue.len); 1.4532 + fprintf(dsaresp, "Y = %s\n", buf); 1.4533 + to_hex_str(buf, &signature.data[0], len); 1.4534 + fprintf(dsaresp, "R = %s\n", buf); 1.4535 + to_hex_str(buf, &signature.data[len], len); 1.4536 + fprintf(dsaresp, "S = %s\n", buf); 1.4537 + fputc('\n', dsaresp); 1.4538 + continue; 1.4539 + } 1.4540 + 1.4541 + } 1.4542 +loser: 1.4543 + fclose(dsareq); 1.4544 + if(pqg != NULL) { 1.4545 + PQG_DestroyParams(pqg); 1.4546 + pqg = NULL; 1.4547 + } 1.4548 + if(vfy != NULL) { 1.4549 + PQG_DestroyVerify(vfy); 1.4550 + vfy = NULL; 1.4551 + } 1.4552 + if (dsakey) { 1.4553 + PORT_FreeArena(dsakey->params.arena, PR_TRUE); 1.4554 + dsakey = NULL; 1.4555 + } 1.4556 +} 1.4557 + 1.4558 + /* 1.4559 + * Perform the DSA Signature Verification Test. 1.4560 + * 1.4561 + * reqfn is the pathname of the REQUEST file. 1.4562 + * 1.4563 + * The output RESPONSE file is written to stdout. 1.4564 + */ 1.4565 +void 1.4566 +dsa_sigver_test(char *reqfn) 1.4567 +{ 1.4568 + char buf[800]; /* holds one line from the input REQUEST file 1.4569 + * or to the output RESPONSE file. 1.4570 + * max for Msg = .... 1.4571 + */ 1.4572 + FILE *dsareq; /* input stream from the REQUEST file */ 1.4573 + FILE *dsaresp; /* output stream to the RESPONSE file */ 1.4574 + int L; 1.4575 + int N; 1.4576 + unsigned int i, j; 1.4577 + SECItem digest, signature; 1.4578 + DSAPublicKey pubkey; 1.4579 + unsigned int pgySize; /* size for p, g, and y */ 1.4580 + unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */ 1.4581 + unsigned char sig[DSA_MAX_SIGNATURE_LEN]; 1.4582 + HASH_HashType hashType = HASH_AlgNULL; 1.4583 + int hashNum = 0; 1.4584 + 1.4585 + dsareq = fopen(reqfn, "r"); 1.4586 + dsaresp = stdout; 1.4587 + memset(&pubkey, 0, sizeof(pubkey)); 1.4588 + 1.4589 + while (fgets(buf, sizeof buf, dsareq) != NULL) { 1.4590 + /* a comment or blank line */ 1.4591 + if (buf[0] == '#' || buf[0] == '\n') { 1.4592 + fputs(buf, dsaresp); 1.4593 + continue; 1.4594 + } 1.4595 + 1.4596 + /* [Mod = x] */ 1.4597 + if (buf[0] == '[') { 1.4598 + 1.4599 + if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, & N, 1.4600 + &hashNum) != 3) { 1.4601 + N=160; 1.4602 + hashNum = 1; 1.4603 + if (sscanf(buf, "[mod = %d]", &L) != 1) { 1.4604 + goto loser; 1.4605 + } 1.4606 + } 1.4607 + 1.4608 + if (pubkey.params.prime.data) { /* P */ 1.4609 + SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE); 1.4610 + } 1.4611 + if (pubkey.params.subPrime.data) { /* Q */ 1.4612 + SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE); 1.4613 + } 1.4614 + if (pubkey.params.base.data) { /* G */ 1.4615 + SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE); 1.4616 + } 1.4617 + if (pubkey.publicValue.data) { /* Y */ 1.4618 + SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE); 1.4619 + } 1.4620 + fputs(buf, dsaresp); 1.4621 + 1.4622 + /* calculate the size of p, g, and y then allocate items */ 1.4623 + pgySize = L/8; 1.4624 + SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize); 1.4625 + SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize); 1.4626 + SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize); 1.4627 + pubkey.params.prime.len = pubkey.params.base.len = pgySize; 1.4628 + pubkey.publicValue.len = pgySize; 1.4629 + 1.4630 + /* q always N/8 bytes */ 1.4631 + SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N/8); 1.4632 + pubkey.params.subPrime.len = N/8; 1.4633 + 1.4634 + hashType = sha_get_hashType(hashNum); 1.4635 + if (hashType == HASH_AlgNULL) { 1.4636 + fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)",hashNum); 1.4637 + goto loser; 1.4638 + } 1.4639 + 1.4640 + continue; 1.4641 + } 1.4642 + /* P = ... */ 1.4643 + if (buf[0] == 'P') { 1.4644 + i = 1; 1.4645 + while (isspace(buf[i]) || buf[i] == '=') { 1.4646 + i++; 1.4647 + } 1.4648 + memset(pubkey.params.prime.data, 0, pubkey.params.prime.len); 1.4649 + for (j=0; j< pubkey.params.prime.len; i+=2,j++) { 1.4650 + hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]); 1.4651 + } 1.4652 + 1.4653 + fputs(buf, dsaresp); 1.4654 + continue; 1.4655 + } 1.4656 + 1.4657 + /* Q = ... */ 1.4658 + if (buf[0] == 'Q') { 1.4659 + i = 1; 1.4660 + while (isspace(buf[i]) || buf[i] == '=') { 1.4661 + i++; 1.4662 + } 1.4663 + memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len); 1.4664 + for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) { 1.4665 + hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]); 1.4666 + } 1.4667 + 1.4668 + fputs(buf, dsaresp); 1.4669 + continue; 1.4670 + } 1.4671 + 1.4672 + /* G = ... */ 1.4673 + if (buf[0] == 'G') { 1.4674 + i = 1; 1.4675 + while (isspace(buf[i]) || buf[i] == '=') { 1.4676 + i++; 1.4677 + } 1.4678 + memset(pubkey.params.base.data, 0, pubkey.params.base.len); 1.4679 + for (j=0; j< pubkey.params.base.len; i+=2,j++) { 1.4680 + hex_to_byteval(&buf[i], &pubkey.params.base.data[j]); 1.4681 + } 1.4682 + 1.4683 + fputs(buf, dsaresp); 1.4684 + continue; 1.4685 + } 1.4686 + 1.4687 + /* Msg = ... */ 1.4688 + if (strncmp(buf, "Msg", 3) == 0) { 1.4689 + unsigned char msg[128]; /* MAX msg 128 */ 1.4690 + memset(hashBuf, 0, sizeof hashBuf); 1.4691 + 1.4692 + if (hashType == HASH_AlgNULL) { 1.4693 + fprintf(dsaresp, "ERROR: Hash Alg not set"); 1.4694 + goto loser; 1.4695 + } 1.4696 + 1.4697 + i = 3; 1.4698 + while (isspace(buf[i]) || buf[i] == '=') { 1.4699 + i++; 1.4700 + } 1.4701 + for (j=0; isxdigit(buf[i]); i+=2,j++) { 1.4702 + hex_to_byteval(&buf[i], &msg[j]); 1.4703 + } 1.4704 + if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) { 1.4705 + fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest", 1.4706 + hashNum); 1.4707 + goto loser; 1.4708 + } 1.4709 + 1.4710 + fputs(buf, dsaresp); 1.4711 + continue; 1.4712 + } 1.4713 + 1.4714 + /* Y = ... */ 1.4715 + if (buf[0] == 'Y') { 1.4716 + i = 1; 1.4717 + while (isspace(buf[i]) || buf[i] == '=') { 1.4718 + i++; 1.4719 + } 1.4720 + memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len); 1.4721 + for (j=0; j< pubkey.publicValue.len; i+=2,j++) { 1.4722 + hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]); 1.4723 + } 1.4724 + 1.4725 + fputs(buf, dsaresp); 1.4726 + continue; 1.4727 + } 1.4728 + 1.4729 + /* R = ... */ 1.4730 + if (buf[0] == 'R') { 1.4731 + memset(sig, 0, sizeof sig); 1.4732 + i = 1; 1.4733 + while (isspace(buf[i]) || buf[i] == '=') { 1.4734 + i++; 1.4735 + } 1.4736 + for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) { 1.4737 + hex_to_byteval(&buf[i], &sig[j]); 1.4738 + } 1.4739 + 1.4740 + fputs(buf, dsaresp); 1.4741 + continue; 1.4742 + } 1.4743 + 1.4744 + /* S = ... */ 1.4745 + if (buf[0] == 'S') { 1.4746 + if (hashType == HASH_AlgNULL) { 1.4747 + fprintf(dsaresp, "ERROR: Hash Alg not set"); 1.4748 + goto loser; 1.4749 + } 1.4750 + 1.4751 + i = 1; 1.4752 + while (isspace(buf[i]) || buf[i] == '=') { 1.4753 + i++; 1.4754 + } 1.4755 + for (j=pubkey.params.subPrime.len; 1.4756 + j< pubkey.params.subPrime.len*2; i+=2,j++) { 1.4757 + hex_to_byteval(&buf[i], &sig[j]); 1.4758 + } 1.4759 + fputs(buf, dsaresp); 1.4760 + 1.4761 + digest.type = siBuffer; 1.4762 + digest.data = hashBuf; 1.4763 + digest.len = fips_hashLen(hashType); 1.4764 + signature.type = siBuffer; 1.4765 + signature.data = sig; 1.4766 + signature.len = pubkey.params.subPrime.len*2; 1.4767 + 1.4768 + if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) { 1.4769 + fprintf(dsaresp, "Result = P\n"); 1.4770 + } else { 1.4771 + fprintf(dsaresp, "Result = F\n"); 1.4772 + } 1.4773 + fprintf(dsaresp, "\n"); 1.4774 + continue; 1.4775 + } 1.4776 + } 1.4777 +loser: 1.4778 + fclose(dsareq); 1.4779 + if (pubkey.params.prime.data) { /* P */ 1.4780 + SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE); 1.4781 + } 1.4782 + if (pubkey.params.subPrime.data) { /* Q */ 1.4783 + SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE); 1.4784 + } 1.4785 + if (pubkey.params.base.data) { /* G */ 1.4786 + SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE); 1.4787 + } 1.4788 + if (pubkey.publicValue.data) { /* Y */ 1.4789 + SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE); 1.4790 + } 1.4791 +} 1.4792 + 1.4793 +/* 1.4794 + * Perform the RSA Signature Generation Test. 1.4795 + * 1.4796 + * reqfn is the pathname of the REQUEST file. 1.4797 + * 1.4798 + * The output RESPONSE file is written to stdout. 1.4799 + */ 1.4800 +void 1.4801 +rsa_siggen_test(char *reqfn) 1.4802 +{ 1.4803 + char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1]; 1.4804 + /* buf holds one line from the input REQUEST file 1.4805 + * or to the output RESPONSE file. 1.4806 + * 2x for HEX output + 1 for \n 1.4807 + */ 1.4808 + FILE *rsareq; /* input stream from the REQUEST file */ 1.4809 + FILE *rsaresp; /* output stream to the RESPONSE file */ 1.4810 + int i, j; 1.4811 + unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ 1.4812 + unsigned int shaLength = 0; /* length of SHA */ 1.4813 + HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */ 1.4814 + SECOidTag shaOid = SEC_OID_UNKNOWN; 1.4815 + int modulus; /* the Modulus size */ 1.4816 + int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT; 1.4817 + SECItem pe = {0, 0, 0 }; 1.4818 + unsigned char pubEx[4]; 1.4819 + int peCount = 0; 1.4820 + 1.4821 + RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and 1.4822 + * public keys */ 1.4823 + RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */ 1.4824 + 1.4825 + rsareq = fopen(reqfn, "r"); 1.4826 + rsaresp = stdout; 1.4827 + 1.4828 + /* calculate the exponent */ 1.4829 + for (i=0; i < 4; i++) { 1.4830 + if (peCount || (publicExponent & 1.4831 + ((unsigned long)0xff000000L >> (i*8)))) { 1.4832 + pubEx[peCount] = 1.4833 + (unsigned char)((publicExponent >> (3-i)*8) & 0xff); 1.4834 + peCount++; 1.4835 + } 1.4836 + } 1.4837 + pe.len = peCount; 1.4838 + pe.data = &pubEx[0]; 1.4839 + pe.type = siBuffer; 1.4840 + 1.4841 + while (fgets(buf, sizeof buf, rsareq) != NULL) { 1.4842 + /* a comment or blank line */ 1.4843 + if (buf[0] == '#' || buf[0] == '\n') { 1.4844 + fputs(buf, rsaresp); 1.4845 + continue; 1.4846 + } 1.4847 + 1.4848 + /* [mod = ...] */ 1.4849 + if (buf[0] == '[') { 1.4850 + 1.4851 + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { 1.4852 + goto loser; 1.4853 + } 1.4854 + if (modulus > RSA_MAX_TEST_MODULUS_BITS) { 1.4855 + fprintf(rsaresp,"ERROR: modulus greater than test maximum\n"); 1.4856 + goto loser; 1.4857 + } 1.4858 + 1.4859 + fputs(buf, rsaresp); 1.4860 + 1.4861 + if (rsaBlapiPrivKey != NULL) { 1.4862 + PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE); 1.4863 + rsaBlapiPrivKey = NULL; 1.4864 + rsaBlapiPublicKey = NULL; 1.4865 + } 1.4866 + 1.4867 + rsaBlapiPrivKey = RSA_NewKey(modulus, &pe); 1.4868 + if (rsaBlapiPrivKey == NULL) { 1.4869 + fprintf(rsaresp, "Error unable to create RSA key\n"); 1.4870 + goto loser; 1.4871 + } 1.4872 + 1.4873 + to_hex_str(buf, rsaBlapiPrivKey->modulus.data, 1.4874 + rsaBlapiPrivKey->modulus.len); 1.4875 + fprintf(rsaresp, "\nn = %s\n\n", buf); 1.4876 + to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data, 1.4877 + rsaBlapiPrivKey->publicExponent.len); 1.4878 + fprintf(rsaresp, "e = %s\n", buf); 1.4879 + /* convert private key to public key. Memory 1.4880 + * is freed with private key's arena */ 1.4881 + rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc( 1.4882 + rsaBlapiPrivKey->arena, 1.4883 + sizeof(RSAPublicKey)); 1.4884 + 1.4885 + rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len; 1.4886 + rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data; 1.4887 + rsaBlapiPublicKey->publicExponent.len = 1.4888 + rsaBlapiPrivKey->publicExponent.len; 1.4889 + rsaBlapiPublicKey->publicExponent.data = 1.4890 + rsaBlapiPrivKey->publicExponent.data; 1.4891 + continue; 1.4892 + } 1.4893 + 1.4894 + /* SHAAlg = ... */ 1.4895 + if (strncmp(buf, "SHAAlg", 6) == 0) { 1.4896 + i = 6; 1.4897 + while (isspace(buf[i]) || buf[i] == '=') { 1.4898 + i++; 1.4899 + } 1.4900 + /* set the SHA Algorithm */ 1.4901 + if (strncmp(&buf[i], "SHA1", 4) == 0) { 1.4902 + shaAlg = HASH_AlgSHA1; 1.4903 + } else if (strncmp(&buf[i], "SHA224", 6) == 0) { 1.4904 + shaAlg = HASH_AlgSHA224; 1.4905 + } else if (strncmp(&buf[i], "SHA256", 6) == 0) { 1.4906 + shaAlg = HASH_AlgSHA256; 1.4907 + } else if (strncmp(&buf[i], "SHA384", 6)== 0) { 1.4908 + shaAlg = HASH_AlgSHA384; 1.4909 + } else if (strncmp(&buf[i], "SHA512", 6) == 0) { 1.4910 + shaAlg = HASH_AlgSHA512; 1.4911 + } else { 1.4912 + fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); 1.4913 + goto loser; 1.4914 + } 1.4915 + fputs(buf, rsaresp); 1.4916 + continue; 1.4917 + 1.4918 + } 1.4919 + /* Msg = ... */ 1.4920 + if (strncmp(buf, "Msg", 3) == 0) { 1.4921 + 1.4922 + unsigned char msg[128]; /* MAX msg 128 */ 1.4923 + unsigned int rsa_bytes_signed; 1.4924 + unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES]; 1.4925 + SECStatus rv = SECFailure; 1.4926 + NSSLOWKEYPublicKey * rsa_public_key; 1.4927 + NSSLOWKEYPrivateKey * rsa_private_key; 1.4928 + NSSLOWKEYPrivateKey low_RSA_private_key = { NULL, 1.4929 + NSSLOWKEYRSAKey, }; 1.4930 + NSSLOWKEYPublicKey low_RSA_public_key = { NULL, 1.4931 + NSSLOWKEYRSAKey, }; 1.4932 + 1.4933 + low_RSA_private_key.u.rsa = *rsaBlapiPrivKey; 1.4934 + low_RSA_public_key.u.rsa = *rsaBlapiPublicKey; 1.4935 + 1.4936 + rsa_private_key = &low_RSA_private_key; 1.4937 + rsa_public_key = &low_RSA_public_key; 1.4938 + 1.4939 + memset(sha, 0, sizeof sha); 1.4940 + memset(msg, 0, sizeof msg); 1.4941 + rsa_bytes_signed = 0; 1.4942 + memset(rsa_computed_signature, 0, sizeof rsa_computed_signature); 1.4943 + 1.4944 + i = 3; 1.4945 + while (isspace(buf[i]) || buf[i] == '=') { 1.4946 + i++; 1.4947 + } 1.4948 + for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) { 1.4949 + hex_to_byteval(&buf[i], &msg[j]); 1.4950 + } 1.4951 + shaLength = fips_hashLen(shaAlg); 1.4952 + if (fips_hashBuf(shaAlg,sha,msg,j) != SECSuccess) { 1.4953 + if (shaLength == 0) { 1.4954 + fprintf(rsaresp, "ERROR: SHAAlg not defined."); 1.4955 + } 1.4956 + fprintf(rsaresp, "ERROR: Unable to generate SHA%x", 1.4957 + shaLength == 160 ? 1 : shaLength); 1.4958 + goto loser; 1.4959 + } 1.4960 + shaOid = fips_hashOid(shaAlg); 1.4961 + 1.4962 + /* Perform RSA signature with the RSA private key. */ 1.4963 + rv = RSA_HashSign( shaOid, 1.4964 + rsa_private_key, 1.4965 + rsa_computed_signature, 1.4966 + &rsa_bytes_signed, 1.4967 + nsslowkey_PrivateModulusLen(rsa_private_key), 1.4968 + sha, 1.4969 + shaLength); 1.4970 + 1.4971 + if( rv != SECSuccess ) { 1.4972 + fprintf(rsaresp, "ERROR: RSA_HashSign failed"); 1.4973 + goto loser; 1.4974 + } 1.4975 + 1.4976 + /* Output the signature */ 1.4977 + fputs(buf, rsaresp); 1.4978 + to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed); 1.4979 + fprintf(rsaresp, "S = %s\n", buf); 1.4980 + 1.4981 + /* Perform RSA verification with the RSA public key. */ 1.4982 + rv = RSA_HashCheckSign( shaOid, 1.4983 + rsa_public_key, 1.4984 + rsa_computed_signature, 1.4985 + rsa_bytes_signed, 1.4986 + sha, 1.4987 + shaLength); 1.4988 + if( rv != SECSuccess ) { 1.4989 + fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed"); 1.4990 + goto loser; 1.4991 + } 1.4992 + continue; 1.4993 + } 1.4994 + } 1.4995 +loser: 1.4996 + fclose(rsareq); 1.4997 + 1.4998 + if (rsaBlapiPrivKey != NULL) { 1.4999 + /* frees private and public key */ 1.5000 + PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE); 1.5001 + rsaBlapiPrivKey = NULL; 1.5002 + rsaBlapiPublicKey = NULL; 1.5003 + } 1.5004 + 1.5005 +} 1.5006 +/* 1.5007 + * Perform the RSA Signature Verification Test. 1.5008 + * 1.5009 + * reqfn is the pathname of the REQUEST file. 1.5010 + * 1.5011 + * The output RESPONSE file is written to stdout. 1.5012 + */ 1.5013 +void 1.5014 +rsa_sigver_test(char *reqfn) 1.5015 +{ 1.5016 + char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7]; 1.5017 + /* buf holds one line from the input REQUEST file 1.5018 + * or to the output RESPONSE file. 1.5019 + * s = 2x for HEX output + 1 for \n 1.5020 + */ 1.5021 + FILE *rsareq; /* input stream from the REQUEST file */ 1.5022 + FILE *rsaresp; /* output stream to the RESPONSE file */ 1.5023 + int i, j; 1.5024 + unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ 1.5025 + unsigned int shaLength = 0; /* actual length of the digest */ 1.5026 + HASH_HashType shaAlg = HASH_AlgNULL; 1.5027 + SECOidTag shaOid = SEC_OID_UNKNOWN; 1.5028 + int modulus = 0; /* the Modulus size */ 1.5029 + unsigned char signature[513]; /* largest signature size + '\n' */ 1.5030 + unsigned int signatureLength = 0; /* actual length of the signature */ 1.5031 + PRBool keyvalid = PR_TRUE; 1.5032 + 1.5033 + RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */ 1.5034 + 1.5035 + rsareq = fopen(reqfn, "r"); 1.5036 + rsaresp = stdout; 1.5037 + memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey)); 1.5038 + 1.5039 + while (fgets(buf, sizeof buf, rsareq) != NULL) { 1.5040 + /* a comment or blank line */ 1.5041 + if (buf[0] == '#' || buf[0] == '\n') { 1.5042 + fputs(buf, rsaresp); 1.5043 + continue; 1.5044 + } 1.5045 + 1.5046 + /* [Mod = ...] */ 1.5047 + if (buf[0] == '[') { 1.5048 + unsigned int flen; /* length in bytes of the field size */ 1.5049 + 1.5050 + if (rsaBlapiPublicKey.modulus.data) { /* n */ 1.5051 + SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE); 1.5052 + } 1.5053 + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { 1.5054 + goto loser; 1.5055 + } 1.5056 + 1.5057 + if (modulus > RSA_MAX_TEST_MODULUS_BITS) { 1.5058 + fprintf(rsaresp,"ERROR: modulus greater than test maximum\n"); 1.5059 + goto loser; 1.5060 + } 1.5061 + 1.5062 + fputs(buf, rsaresp); 1.5063 + 1.5064 + signatureLength = flen = modulus/8; 1.5065 + 1.5066 + SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen); 1.5067 + if (rsaBlapiPublicKey.modulus.data == NULL) { 1.5068 + goto loser; 1.5069 + } 1.5070 + continue; 1.5071 + } 1.5072 + 1.5073 + /* n = ... modulus */ 1.5074 + if (buf[0] == 'n') { 1.5075 + i = 1; 1.5076 + while (isspace(buf[i]) || buf[i] == '=') { 1.5077 + i++; 1.5078 + } 1.5079 + keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0], 1.5080 + rsaBlapiPublicKey.modulus.len, 1.5081 + &buf[i]); 1.5082 + 1.5083 + if (!keyvalid) { 1.5084 + fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n"); 1.5085 + goto loser; 1.5086 + } 1.5087 + fputs(buf, rsaresp); 1.5088 + continue; 1.5089 + } 1.5090 + 1.5091 + /* SHAAlg = ... */ 1.5092 + if (strncmp(buf, "SHAAlg", 6) == 0) { 1.5093 + i = 6; 1.5094 + while (isspace(buf[i]) || buf[i] == '=') { 1.5095 + i++; 1.5096 + } 1.5097 + /* set the SHA Algorithm */ 1.5098 + if (strncmp(&buf[i], "SHA1", 4) == 0) { 1.5099 + shaAlg = HASH_AlgSHA1; 1.5100 + } else if (strncmp(&buf[i], "SHA224", 6) == 0) { 1.5101 + shaAlg = HASH_AlgSHA224; 1.5102 + } else if (strncmp(&buf[i], "SHA256", 6) == 0) { 1.5103 + shaAlg = HASH_AlgSHA256; 1.5104 + } else if (strncmp(&buf[i], "SHA384", 6) == 0) { 1.5105 + shaAlg = HASH_AlgSHA384; 1.5106 + } else if (strncmp(&buf[i], "SHA512", 6) == 0) { 1.5107 + shaAlg = HASH_AlgSHA512; 1.5108 + } else { 1.5109 + fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); 1.5110 + goto loser; 1.5111 + } 1.5112 + fputs(buf, rsaresp); 1.5113 + continue; 1.5114 + } 1.5115 + 1.5116 + /* e = ... public Key */ 1.5117 + if (buf[0] == 'e') { 1.5118 + unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES]; 1.5119 + unsigned char t; 1.5120 + 1.5121 + memset(data, 0, sizeof data); 1.5122 + 1.5123 + if (rsaBlapiPublicKey.publicExponent.data) { /* e */ 1.5124 + SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE); 1.5125 + } 1.5126 + 1.5127 + i = 1; 1.5128 + while (isspace(buf[i]) || buf[i] == '=') { 1.5129 + i++; 1.5130 + } 1.5131 + /* skip leading zero's */ 1.5132 + while (isxdigit(buf[i])) { 1.5133 + hex_to_byteval(&buf[i], &t); 1.5134 + if (t == 0) { 1.5135 + i+=2; 1.5136 + } else break; 1.5137 + } 1.5138 + 1.5139 + /* get the exponent */ 1.5140 + for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) { 1.5141 + hex_to_byteval(&buf[i], &data[j]); 1.5142 + } 1.5143 + 1.5144 + if (j == 0) { j = 1; } /* to handle 1 byte length exponents */ 1.5145 + 1.5146 + SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j); 1.5147 + if (rsaBlapiPublicKey.publicExponent.data == NULL) { 1.5148 + goto loser; 1.5149 + } 1.5150 + 1.5151 + for (i=0; i < j; i++) { 1.5152 + rsaBlapiPublicKey.publicExponent.data[i] = data[i]; 1.5153 + } 1.5154 + 1.5155 + fputs(buf, rsaresp); 1.5156 + continue; 1.5157 + } 1.5158 + 1.5159 + /* Msg = ... */ 1.5160 + if (strncmp(buf, "Msg", 3) == 0) { 1.5161 + unsigned char msg[128]; /* MAX msg 128 */ 1.5162 + 1.5163 + memset(sha, 0, sizeof sha); 1.5164 + memset(msg, 0, sizeof msg); 1.5165 + 1.5166 + i = 3; 1.5167 + while (isspace(buf[i]) || buf[i] == '=') { 1.5168 + i++; 1.5169 + } 1.5170 + 1.5171 + for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) { 1.5172 + hex_to_byteval(&buf[i], &msg[j]); 1.5173 + } 1.5174 + 1.5175 + shaLength = fips_hashLen(shaAlg); 1.5176 + if (fips_hashBuf(shaAlg,sha,msg,j) != SECSuccess) { 1.5177 + if (shaLength == 0) { 1.5178 + fprintf(rsaresp, "ERROR: SHAAlg not defined."); 1.5179 + } 1.5180 + fprintf(rsaresp, "ERROR: Unable to generate SHA%x", 1.5181 + shaLength == 160 ? 1 : shaLength); 1.5182 + goto loser; 1.5183 + } 1.5184 + 1.5185 + fputs(buf, rsaresp); 1.5186 + continue; 1.5187 + 1.5188 + } 1.5189 + 1.5190 + /* S = ... */ 1.5191 + if (buf[0] == 'S') { 1.5192 + SECStatus rv = SECFailure; 1.5193 + NSSLOWKEYPublicKey * rsa_public_key; 1.5194 + NSSLOWKEYPublicKey low_RSA_public_key = { NULL, 1.5195 + NSSLOWKEYRSAKey, }; 1.5196 + 1.5197 + /* convert to a low RSA public key */ 1.5198 + low_RSA_public_key.u.rsa = rsaBlapiPublicKey; 1.5199 + rsa_public_key = &low_RSA_public_key; 1.5200 + 1.5201 + memset(signature, 0, sizeof(signature)); 1.5202 + i = 1; 1.5203 + while (isspace(buf[i]) || buf[i] == '=') { 1.5204 + i++; 1.5205 + } 1.5206 + 1.5207 + for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) { 1.5208 + hex_to_byteval(&buf[i], &signature[j]); 1.5209 + } 1.5210 + 1.5211 + signatureLength = j; 1.5212 + fputs(buf, rsaresp); 1.5213 + 1.5214 + /* Perform RSA verification with the RSA public key. */ 1.5215 + rv = RSA_HashCheckSign( shaOid, 1.5216 + rsa_public_key, 1.5217 + signature, 1.5218 + signatureLength, 1.5219 + sha, 1.5220 + shaLength); 1.5221 + if( rv == SECSuccess ) { 1.5222 + fputs("Result = P\n", rsaresp); 1.5223 + } else { 1.5224 + fputs("Result = F\n", rsaresp); 1.5225 + } 1.5226 + continue; 1.5227 + } 1.5228 + } 1.5229 +loser: 1.5230 + fclose(rsareq); 1.5231 + if (rsaBlapiPublicKey.modulus.data) { /* n */ 1.5232 + SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE); 1.5233 + } 1.5234 + if (rsaBlapiPublicKey.publicExponent.data) { /* e */ 1.5235 + SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE); 1.5236 + } 1.5237 +} 1.5238 + 1.5239 +int main(int argc, char **argv) 1.5240 +{ 1.5241 + if (argc < 2) exit (-1); 1.5242 + 1.5243 + RNG_RNGInit(); 1.5244 + SECOID_Init(); 1.5245 + 1.5246 + /*************/ 1.5247 + /* TDEA */ 1.5248 + /*************/ 1.5249 + if (strcmp(argv[1], "tdea") == 0) { 1.5250 + /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */ 1.5251 + if (strcmp(argv[2], "kat") == 0) { 1.5252 + /* Known Answer Test (KAT) */ 1.5253 + tdea_kat_mmt(argv[4]); 1.5254 + } else if (strcmp(argv[2], "mmt") == 0) { 1.5255 + /* Multi-block Message Test (MMT) */ 1.5256 + tdea_kat_mmt(argv[4]); 1.5257 + } else if (strcmp(argv[2], "mct") == 0) { 1.5258 + /* Monte Carlo Test (MCT) */ 1.5259 + if (strcmp(argv[3], "ecb") == 0) { 1.5260 + /* ECB mode */ 1.5261 + tdea_mct(NSS_DES_EDE3, argv[4]); 1.5262 + } else if (strcmp(argv[3], "cbc") == 0) { 1.5263 + /* CBC mode */ 1.5264 + tdea_mct(NSS_DES_EDE3_CBC, argv[4]); 1.5265 + } 1.5266 + } 1.5267 + /*************/ 1.5268 + /* AES */ 1.5269 + /*************/ 1.5270 + } else if (strcmp(argv[1], "aes") == 0) { 1.5271 + /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */ 1.5272 + if ( strcmp(argv[2], "kat") == 0) { 1.5273 + /* Known Answer Test (KAT) */ 1.5274 + aes_kat_mmt(argv[4]); 1.5275 + } else if (strcmp(argv[2], "mmt") == 0) { 1.5276 + /* Multi-block Message Test (MMT) */ 1.5277 + aes_kat_mmt(argv[4]); 1.5278 + } else if (strcmp(argv[2], "mct") == 0) { 1.5279 + /* Monte Carlo Test (MCT) */ 1.5280 + if ( strcmp(argv[3], "ecb") == 0) { 1.5281 + /* ECB mode */ 1.5282 + aes_ecb_mct(argv[4]); 1.5283 + } else if (strcmp(argv[3], "cbc") == 0) { 1.5284 + /* CBC mode */ 1.5285 + aes_cbc_mct(argv[4]); 1.5286 + } 1.5287 + } 1.5288 + /*************/ 1.5289 + /* SHA */ 1.5290 + /*************/ 1.5291 + } else if (strcmp(argv[1], "sha") == 0) { 1.5292 + sha_test(argv[2]); 1.5293 + /*************/ 1.5294 + /* RSA */ 1.5295 + /*************/ 1.5296 + } else if (strcmp(argv[1], "rsa") == 0) { 1.5297 + /* argv[2]=siggen|sigver */ 1.5298 + /* argv[3]=<test name>.req */ 1.5299 + if (strcmp(argv[2], "siggen") == 0) { 1.5300 + /* Signature Generation Test */ 1.5301 + rsa_siggen_test(argv[3]); 1.5302 + } else if (strcmp(argv[2], "sigver") == 0) { 1.5303 + /* Signature Verification Test */ 1.5304 + rsa_sigver_test(argv[3]); 1.5305 + } 1.5306 + /*************/ 1.5307 + /* HMAC */ 1.5308 + /*************/ 1.5309 + } else if (strcmp(argv[1], "hmac") == 0) { 1.5310 + hmac_test(argv[2]); 1.5311 + /*************/ 1.5312 + /* DSA */ 1.5313 + /*************/ 1.5314 + } else if (strcmp(argv[1], "dsa") == 0) { 1.5315 + /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */ 1.5316 + /* argv[3]=<test name>.req */ 1.5317 + if (strcmp(argv[2], "keypair") == 0) { 1.5318 + /* Key Pair Generation Test */ 1.5319 + dsa_keypair_test(argv[3]); 1.5320 + } else if (strcmp(argv[2], "pqggen") == 0) { 1.5321 + /* Domain Parameter Generation Test */ 1.5322 + dsa_pqggen_test(argv[3]); 1.5323 + } else if (strcmp(argv[2], "pqgver") == 0) { 1.5324 + /* Domain Parameter Validation Test */ 1.5325 + dsa_pqgver_test(argv[3]); 1.5326 + } else if (strcmp(argv[2], "siggen") == 0) { 1.5327 + /* Signature Generation Test */ 1.5328 + dsa_siggen_test(argv[3]); 1.5329 + } else if (strcmp(argv[2], "sigver") == 0) { 1.5330 + /* Signature Verification Test */ 1.5331 + dsa_sigver_test(argv[3]); 1.5332 + } 1.5333 +#ifndef NSS_DISABLE_ECC 1.5334 + /*************/ 1.5335 + /* ECDSA */ 1.5336 + /*************/ 1.5337 + } else if (strcmp(argv[1], "ecdsa") == 0) { 1.5338 + /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */ 1.5339 + if ( strcmp(argv[2], "keypair") == 0) { 1.5340 + /* Key Pair Generation Test */ 1.5341 + ecdsa_keypair_test(argv[3]); 1.5342 + } else if (strcmp(argv[2], "pkv") == 0) { 1.5343 + /* Public Key Validation Test */ 1.5344 + ecdsa_pkv_test(argv[3]); 1.5345 + } else if (strcmp(argv[2], "siggen") == 0) { 1.5346 + /* Signature Generation Test */ 1.5347 + ecdsa_siggen_test(argv[3]); 1.5348 + } else if (strcmp(argv[2], "sigver") == 0) { 1.5349 + /* Signature Verification Test */ 1.5350 + ecdsa_sigver_test(argv[3]); 1.5351 + } 1.5352 +#endif /* NSS_DISABLE_ECC */ 1.5353 + /*************/ 1.5354 + /* RNG */ 1.5355 + /*************/ 1.5356 + } else if (strcmp(argv[1], "rng") == 0) { 1.5357 + /* argv[2]=vst|mct argv[3]=<test name>.req */ 1.5358 + if ( strcmp(argv[2], "vst") == 0) { 1.5359 + /* Variable Seed Test */ 1.5360 + rng_vst(argv[3]); 1.5361 + } else if (strcmp(argv[2], "mct") == 0) { 1.5362 + /* Monte Carlo Test */ 1.5363 + rng_mct(argv[3]); 1.5364 + } 1.5365 + } else if (strcmp(argv[1], "drbg") == 0) { 1.5366 + /* Variable Seed Test */ 1.5367 + drbg(argv[2]); 1.5368 + } else if (strcmp(argv[1], "ddrbg") == 0) { 1.5369 + debug = 1; 1.5370 + drbg(argv[2]); 1.5371 + } 1.5372 + return 0; 1.5373 +}