nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / cmd / sdrtest / sdrtest.c
blob35199dadb3c188212cdec428009cd89778c9416c
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * Test program for SDR (Secret Decoder Ring) functions.
40 * $Id: sdrtest.c,v 1.14 2008/03/10 20:16:44 rrelyea%redhat.com Exp $
43 #include "nspr.h"
44 #include "string.h"
45 #include "nss.h"
46 #include "secutil.h"
47 #include "cert.h"
48 #include "pk11func.h"
50 #include "plgetopt.h"
51 #include "pk11sdr.h"
52 #include "nssb64.h"
54 #define DEFAULT_VALUE "Test"
55 static const char default_value[] = { DEFAULT_VALUE };
57 PRFileDesc *pr_stderr;
58 PRBool verbose = PR_FALSE;
60 static void
61 synopsis (char *program_name)
63 PR_fprintf (pr_stderr,
64 "Usage: %s [<common>] -i <input-file>\n"
65 " %s [<common>] -o <output-file>\n"
66 " <common> [-d dir] [-v] [-t text] [-a] [-f pwfile | -p pwd]\n",
67 program_name, program_name);
70 static void
71 short_usage (char *program_name)
73 PR_fprintf (pr_stderr,
74 "Type %s -H for more detailed descriptions\n",
75 program_name);
76 synopsis (program_name);
80 static void
81 long_usage (char *program_name)
83 synopsis (program_name);
84 PR_fprintf (pr_stderr, "\nSecret Decoder Test:\n");
85 PR_fprintf (pr_stderr,
86 " %-13s Read encrypted data from \"file\"\n",
87 "-i file");
88 PR_fprintf (pr_stderr,
89 " %-13s Write newly generated encrypted data to \"file\"\n",
90 "-o file");
91 PR_fprintf (pr_stderr,
92 " %-13s Use \"text\" as the plaintext for encryption and verification\n",
93 "-t text");
94 PR_fprintf (pr_stderr,
95 " %-13s Find security databases in \"dbdir\"\n",
96 "-d dbdir");
97 PR_fprintf (pr_stderr,
98 " %-13s read the password from \"pwfile\"\n",
99 "-f pwfile");
100 PR_fprintf (pr_stderr,
101 " %-13s supply \"password\" on the command line\n",
102 "-p password");
105 int
106 readStdin(SECItem * result)
108 int bufsize = 0;
109 int cc;
110 int wanted = 8192;
112 result->len = 0;
113 result->data = NULL;
114 do {
115 if (bufsize < wanted) {
116 unsigned char * tmpData = (unsigned char *)realloc(result->data, wanted);
117 if (!tmpData) {
118 if (verbose) PR_fprintf(pr_stderr, "Allocation of buffer failed\n");
119 return -1;
121 result->data = tmpData;
122 bufsize = wanted;
124 cc = PR_Read(PR_STDIN, result->data + result->len, bufsize - result->len);
125 if (cc > 0) {
126 result->len += (unsigned)cc;
127 if (result->len >= wanted)
128 wanted *= 2;
130 } while (cc > 0);
131 return cc;
135 readInputFile(const char * filename, SECItem * result)
137 PRFileDesc *file /* = PR_OpenFile(input_file, 0) */;
138 PRFileInfo info;
139 PRStatus s;
140 PRInt32 count;
141 int retval = -1;
143 file = PR_Open(filename, PR_RDONLY, 0);
144 if (!file) {
145 if (verbose) PR_fprintf(pr_stderr, "Open of file %s failed\n", filename);
146 goto loser;
149 s = PR_GetOpenFileInfo(file, &info);
150 if (s != PR_SUCCESS) {
151 if (verbose) PR_fprintf(pr_stderr, "File info operation failed\n");
152 goto file_loser;
155 result->len = info.size;
156 result->data = (unsigned char *)malloc(result->len);
157 if (!result->data) {
158 if (verbose) PR_fprintf(pr_stderr, "Allocation of buffer failed\n");
159 goto file_loser;
162 count = PR_Read(file, result->data, result->len);
163 if (count != result->len) {
164 if (verbose) PR_fprintf(pr_stderr, "Read failed\n");
165 goto file_loser;
167 retval = 0;
169 file_loser:
170 PR_Close(file);
171 loser:
172 return retval;
176 main (int argc, char **argv)
178 int retval = 0; /* 0 - test succeeded. -1 - test failed */
179 SECStatus rv;
180 PLOptState *optstate;
181 PLOptStatus optstatus;
182 char *program_name;
183 const char *input_file = NULL; /* read encrypted data from here (or create) */
184 const char *output_file = NULL; /* write new encrypted data here */
185 const char *value = default_value; /* Use this for plaintext */
186 SECItem data;
187 SECItem result = {0, 0, 0};
188 SECItem text;
189 PRBool ascii = PR_FALSE;
190 secuPWData pwdata = { PW_NONE, 0 };
192 pr_stderr = PR_STDERR;
193 result.data = 0;
194 text.data = 0; text.len = 0;
196 program_name = PL_strrchr(argv[0], '/');
197 program_name = program_name ? (program_name + 1) : argv[0];
199 optstate = PL_CreateOptState (argc, argv, "?Had:i:o:t:vf:p:");
200 if (optstate == NULL) {
201 SECU_PrintError (program_name, "PL_CreateOptState failed");
202 return -1;
205 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
206 switch (optstate->option) {
207 case '?':
208 short_usage (program_name);
209 return retval;
211 case 'H':
212 long_usage (program_name);
213 return retval;
215 case 'a':
216 ascii = PR_TRUE;
217 break;
219 case 'd':
220 SECU_ConfigDirectory(optstate->value);
221 break;
223 case 'i':
224 input_file = optstate->value;
225 break;
227 case 'o':
228 output_file = optstate->value;
229 break;
231 case 't':
232 value = optstate->value;
233 break;
235 case 'f':
236 if (pwdata.data) {
237 PORT_Free(pwdata.data);
238 short_usage(program_name);
239 return -1;
241 pwdata.source = PW_FROMFILE;
242 pwdata.data = PORT_Strdup(optstate->value);
243 break;
245 case 'p':
246 if (pwdata.data) {
247 PORT_Free(pwdata.data);
248 short_usage(program_name);
249 return -1;
251 pwdata.source = PW_PLAINTEXT;
252 pwdata.data = PORT_Strdup(optstate->value);
253 break;
255 case 'v':
256 verbose = PR_TRUE;
257 break;
260 PL_DestroyOptState(optstate);
261 if (optstatus == PL_OPT_BAD) {
262 short_usage (program_name);
263 return -1;
265 if (!output_file && !input_file && value == default_value) {
266 short_usage (program_name);
267 PR_fprintf (pr_stderr, "Must specify at least one of -t, -i or -o \n");
268 return -1;
272 * Initialize the Security libraries.
274 PK11_SetPasswordFunc(SECU_GetModulePassword);
276 if (output_file) {
277 rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
278 } else {
279 rv = NSS_Init(SECU_ConfigDirectory(NULL));
281 if (rv != SECSuccess) {
282 SECU_PrintError(program_name, "NSS_Init failed");
283 retval = -1;
284 goto prdone;
287 /* Convert value into an item */
288 data.data = (unsigned char *)value;
289 data.len = strlen(value);
291 /* Get the encrypted result, either from the input file
292 * or from encrypting the plaintext value
294 if (input_file)
296 if (verbose) printf("Reading data from %s\n", input_file);
298 if (!strcmp(input_file, "-")) {
299 retval = readStdin(&result);
300 ascii = PR_TRUE;
301 } else {
302 retval = readInputFile(input_file, &result);
304 if (retval != 0)
305 goto loser;
306 if (ascii) {
307 /* input was base64 encoded. Decode it. */
308 SECItem newResult = {0, 0, 0};
309 SECItem *ok = NSSBase64_DecodeBuffer(NULL, &newResult,
310 (const char *)result.data, result.len);
311 if (!ok) {
312 SECU_PrintError(program_name, "Base 64 decode failed");
313 retval = -1;
314 goto loser;
316 free(result.data);
317 result = *ok;
320 else
322 SECItem keyid = { 0, 0, 0 };
323 SECItem outBuf = { 0, 0, 0 };
324 PK11SlotInfo *slot = NULL;
326 /* sigh, initialize the key database */
327 slot = PK11_GetInternalKeySlot();
328 if (slot && PK11_NeedUserInit(slot)) {
329 switch (pwdata.source) {
330 case PW_FROMFILE:
331 rv = SECU_ChangePW(slot, 0, pwdata.data);
332 break;
333 case PW_PLAINTEXT:
334 rv = SECU_ChangePW(slot, pwdata.data, 0);
335 break;
336 default:
337 rv = SECU_ChangePW(slot, "", 0);
338 break;
340 if (rv != SECSuccess) {
341 SECU_PrintError(program_name, "Failed to initialize slot \"%s\"",
342 PK11_GetSlotName(slot));
343 return SECFailure;
346 if (slot) {
347 PK11_FreeSlot(slot);
350 rv = PK11SDR_Encrypt(&keyid, &data, &result, &pwdata);
351 if (rv != SECSuccess) {
352 if (verbose)
353 SECU_PrintError(program_name, "Encrypt operation failed\n");
354 retval = -1;
355 goto loser;
358 if (verbose) printf("Encrypted result is %d bytes long\n", result.len);
360 if (!strcmp(output_file, "-")) {
361 ascii = PR_TRUE;
364 if (ascii) {
365 /* base64 encode output. */
366 char * newResult = NSSBase64_EncodeItem(NULL, NULL, 0, &result);
367 if (!newResult) {
368 SECU_PrintError(program_name, "Base 64 encode failed\n");
369 retval = -1;
370 goto loser;
372 outBuf.data = (unsigned char *)newResult;
373 outBuf.len = strlen(newResult);
374 if (verbose)
375 printf("Base 64 encoded result is %d bytes long\n", outBuf.len);
376 } else {
377 outBuf = result;
380 /* -v printf("Result is %.*s\n", text.len, text.data); */
381 if (output_file) {
382 PRFileDesc *file;
383 PRInt32 count;
385 if (verbose) printf("Writing result to %s\n", output_file);
386 if (!strcmp(output_file, "-")) {
387 file = PR_STDOUT;
388 } else {
389 /* Write to file */
390 file = PR_Open(output_file, PR_CREATE_FILE|PR_WRONLY, 0666);
392 if (!file) {
393 if (verbose)
394 SECU_PrintError(program_name,
395 "Open of output file %s failed\n",
396 output_file);
397 retval = -1;
398 goto loser;
401 count = PR_Write(file, outBuf.data, outBuf.len);
403 if (file == PR_STDOUT) {
404 puts("");
405 } else {
406 PR_Close(file);
409 if (count != outBuf.len) {
410 if (verbose) SECU_PrintError(program_name, "Write failed\n");
411 retval = -1;
412 goto loser;
414 if (ascii) {
415 free(outBuf.data);
420 /* Decrypt the value */
421 rv = PK11SDR_Decrypt(&result, &text, &pwdata);
422 if (rv != SECSuccess) {
423 if (verbose) SECU_PrintError(program_name, "Decrypt operation failed\n");
424 retval = -1;
425 goto loser;
428 if (verbose) printf("Decrypted result is \"%.*s\"\n", text.len, text.data);
430 /* Compare to required value */
431 if (text.len != data.len || memcmp(data.data, text.data, text.len) != 0)
433 if (verbose) PR_fprintf(pr_stderr, "Comparison failed\n");
434 retval = -1;
435 goto loser;
438 loser:
439 if (text.data) free(text.data);
440 if (result.data) free(result.data);
441 if (NSS_Shutdown() != SECSuccess) {
442 exit(1);
445 prdone:
446 PR_Cleanup ();
447 if (pwdata.data) {
448 PORT_Free(pwdata.data);
450 return retval;