security/nss/cmd/sdrtest/sdrtest.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  * Test program for SDR (Secret Decoder Ring) functions.
     7  */
     9 #include "nspr.h"
    10 #include "string.h"
    11 #include "nss.h"
    12 #include "secutil.h"
    13 #include "cert.h"
    14 #include "pk11func.h"
    16 #include "plgetopt.h"
    17 #include "pk11sdr.h"
    18 #include "nssb64.h"
    20 #define DEFAULT_VALUE "Test"
    21 static const char default_value[] = { DEFAULT_VALUE };
    23 PRFileDesc *pr_stderr;
    24 PRBool      verbose = PR_FALSE;
    26 static void
    27 synopsis (char *program_name)
    28 {
    29     PR_fprintf (pr_stderr, 
    30 "Usage: %s [<common>] -i <input-file>\n"
    31 "       %s [<common>]  -o <output-file>\n"
    32 "       <common> [-d dir] [-v] [-t text] [-a] [-f pwfile | -p pwd]\n",
    33 	program_name, program_name);
    34 }
    36 static void
    37 short_usage (char *program_name)
    38 {
    39     PR_fprintf (pr_stderr,
    40 		"Type %s -H for more detailed descriptions\n",
    41 		program_name);
    42     synopsis (program_name);
    43 }
    46 static void
    47 long_usage (char *program_name)
    48 {
    49     synopsis (program_name);
    50     PR_fprintf (pr_stderr, "\nSecret Decoder Test:\n");
    51     PR_fprintf (pr_stderr,
    52 		"  %-13s Read encrypted data from \"file\"\n",
    53 		"-i file");
    54     PR_fprintf (pr_stderr,
    55 		"  %-13s Write newly generated encrypted data to \"file\"\n",
    56 		"-o file");
    57     PR_fprintf (pr_stderr,
    58 		"  %-13s Use \"text\" as the plaintext for encryption and verification\n",
    59 		"-t text");
    60     PR_fprintf (pr_stderr,
    61 		"  %-13s Find security databases in \"dbdir\"\n",
    62 		"-d dbdir");
    63     PR_fprintf (pr_stderr,
    64 		"  %-13s read the password from \"pwfile\"\n",
    65 		"-f pwfile");
    66     PR_fprintf (pr_stderr,
    67 		"  %-13s supply \"password\" on the command line\n",
    68 		"-p password");
    69 }
    71 int 
    72 readStdin(SECItem * result)
    73 {
    74   int bufsize = 0;
    75   int cc;
    76   int wanted  = 8192;
    78   result->len = 0;
    79   result->data = NULL;
    80   do {
    81     if (bufsize < wanted) {
    82       unsigned char * tmpData = (unsigned char *)PR_Realloc(result->data, wanted);
    83       if (!tmpData) {
    84 	if (verbose) PR_fprintf(pr_stderr, "Allocation of buffer failed\n");
    85 	return -1;
    86       }
    87       result->data = tmpData;
    88       bufsize = wanted;
    89     }
    90     cc = PR_Read(PR_STDIN, result->data + result->len, bufsize - result->len);
    91     if (cc > 0) {
    92       result->len += (unsigned)cc;
    93       if (result->len >= wanted) 
    94         wanted *= 2;
    95     }
    96   } while (cc > 0);
    97   return cc;
    98 }
   100 int
   101 readInputFile(const char * filename, SECItem * result)
   102 {
   103   PRFileDesc *file /* = PR_OpenFile(input_file, 0) */;
   104   PRFileInfo info;
   105   PRStatus s;
   106   PRInt32 count;
   107   int retval = -1;
   109   file = PR_Open(filename, PR_RDONLY, 0);
   110   if (!file) {
   111     if (verbose) PR_fprintf(pr_stderr, "Open of file %s failed\n", filename);
   112     goto loser;
   113   }
   115   s = PR_GetOpenFileInfo(file, &info);
   116   if (s != PR_SUCCESS) {
   117     if (verbose) PR_fprintf(pr_stderr, "File info operation failed\n");
   118     goto file_loser;
   119   }
   121   result->len = info.size;
   122   result->data = (unsigned char *)PR_Malloc(result->len);
   123   if (!result->data) {
   124     if (verbose) PR_fprintf(pr_stderr, "Allocation of buffer failed\n");
   125     goto file_loser;
   126   }
   128   count = PR_Read(file, result->data, result->len);
   129   if (count != result->len) {
   130     if (verbose) PR_fprintf(pr_stderr, "Read failed\n");
   131     goto file_loser;
   132   }
   133   retval = 0;
   135 file_loser:
   136   PR_Close(file);
   137 loser:
   138   return retval;
   139 }
   141 int
   142 main (int argc, char **argv)
   143 {
   144     int		 retval = 0;  /* 0 - test succeeded.  -1 - test failed */
   145     SECStatus	 rv;
   146     PLOptState	*optstate;
   147     PLOptStatus  optstatus;
   148     char	*program_name;
   149     const char  *input_file = NULL; 	/* read encrypted data from here (or create) */
   150     const char  *output_file = NULL;	/* write new encrypted data here */
   151     const char  *value = default_value;	/* Use this for plaintext */
   152     SECItem     data;
   153     SECItem     result = {0, 0, 0};
   154     SECItem     text;
   155     PRBool      ascii = PR_FALSE;
   156     secuPWData  pwdata = { PW_NONE, 0 };
   158     pr_stderr = PR_STDERR;
   159     result.data = 0;
   160     text.data = 0; text.len = 0;
   162     program_name = PL_strrchr(argv[0], '/');
   163     program_name = program_name ? (program_name + 1) : argv[0];
   165     optstate = PL_CreateOptState (argc, argv, "?Had:i:o:t:vf:p:");
   166     if (optstate == NULL) {
   167 	SECU_PrintError (program_name, "PL_CreateOptState failed");
   168 	return -1;
   169     }
   171     while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   172 	switch (optstate->option) {
   173 	  case '?':
   174 	    short_usage (program_name);
   175 	    return retval;
   177 	  case 'H':
   178 	    long_usage (program_name);
   179 	    return retval;
   181 	  case 'a':
   182 	    ascii = PR_TRUE;
   183 	    break;
   185 	  case 'd':
   186 	    SECU_ConfigDirectory(optstate->value);
   187 	    break;
   189           case 'i':
   190             input_file = optstate->value;
   191             break;
   193           case 'o':
   194             output_file = optstate->value;
   195             break;
   197           case 't':
   198             value = optstate->value;
   199             break;
   201 	  case 'f':
   202 	    if (pwdata.data) {
   203 		PORT_Free(pwdata.data);
   204 		short_usage(program_name);
   205 		return -1;
   206 	    }
   207 	    pwdata.source = PW_FROMFILE;
   208 	    pwdata.data = PORT_Strdup(optstate->value);
   209 	    break;
   211 	  case 'p':
   212 	    if (pwdata.data) {
   213 		PORT_Free(pwdata.data);
   214 		short_usage(program_name);
   215 		return -1;
   216 	    }
   217 	    pwdata.source = PW_PLAINTEXT;
   218 	    pwdata.data = PORT_Strdup(optstate->value);
   219 	    break;
   221           case 'v':
   222             verbose = PR_TRUE;
   223             break;
   224 	}
   225     }
   226     PL_DestroyOptState(optstate);
   227     if (optstatus == PL_OPT_BAD) {
   228 	short_usage (program_name);
   229 	return -1;
   230     }
   231     if (!output_file && !input_file && value == default_value) {
   232 	short_usage (program_name);
   233 	PR_fprintf (pr_stderr, "Must specify at least one of -t, -i or -o \n");
   234 	return -1;
   235     }
   237     /*
   238      * Initialize the Security libraries.
   239      */
   240     PK11_SetPasswordFunc(SECU_GetModulePassword);
   242     if (output_file) {
   243 	rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
   244     } else {
   245 	rv = NSS_Init(SECU_ConfigDirectory(NULL));
   246     }
   247     if (rv != SECSuccess) {
   248 	SECU_PrintError(program_name, "NSS_Init failed");
   249 	retval = -1;
   250 	goto prdone;
   251     }
   253     /* Convert value into an item */
   254     data.data = (unsigned char *)value;
   255     data.len = strlen(value);
   257     /* Get the encrypted result, either from the input file
   258      * or from encrypting the plaintext value
   259      */
   260     if (input_file)
   261     {
   262       if (verbose) printf("Reading data from %s\n", input_file);
   264       if (!strcmp(input_file, "-")) {
   265 	retval = readStdin(&result);
   266         ascii = PR_TRUE;
   267       } else {
   268         retval = readInputFile(input_file, &result);
   269       }
   270       if (retval != 0) 
   271 	goto loser;
   272       if (ascii) {
   273 	/* input was base64 encoded.  Decode it. */
   274 	SECItem newResult = {0, 0, 0};
   275 	SECItem *ok = NSSBase64_DecodeBuffer(NULL, &newResult, 
   276 	                       (const char *)result.data, result.len);
   277 	if (!ok) {
   278 	  SECU_PrintError(program_name, "Base 64 decode failed");
   279 	  retval = -1;
   280 	  goto loser;
   281 	}
   282 	SECITEM_ZfreeItem(&result, PR_FALSE);
   283 	result = *ok;
   284       }
   285     }
   286     else
   287     {
   288       SECItem keyid = { 0, 0, 0 };
   289       SECItem outBuf = { 0, 0, 0 };
   290       PK11SlotInfo *slot = NULL;
   292       /* sigh, initialize the key database */
   293       slot = PK11_GetInternalKeySlot();
   294       if (slot && PK11_NeedUserInit(slot)) {
   295 	switch (pwdata.source) {
   296 	case PW_FROMFILE:
   297 	    rv = SECU_ChangePW(slot, 0, pwdata.data);
   298 	    break;
   299 	case PW_PLAINTEXT:
   300 	    rv = SECU_ChangePW(slot, pwdata.data, 0);
   301 	    break;
   302 	default:
   303             rv = SECU_ChangePW(slot, "", 0);
   304 	    break;
   305 	}
   306         if (rv != SECSuccess) {
   307             SECU_PrintError(program_name, "Failed to initialize slot \"%s\"",
   308                                     PK11_GetSlotName(slot));
   309             return SECFailure;
   310         }
   311       }
   312       if (slot) {
   313 	PK11_FreeSlot(slot);
   314       }
   316       rv = PK11SDR_Encrypt(&keyid, &data, &result, &pwdata);
   317       if (rv != SECSuccess) {
   318         if (verbose) 
   319 	  SECU_PrintError(program_name, "Encrypt operation failed\n");
   320         retval = -1;
   321         goto loser;
   322       }
   324       if (verbose) printf("Encrypted result is %d bytes long\n", result.len);
   326       if (!strcmp(output_file, "-")) {
   327         ascii = PR_TRUE;
   328       }
   330       if (ascii) {
   331       	/* base64 encode output. */
   332 	char * newResult = NSSBase64_EncodeItem(NULL, NULL, 0, &result);
   333 	if (!newResult) {
   334 	  SECU_PrintError(program_name, "Base 64 encode failed\n");
   335 	  retval = -1;
   336 	  goto loser;
   337 	}
   338 	outBuf.data = (unsigned char *)newResult;
   339 	outBuf.len  = strlen(newResult);
   340 	if (verbose) 
   341 	  printf("Base 64 encoded result is %d bytes long\n", outBuf.len);
   342       } else {
   343 	outBuf = result;
   344       }
   346       /* -v printf("Result is %.*s\n", text.len, text.data); */
   347       if (output_file) {
   348          PRFileDesc *file;
   349          PRInt32 count;
   351          if (verbose) printf("Writing result to %s\n", output_file);
   352 	 if (!strcmp(output_file, "-")) {
   353 	   file = PR_STDOUT;
   354 	 } else {
   355 	   /* Write to file */
   356 	   file = PR_Open(output_file, PR_CREATE_FILE|PR_WRONLY, 0666);
   357 	 }
   358          if (!file) {
   359             if (verbose) 
   360 		SECU_PrintError(program_name, 
   361                                 "Open of output file %s failed\n",
   362                                 output_file);
   363             retval = -1;
   364             goto loser;
   365          }
   367          count = PR_Write(file, outBuf.data, outBuf.len);
   369 	 if (file == PR_STDOUT) {
   370 	   puts("");
   371 	 } else {
   372 	   PR_Close(file);
   373 	 }
   375          if (count != outBuf.len) {
   376            if (verbose) SECU_PrintError(program_name, "Write failed\n");
   377            retval = -1;
   378            goto loser;
   379          }
   380 	 if (ascii) {
   381 	   free(outBuf.data);
   382 	 }
   383       }
   384     }
   386     /* Decrypt the value */
   387     rv = PK11SDR_Decrypt(&result, &text, &pwdata);
   388     if (rv != SECSuccess) {
   389       if (verbose) SECU_PrintError(program_name, "Decrypt operation failed\n");
   390       retval = -1; 
   391       goto loser;
   392     }
   394     if (verbose) printf("Decrypted result is \"%.*s\"\n", text.len, text.data);
   396     /* Compare to required value */
   397     if (text.len != data.len || memcmp(data.data, text.data, text.len) != 0)
   398     {
   399       if (verbose) PR_fprintf(pr_stderr, "Comparison failed\n");
   400       retval = -1;
   401       goto loser;
   402     }
   404 loser:
   405     if (text.data) SECITEM_ZfreeItem(&text, PR_FALSE);
   406     if (result.data) SECITEM_ZfreeItem(&result, PR_FALSE);
   407     if (NSS_Shutdown() != SECSuccess) {
   408        exit(1);
   409     }
   411 prdone:
   412     PR_Cleanup ();
   413     if (pwdata.data) {
   414 	PORT_Free(pwdata.data);
   415     }
   416     return retval;
   417 }

mercurial