security/nss/cmd/sdrtest/sdrtest.c

changeset 0
6474c204b198
     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 +}

mercurial