1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/sdrtest/sdrtest.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,417 @@ 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 +/* 1.9 + * Test program for SDR (Secret Decoder Ring) functions. 1.10 + */ 1.11 + 1.12 +#include "nspr.h" 1.13 +#include "string.h" 1.14 +#include "nss.h" 1.15 +#include "secutil.h" 1.16 +#include "cert.h" 1.17 +#include "pk11func.h" 1.18 + 1.19 +#include "plgetopt.h" 1.20 +#include "pk11sdr.h" 1.21 +#include "nssb64.h" 1.22 + 1.23 +#define DEFAULT_VALUE "Test" 1.24 +static const char default_value[] = { DEFAULT_VALUE }; 1.25 + 1.26 +PRFileDesc *pr_stderr; 1.27 +PRBool verbose = PR_FALSE; 1.28 + 1.29 +static void 1.30 +synopsis (char *program_name) 1.31 +{ 1.32 + PR_fprintf (pr_stderr, 1.33 +"Usage: %s [<common>] -i <input-file>\n" 1.34 +" %s [<common>] -o <output-file>\n" 1.35 +" <common> [-d dir] [-v] [-t text] [-a] [-f pwfile | -p pwd]\n", 1.36 + program_name, program_name); 1.37 +} 1.38 + 1.39 +static void 1.40 +short_usage (char *program_name) 1.41 +{ 1.42 + PR_fprintf (pr_stderr, 1.43 + "Type %s -H for more detailed descriptions\n", 1.44 + program_name); 1.45 + synopsis (program_name); 1.46 +} 1.47 + 1.48 + 1.49 +static void 1.50 +long_usage (char *program_name) 1.51 +{ 1.52 + synopsis (program_name); 1.53 + PR_fprintf (pr_stderr, "\nSecret Decoder Test:\n"); 1.54 + PR_fprintf (pr_stderr, 1.55 + " %-13s Read encrypted data from \"file\"\n", 1.56 + "-i file"); 1.57 + PR_fprintf (pr_stderr, 1.58 + " %-13s Write newly generated encrypted data to \"file\"\n", 1.59 + "-o file"); 1.60 + PR_fprintf (pr_stderr, 1.61 + " %-13s Use \"text\" as the plaintext for encryption and verification\n", 1.62 + "-t text"); 1.63 + PR_fprintf (pr_stderr, 1.64 + " %-13s Find security databases in \"dbdir\"\n", 1.65 + "-d dbdir"); 1.66 + PR_fprintf (pr_stderr, 1.67 + " %-13s read the password from \"pwfile\"\n", 1.68 + "-f pwfile"); 1.69 + PR_fprintf (pr_stderr, 1.70 + " %-13s supply \"password\" on the command line\n", 1.71 + "-p password"); 1.72 +} 1.73 + 1.74 +int 1.75 +readStdin(SECItem * result) 1.76 +{ 1.77 + int bufsize = 0; 1.78 + int cc; 1.79 + int wanted = 8192; 1.80 + 1.81 + result->len = 0; 1.82 + result->data = NULL; 1.83 + do { 1.84 + if (bufsize < wanted) { 1.85 + unsigned char * tmpData = (unsigned char *)PR_Realloc(result->data, wanted); 1.86 + if (!tmpData) { 1.87 + if (verbose) PR_fprintf(pr_stderr, "Allocation of buffer failed\n"); 1.88 + return -1; 1.89 + } 1.90 + result->data = tmpData; 1.91 + bufsize = wanted; 1.92 + } 1.93 + cc = PR_Read(PR_STDIN, result->data + result->len, bufsize - result->len); 1.94 + if (cc > 0) { 1.95 + result->len += (unsigned)cc; 1.96 + if (result->len >= wanted) 1.97 + wanted *= 2; 1.98 + } 1.99 + } while (cc > 0); 1.100 + return cc; 1.101 +} 1.102 + 1.103 +int 1.104 +readInputFile(const char * filename, SECItem * result) 1.105 +{ 1.106 + PRFileDesc *file /* = PR_OpenFile(input_file, 0) */; 1.107 + PRFileInfo info; 1.108 + PRStatus s; 1.109 + PRInt32 count; 1.110 + int retval = -1; 1.111 + 1.112 + file = PR_Open(filename, PR_RDONLY, 0); 1.113 + if (!file) { 1.114 + if (verbose) PR_fprintf(pr_stderr, "Open of file %s failed\n", filename); 1.115 + goto loser; 1.116 + } 1.117 + 1.118 + s = PR_GetOpenFileInfo(file, &info); 1.119 + if (s != PR_SUCCESS) { 1.120 + if (verbose) PR_fprintf(pr_stderr, "File info operation failed\n"); 1.121 + goto file_loser; 1.122 + } 1.123 + 1.124 + result->len = info.size; 1.125 + result->data = (unsigned char *)PR_Malloc(result->len); 1.126 + if (!result->data) { 1.127 + if (verbose) PR_fprintf(pr_stderr, "Allocation of buffer failed\n"); 1.128 + goto file_loser; 1.129 + } 1.130 + 1.131 + count = PR_Read(file, result->data, result->len); 1.132 + if (count != result->len) { 1.133 + if (verbose) PR_fprintf(pr_stderr, "Read failed\n"); 1.134 + goto file_loser; 1.135 + } 1.136 + retval = 0; 1.137 + 1.138 +file_loser: 1.139 + PR_Close(file); 1.140 +loser: 1.141 + return retval; 1.142 +} 1.143 + 1.144 +int 1.145 +main (int argc, char **argv) 1.146 +{ 1.147 + int retval = 0; /* 0 - test succeeded. -1 - test failed */ 1.148 + SECStatus rv; 1.149 + PLOptState *optstate; 1.150 + PLOptStatus optstatus; 1.151 + char *program_name; 1.152 + const char *input_file = NULL; /* read encrypted data from here (or create) */ 1.153 + const char *output_file = NULL; /* write new encrypted data here */ 1.154 + const char *value = default_value; /* Use this for plaintext */ 1.155 + SECItem data; 1.156 + SECItem result = {0, 0, 0}; 1.157 + SECItem text; 1.158 + PRBool ascii = PR_FALSE; 1.159 + secuPWData pwdata = { PW_NONE, 0 }; 1.160 + 1.161 + pr_stderr = PR_STDERR; 1.162 + result.data = 0; 1.163 + text.data = 0; text.len = 0; 1.164 + 1.165 + program_name = PL_strrchr(argv[0], '/'); 1.166 + program_name = program_name ? (program_name + 1) : argv[0]; 1.167 + 1.168 + optstate = PL_CreateOptState (argc, argv, "?Had:i:o:t:vf:p:"); 1.169 + if (optstate == NULL) { 1.170 + SECU_PrintError (program_name, "PL_CreateOptState failed"); 1.171 + return -1; 1.172 + } 1.173 + 1.174 + while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.175 + switch (optstate->option) { 1.176 + case '?': 1.177 + short_usage (program_name); 1.178 + return retval; 1.179 + 1.180 + case 'H': 1.181 + long_usage (program_name); 1.182 + return retval; 1.183 + 1.184 + case 'a': 1.185 + ascii = PR_TRUE; 1.186 + break; 1.187 + 1.188 + case 'd': 1.189 + SECU_ConfigDirectory(optstate->value); 1.190 + break; 1.191 + 1.192 + case 'i': 1.193 + input_file = optstate->value; 1.194 + break; 1.195 + 1.196 + case 'o': 1.197 + output_file = optstate->value; 1.198 + break; 1.199 + 1.200 + case 't': 1.201 + value = optstate->value; 1.202 + break; 1.203 + 1.204 + case 'f': 1.205 + if (pwdata.data) { 1.206 + PORT_Free(pwdata.data); 1.207 + short_usage(program_name); 1.208 + return -1; 1.209 + } 1.210 + pwdata.source = PW_FROMFILE; 1.211 + pwdata.data = PORT_Strdup(optstate->value); 1.212 + break; 1.213 + 1.214 + case 'p': 1.215 + if (pwdata.data) { 1.216 + PORT_Free(pwdata.data); 1.217 + short_usage(program_name); 1.218 + return -1; 1.219 + } 1.220 + pwdata.source = PW_PLAINTEXT; 1.221 + pwdata.data = PORT_Strdup(optstate->value); 1.222 + break; 1.223 + 1.224 + case 'v': 1.225 + verbose = PR_TRUE; 1.226 + break; 1.227 + } 1.228 + } 1.229 + PL_DestroyOptState(optstate); 1.230 + if (optstatus == PL_OPT_BAD) { 1.231 + short_usage (program_name); 1.232 + return -1; 1.233 + } 1.234 + if (!output_file && !input_file && value == default_value) { 1.235 + short_usage (program_name); 1.236 + PR_fprintf (pr_stderr, "Must specify at least one of -t, -i or -o \n"); 1.237 + return -1; 1.238 + } 1.239 + 1.240 + /* 1.241 + * Initialize the Security libraries. 1.242 + */ 1.243 + PK11_SetPasswordFunc(SECU_GetModulePassword); 1.244 + 1.245 + if (output_file) { 1.246 + rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL)); 1.247 + } else { 1.248 + rv = NSS_Init(SECU_ConfigDirectory(NULL)); 1.249 + } 1.250 + if (rv != SECSuccess) { 1.251 + SECU_PrintError(program_name, "NSS_Init failed"); 1.252 + retval = -1; 1.253 + goto prdone; 1.254 + } 1.255 + 1.256 + /* Convert value into an item */ 1.257 + data.data = (unsigned char *)value; 1.258 + data.len = strlen(value); 1.259 + 1.260 + /* Get the encrypted result, either from the input file 1.261 + * or from encrypting the plaintext value 1.262 + */ 1.263 + if (input_file) 1.264 + { 1.265 + if (verbose) printf("Reading data from %s\n", input_file); 1.266 + 1.267 + if (!strcmp(input_file, "-")) { 1.268 + retval = readStdin(&result); 1.269 + ascii = PR_TRUE; 1.270 + } else { 1.271 + retval = readInputFile(input_file, &result); 1.272 + } 1.273 + if (retval != 0) 1.274 + goto loser; 1.275 + if (ascii) { 1.276 + /* input was base64 encoded. Decode it. */ 1.277 + SECItem newResult = {0, 0, 0}; 1.278 + SECItem *ok = NSSBase64_DecodeBuffer(NULL, &newResult, 1.279 + (const char *)result.data, result.len); 1.280 + if (!ok) { 1.281 + SECU_PrintError(program_name, "Base 64 decode failed"); 1.282 + retval = -1; 1.283 + goto loser; 1.284 + } 1.285 + SECITEM_ZfreeItem(&result, PR_FALSE); 1.286 + result = *ok; 1.287 + } 1.288 + } 1.289 + else 1.290 + { 1.291 + SECItem keyid = { 0, 0, 0 }; 1.292 + SECItem outBuf = { 0, 0, 0 }; 1.293 + PK11SlotInfo *slot = NULL; 1.294 + 1.295 + /* sigh, initialize the key database */ 1.296 + slot = PK11_GetInternalKeySlot(); 1.297 + if (slot && PK11_NeedUserInit(slot)) { 1.298 + switch (pwdata.source) { 1.299 + case PW_FROMFILE: 1.300 + rv = SECU_ChangePW(slot, 0, pwdata.data); 1.301 + break; 1.302 + case PW_PLAINTEXT: 1.303 + rv = SECU_ChangePW(slot, pwdata.data, 0); 1.304 + break; 1.305 + default: 1.306 + rv = SECU_ChangePW(slot, "", 0); 1.307 + break; 1.308 + } 1.309 + if (rv != SECSuccess) { 1.310 + SECU_PrintError(program_name, "Failed to initialize slot \"%s\"", 1.311 + PK11_GetSlotName(slot)); 1.312 + return SECFailure; 1.313 + } 1.314 + } 1.315 + if (slot) { 1.316 + PK11_FreeSlot(slot); 1.317 + } 1.318 + 1.319 + rv = PK11SDR_Encrypt(&keyid, &data, &result, &pwdata); 1.320 + if (rv != SECSuccess) { 1.321 + if (verbose) 1.322 + SECU_PrintError(program_name, "Encrypt operation failed\n"); 1.323 + retval = -1; 1.324 + goto loser; 1.325 + } 1.326 + 1.327 + if (verbose) printf("Encrypted result is %d bytes long\n", result.len); 1.328 + 1.329 + if (!strcmp(output_file, "-")) { 1.330 + ascii = PR_TRUE; 1.331 + } 1.332 + 1.333 + if (ascii) { 1.334 + /* base64 encode output. */ 1.335 + char * newResult = NSSBase64_EncodeItem(NULL, NULL, 0, &result); 1.336 + if (!newResult) { 1.337 + SECU_PrintError(program_name, "Base 64 encode failed\n"); 1.338 + retval = -1; 1.339 + goto loser; 1.340 + } 1.341 + outBuf.data = (unsigned char *)newResult; 1.342 + outBuf.len = strlen(newResult); 1.343 + if (verbose) 1.344 + printf("Base 64 encoded result is %d bytes long\n", outBuf.len); 1.345 + } else { 1.346 + outBuf = result; 1.347 + } 1.348 + 1.349 + /* -v printf("Result is %.*s\n", text.len, text.data); */ 1.350 + if (output_file) { 1.351 + PRFileDesc *file; 1.352 + PRInt32 count; 1.353 + 1.354 + if (verbose) printf("Writing result to %s\n", output_file); 1.355 + if (!strcmp(output_file, "-")) { 1.356 + file = PR_STDOUT; 1.357 + } else { 1.358 + /* Write to file */ 1.359 + file = PR_Open(output_file, PR_CREATE_FILE|PR_WRONLY, 0666); 1.360 + } 1.361 + if (!file) { 1.362 + if (verbose) 1.363 + SECU_PrintError(program_name, 1.364 + "Open of output file %s failed\n", 1.365 + output_file); 1.366 + retval = -1; 1.367 + goto loser; 1.368 + } 1.369 + 1.370 + count = PR_Write(file, outBuf.data, outBuf.len); 1.371 + 1.372 + if (file == PR_STDOUT) { 1.373 + puts(""); 1.374 + } else { 1.375 + PR_Close(file); 1.376 + } 1.377 + 1.378 + if (count != outBuf.len) { 1.379 + if (verbose) SECU_PrintError(program_name, "Write failed\n"); 1.380 + retval = -1; 1.381 + goto loser; 1.382 + } 1.383 + if (ascii) { 1.384 + free(outBuf.data); 1.385 + } 1.386 + } 1.387 + } 1.388 + 1.389 + /* Decrypt the value */ 1.390 + rv = PK11SDR_Decrypt(&result, &text, &pwdata); 1.391 + if (rv != SECSuccess) { 1.392 + if (verbose) SECU_PrintError(program_name, "Decrypt operation failed\n"); 1.393 + retval = -1; 1.394 + goto loser; 1.395 + } 1.396 + 1.397 + if (verbose) printf("Decrypted result is \"%.*s\"\n", text.len, text.data); 1.398 + 1.399 + /* Compare to required value */ 1.400 + if (text.len != data.len || memcmp(data.data, text.data, text.len) != 0) 1.401 + { 1.402 + if (verbose) PR_fprintf(pr_stderr, "Comparison failed\n"); 1.403 + retval = -1; 1.404 + goto loser; 1.405 + } 1.406 + 1.407 +loser: 1.408 + if (text.data) SECITEM_ZfreeItem(&text, PR_FALSE); 1.409 + if (result.data) SECITEM_ZfreeItem(&result, PR_FALSE); 1.410 + if (NSS_Shutdown() != SECSuccess) { 1.411 + exit(1); 1.412 + } 1.413 + 1.414 +prdone: 1.415 + PR_Cleanup (); 1.416 + if (pwdata.data) { 1.417 + PORT_Free(pwdata.data); 1.418 + } 1.419 + return retval; 1.420 +}