Browse Source

Re-work some of the demos

* Add at least a `-h` option, sometimes more.
* Fix the exit codes of some of them.
* Make them all compile with `LTC_EASY`.

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 10 months ago
parent
commit
795e8e8cfe
7 changed files with 232 additions and 138 deletions
  1. 21 31
      demos/aesgcm.c
  2. 34 22
      demos/crypt.c
  3. 14 9
      demos/hashsum.c
  4. 83 56
      demos/openssl-enc.c
  5. 15 1
      demos/pem-info.c
  6. 44 17
      demos/timing.c
  7. 21 2
      demos/tv_gen.c

+ 21 - 31
demos/aesgcm.c

@@ -16,10 +16,16 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <string.h>
-#include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
 
+#ifndef LTC_GCM_MODE
+int main(void)
+{
+   return -1;
+}
+#else
+
 #include "gcm-file/gcm_filehandle.c"
 #include "gcm-file/gcm_file.c"
 
@@ -58,33 +64,7 @@ OUT:
    return 0;
 }
 
-/* https://stackoverflow.com/a/23898449 */
-static void scan_hex(const char* str, uint8_t* bytes, size_t blen)
-{
-   uint8_t  pos;
-   uint8_t  idx0;
-   uint8_t  idx1;
-
-   const uint8_t hashmap[] =
-   {
-     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
-     0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */
-     0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* @ABCDEFG */
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* HIJKLMNO */
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* PQRSTUVW */
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* XYZ[\]^_ */
-     0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* `abcdefg */
-   };
-
-   for (pos = 0; ((pos < (blen*2)) && (pos < XSTRLEN(str))); pos += 2)
-   {
-      idx0 = (uint8_t)(str[pos+0] & 0x1F) ^ 0x10;
-      idx1 = (uint8_t)(str[pos+1] & 0x1F) ^ 0x10;
-      bytes[pos/2] = (uint8_t)(hashmap[idx0] << 4) | hashmap[idx1];
-   }
-}
-
-static void die(int ret)
+static void LTC_NORETURN die(int ret)
 {
    fprintf(stderr, "Usage: aesgcm <-e|-d> <infile> <outfile> <88|96 char hex-string 'IV | key'>\n");
    exit(ret);
@@ -97,9 +77,14 @@ int main(int argc, char **argv)
    uint8_t keybuf[48] = {0};
    char *out = NULL;
    const char *mode, *in_file, *out_file, *key_string;
-   unsigned long ivlen;
+   unsigned long ivlen, key_len;
 
-   if (argc < 5) die(__LINE__);
+   if (argc < 5) {
+      if (argc > 1 && strstr(argv[1], "-h"))
+         die(0);
+      else
+         die(__LINE__);
+   }
 
    arg = 1;
    mode = argv[arg++];
@@ -116,7 +101,11 @@ int main(int argc, char **argv)
    keylen = XSTRLEN(key_string);
    if (keylen != 88 && keylen != 96) die(__LINE__);
 
-   scan_hex(key_string, keybuf, keylen/2);
+   key_len = sizeof(keybuf);
+   if ((err = base16_decode(key_string, keylen, keybuf, &key_len)) != CRYPT_OK) {
+      fprintf(stderr, "boooh %s\n", error_to_string(err));
+      die(__LINE__);
+   }
 
    register_all_ciphers();
 
@@ -148,3 +137,4 @@ cleanup:
 
    return ret;
 }
+#endif

+ 34 - 22
demos/crypt.c

@@ -12,17 +12,29 @@
 
 #include <tomcrypt.h>
 
-static int LTC_NORETURN usage(char *name)
+static int LTC_NORETURN die(int status)
 {
-   int x;
-
-   printf("Usage encrypt: %s cipher infile outfile\n", name);
-   printf("Usage decrypt: %s -d cipher infile outfile\n", name);
-   printf("Usage test:    %s -t cipher\nCiphers:\n", name);
+   int x, w, tot = 0;
+   FILE* o = status == EXIT_SUCCESS ? stdout : stderr;
+   fprintf(o,
+           "Usage encrypt: crypt <cipher> <infile> <outfile>\n"
+           "Usage decrypt: crypt -d <cipher> <infile> <outfile>\n"
+           "Usage test:    crypt -t <cipher>\n"
+           "This help:     crypt -h\n\nCiphers:\n\t");
    for (x = 0; cipher_descriptor[x].name != NULL; x++) {
-      printf("%s\n",cipher_descriptor[x].name);
+      w = fprintf(o, "%-14s",cipher_descriptor[x].name);
+      if (w < 0) {
+         status = EXIT_FAILURE;
+         break;
+      }
+      tot += w;
+      if (tot >= 70) {
+         fprintf(o, "\n\t");
+         tot = 0;
+      }
    }
-   exit(1);
+   if (tot != 0) fprintf(o, "\n");
+   exit(status);
 }
 
 int main(int argc, char *argv[])
@@ -48,24 +60,24 @@ int main(int argc, char *argv[])
         cipher  = argv[2];
         cipher_idx = find_cipher(cipher);
         if (cipher_idx == -1) {
-          printf("Invalid cipher %s entered on command line.\n", cipher);
-          exit(-1);
+          fprintf(stderr, "Invalid cipher %s entered on command line.\n", cipher);
+          die(EXIT_FAILURE);
         } /* if */
-        if (cipher_descriptor[cipher_idx].test)
-        {
-          if (cipher_descriptor[cipher_idx].test() != CRYPT_OK)
-          {
-            printf("Error when testing cipher %s.\n", cipher);
-            exit(-1);
+        if (cipher_descriptor[cipher_idx].test) {
+          if (cipher_descriptor[cipher_idx].test() != CRYPT_OK) {
+            fprintf(stderr, "Error when testing cipher %s.\n", cipher);
+            die(EXIT_FAILURE);
           }
-          else
-          {
+          else {
             printf("Testing cipher %s succeeded.\n", cipher);
-            exit(0);
-          } /* if ... else */
-        } /* if */
+            exit(EXIT_SUCCESS);
+          }
+        } else {
+          fprintf(stderr, "Cipher %s has no tests.\n", cipher);
+          exit(EXIT_SUCCESS);
+        }
       }
-      return usage(argv[0]);
+      return die(argc > 1 && strstr(argv[1], "-h") != NULL ? EXIT_SUCCESS : EXIT_FAILURE);
    }
 
    if (!strcmp(argv[1], "-d")) {

+ 14 - 9
demos/hashsum.c

@@ -41,10 +41,17 @@ static void die(int status)
 {
    unsigned long w, x;
    FILE* o = status == EXIT_SUCCESS ? stdout : stderr;
-   fprintf(o, "usage: %s -a algorithm [-c] [file...]\n\n", hashsum);
-   fprintf(o, "\t-c\tCheck the hash(es) of the file(s) written in [file].\n");
-   fprintf(o, "\t\t(-a not required)\n");
-   fprintf(o, "\nAlgorithms:\n\t");
+   fprintf(o,
+           "Usage: %s [-a <algorithm>...] [-c|-h] [<file>...]\n\n"
+           "\t-c\tCheck the hash(es) of the file(s) written in <file>.\n"
+           "\t\tNote: -a is not required when checking the hash(es).\n"
+           "\t-h\tThis help\n\n"
+           "Examples:\n"
+           "\t%s -a sha1 file > file.sha1sum\n"
+           "\t%s -c file.sha1sum\n"
+           "\t%s -a sha1 -a sha256 -a sha512-256 file > file.hashsum\n"
+           "\t%s -c file.hashsum\n\n"
+           "Algorithms:\n\t", hashsum, hashsum, hashsum, hashsum, hashsum);
    w = 0;
    for (x = 0; hash_descriptor[x].name != NULL; x++) {
       w += fprintf(o, "%-14s", hash_descriptor[x].name);
@@ -67,7 +74,7 @@ static void printf_hex(unsigned char* hash_buffer, unsigned long w)
 
 static void check_file(int argn, int argc, char **argv)
 {
-   int err, failed, invalid;
+   int err, failed = 0, invalid = 0;
    unsigned char is_buffer[MAXBLOCKSIZE], should_buffer[MAXBLOCKSIZE];
    char buf[PATH_MAX + (MAXBLOCKSIZE * 3)];
    /* iterate through all files */
@@ -82,8 +89,6 @@ static void check_file(int argn, int argc, char **argv)
             perror(argv[argn]);
          exit(EXIT_FAILURE);
       }
-      failed = 0;
-      invalid = 0;
       /* read the file line by line */
       while((s = fgets(buf, sizeof(buf), f)) != NULL)
       {
@@ -163,7 +168,7 @@ ERR:
       }
       argn++;
    }
-   exit(EXIT_SUCCESS);
+   exit(failed == 0 && invalid == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
 int main(int argc, char **argv)
@@ -178,7 +183,7 @@ int main(int argc, char **argv)
    /* You need to register algorithms before using them */
    register_all_ciphers();
    register_all_hashes();
-   if (argc > 1 && (strcmp("-h", argv[1]) == 0 || strcmp("--help", argv[1]) == 0)) {
+   if (argc > 1 && strstr(argv[1], "-h")) {
       die(EXIT_SUCCESS);
    }
    if (argc < 3) {

+ 83 - 56
demos/openssl-enc.c

@@ -24,8 +24,6 @@
  * - OpenSSL-compatible key derivation (in OpenSSL's modified PKCS#5v1 approach)
  * - Grabbing an Initialization Vector from the key generator
  * - Performing simple block encryption using AES
- * - PKCS#7-type padding (which hopefully can get ripped out of this demo and
- *   made a libtomcrypt thing someday).
  *
  * This program is free for all purposes without any express guarantee it
  * works. If you really want to see a license here, assume the WTFPL :-)
@@ -38,22 +36,14 @@
  */
 
 #include <tomcrypt.h>
+#include <termios.h>
 
-#ifndef LTC_RIJNDAEL
-#error Cannot compile this demo; Rijndael (AES) required
-#endif
-#ifndef LTC_CBC_MODE
-#error Cannot compile this demo; CBC mode required
-#endif
-#ifndef LTC_PKCS_5
-#error Cannot compile this demo; PKCS5 required
-#endif
-#ifndef LTC_RNG_GET_BYTES
-#error Cannot compile this demo; random generator required
-#endif
-#ifndef LTC_MD5
-#error Cannot compile this demo; MD5 required
-#endif
+#if !defined(LTC_RIJNDAEL) || !defined(LTC_CBC_MODE) || !defined(LTC_PKCS_5) || !defined(LTC_RNG_GET_BYTES) || !defined(LTC_MD5)
+int main(void)
+{
+   return -1;
+}
+#else
 
 /* OpenSSL by default only runs one hash round */
 #define OPENSSL_ITERATIONS 1
@@ -83,44 +73,33 @@ union paddable {
  * Output:       <no return>
  * Side Effects: print messages and barf (does exit(3))
  */
-void barf(const char *pname, const char *err)
+static void LTC_NORETURN barf(const char *pname, const char *err)
 {
-   printf("Usage: %s <enc|dec> infile outfile passphrase [salt]\n", pname);
-   printf("\n");
-   printf("       # encrypts infile->outfile, random salt\n");
-   printf("       %s enc infile outfile \"passphrase\"\n", pname);
-   printf("\n");
-   printf("       # encrypts infile->outfile, salt from cmdline\n");
-   printf("       %s enc infile outfile pass 0123456789abcdef\n", pname);
-   printf("\n");
-   printf("       # decrypts infile->outfile, pulls salt from infile\n");
-   printf("       %s dec infile outfile pass\n", pname);
-   printf("\n");
-   printf("       # decrypts infile->outfile, salt specified\n");
-   printf("       # (don't try to read the salt from infile)\n");
-   printf("       %s dec infile outfile pass 0123456789abcdef"
-          "\n", pname);
-   printf("\n");
-   printf("Application Error: %s\n", err);
+   FILE* o = err == NULL ? stdout : stderr;
+   fprintf(o,
+            "Usage: %s <enc|dec> infile outfile [passphrase | -] [salt]\n"
+            "\n"
+            "       The passphrase can either be given at the command line\n"
+            "       or if it's passed as '-' it will be read interactively.\n"
+            "\n"
+            "       # encrypts infile->outfile, random salt\n"
+            "       %s enc infile outfile pass\n"
+            "\n"
+            "       # encrypts infile->outfile, salt from cmdline\n"
+            "       %s enc infile outfile pass 0123456789abcdef\n"
+            "\n"
+            "       # decrypts infile->outfile, pulls salt from infile\n"
+            "       %s dec infile outfile pass\n"
+            "\n"
+            "       # decrypts infile->outfile, salt specified\n"
+            "       # (don't try to read the salt from infile)\n"
+            "       %s dec infile outfile pass 0123456789abcdef\n"
+            "\n"
+            "Application Error: %s\n", pname, pname, pname, pname, pname, err ? err : "None");
    if(errno)
-      perror("     System Error");
-   exit(-1);
-}
-
-/*
- * Parse a salt value passed in on the cmdline.
- *
- * Input:        string passed in and a buf to put it in (exactly 8 bytes!)
- * Output:       CRYPT_OK if parsed OK, CRYPT_ERROR if not
- * Side Effects: none
- */
-int parse_hex_salt(unsigned char *in, unsigned char *out)
-{
-   int idx;
-   for(idx=0; idx<SALT_LENGTH; idx++)
-      if(sscanf((char*)in+idx*2, "%02hhx", out+idx) != 1)
-         return CRYPT_ERROR;
-   return CRYPT_OK;
+      perror(
+            "     System Error");
+   exit(err == NULL ? 0 : -1);
 }
 
 /*
@@ -259,8 +238,39 @@ int do_crypt(FILE *infd, FILE *outfd, unsigned char *key, unsigned char *iv,
    return CRYPT_OK;
 }
 
+
+static char* getpassword(const char *prompt, size_t maxlen)
+{
+   char *wr, *end, *pass = XCALLOC(1, maxlen + 1);
+   struct termios tio;
+   tcflag_t c_lflag;
+   if (pass == NULL)
+      return NULL;
+   wr = pass;
+   end = pass + maxlen;
+
+   tcgetattr(0, &tio);
+   c_lflag = tio.c_lflag;
+   tio.c_lflag &= ~ECHO;
+   tcsetattr(0, TCSANOW, &tio);
+
+   printf("%s", prompt);
+   fflush(stdout);
+   while (pass < end) {
+      int c = getchar();
+      if (c == '\r' || c == '\n' || c == -1)
+         break;
+      *wr++ = c;
+   }
+   tio.c_lflag = c_lflag;
+   tcsetattr(0, TCSAFLUSH, &tio);
+   printf("\n");
+   return pass;
+}
+
 /* Convenience macro for the various barfable places below */
 #define BARF(a) { \
+   if(password) free(password); \
    if(infd) fclose(infd); \
    if(outfd) { fclose(outfd); remove(argv[3]); } \
    barf(argv[0], a); \
@@ -278,6 +288,12 @@ int main(int argc, char *argv[]) {
    unsigned char keyiv[KEY_LENGTH + IV_LENGTH];
    unsigned long keyivlen = (KEY_LENGTH + IV_LENGTH);
    unsigned char *key, *iv;
+   const void *pass;
+   char *password = NULL;
+   unsigned long saltlen = sizeof(salt);
+
+   if (argc > 1 && strstr(argv[1], "-h"))
+      barf(argv[0], NULL);
 
    /* Check proper number of cmdline args */
    if(argc < 5 || argc > 6)
@@ -302,9 +318,9 @@ int main(int argc, char *argv[]) {
    /* Get the salt from wherever */
    if(argc == 6) {
       /* User-provided */
-      if(parse_hex_salt((unsigned char*) argv[5], salt) != CRYPT_OK)
+      if(base16_decode(argv[5], strlen(argv[5]), salt, &saltlen) != CRYPT_OK)
          BARF("Bad user-specified salt");
-   } else if(!strncmp(argv[1], "enc", 3)) {
+   } else if(encrypt) {
       /* Encrypting; get from RNG */
       if(rng_get_bytes(salt, sizeof(salt), NULL) != sizeof(salt))
          BARF("Not enough random data");
@@ -324,9 +340,18 @@ int main(int argc, char *argv[]) {
    key = keyiv + 0;      /* key comes first */
    iv = keyiv + KEY_LENGTH;   /* iv comes next */
 
+   if (argv[4] && strcmp(argv[4], "-")) {
+      pass = argv[4];
+   } else {
+      password = getpassword("Enter password: ", 256);
+      if (!password)
+         BARF("Could not get password");
+      pass = password;
+   }
+
    /* Run the key derivation from the provided passphrase.  This gets us
       the key and iv. */
-   ret = pkcs_5_alg1_openssl((unsigned char*)argv[4], XSTRLEN(argv[4]), salt,
+   ret = pkcs_5_alg1_openssl(pass, XSTRLEN(pass), salt,
                              OPENSSL_ITERATIONS, hash, keyiv, &keyivlen );
    if(ret != CRYPT_OK)
       BARF("Could not derive key/iv from passphrase");
@@ -353,6 +378,8 @@ int main(int argc, char *argv[]) {
       BARF("Error during crypt operation");
 
    /* Clean up */
+   if(password) free(password);
    fclose(infd); fclose(outfd);
    return 0;
 }
+#endif

+ 15 - 1
demos/pem-info.c

@@ -69,9 +69,23 @@ static const char *s_map_mode(enum cipher_mode mode)
    exit(1);
 }
 
-int main(void)
+
+static void LTC_NORETURN die(int status)
+{
+   FILE* o = status == EXIT_SUCCESS ? stdout : stderr;
+   fprintf(o,
+         "Usage: pem-info [<-h>]\n\n"
+         "Generate LaTeX tables from the supported PEM resp. SSH ciphers.\n\n"
+         "\t-h\tThe help you're looking at.\n"
+   );
+   exit(status);
+}
+
+int main(int argc, char **argv)
 {
    unsigned long n;
+   if (argc > 1 && strstr(argv[1], "-h"))
+      die(0);
    printf("PEM ciphers:\n\n");
    for (n = 0; n < pem_dek_infos_num; ++n) {
       char nbuf[32] = {0};

+ 44 - 17
demos/timing.c

@@ -1325,7 +1325,21 @@ static void time_encmacs(void)
    time_encmacs_(32);
 }
 
-#define LTC_TEST_FN(f)  { f, #f }
+static void LTC_NORETURN die(int status)
+{
+   FILE* o = status == EXIT_SUCCESS ? stdout : stderr;
+   fprintf(o,
+         "Usage: timing [<-h|-l|alg>] [mpi]\n\n"
+         "Run timing tests of all built-in algorithms, or only the one given in <alg>.\n\n"
+         "\talg\tThe algorithm to test. Use the '-l' option to check for valid values.\n"
+         "\tmpi\tThe MPI provider to use.\n"
+         "\t-l\tList all built-in algorithms that can be timed.\n"
+         "\t-h\tThe help you're looking at.\n"
+   );
+   exit(status);
+}
+
+#define LTC_TEST_FN(f)  { time_ ## f, #f }
 int main(int argc, char **argv)
 {
 int err;
@@ -1335,26 +1349,37 @@ const struct
    void (*fn)(void);
    const char* name;
 } test_functions[] = {
-   LTC_TEST_FN(time_keysched),
-   LTC_TEST_FN(time_cipher_ecb),
-   LTC_TEST_FN(time_cipher_cbc),
-   LTC_TEST_FN(time_cipher_ctr),
-   LTC_TEST_FN(time_cipher_lrw),
-   LTC_TEST_FN(time_hash),
-   LTC_TEST_FN(time_macs),
-   LTC_TEST_FN(time_encmacs),
-   LTC_TEST_FN(time_prng),
-   LTC_TEST_FN(time_mult),
-   LTC_TEST_FN(time_sqr),
-   LTC_TEST_FN(time_rsa),
-   LTC_TEST_FN(time_dsa),
-   LTC_TEST_FN(time_ecc),
-   LTC_TEST_FN(time_dh),
+   LTC_TEST_FN(keysched),
+   LTC_TEST_FN(cipher_ecb),
+   LTC_TEST_FN(cipher_cbc),
+   LTC_TEST_FN(cipher_ctr),
+   LTC_TEST_FN(cipher_lrw),
+   LTC_TEST_FN(hash),
+   LTC_TEST_FN(macs),
+   LTC_TEST_FN(encmacs),
+   LTC_TEST_FN(prng),
+   LTC_TEST_FN(mult),
+   LTC_TEST_FN(sqr),
+   LTC_TEST_FN(rsa),
+   LTC_TEST_FN(dsa),
+   LTC_TEST_FN(ecc),
+   LTC_TEST_FN(dh),
 };
 char *single_test = NULL;
 unsigned int i;
 const char* mpi_provider = NULL;
 
+if (argc > 1) {
+   if (strstr(argv[1], "-h")) {
+      die(EXIT_SUCCESS);
+   } else if (strstr(argv[1], "-l")) {
+      for (i = 0; i < sizeof(test_functions)/sizeof(test_functions[0]); ++i) {
+         printf("%s\n", test_functions[i].name);
+      }
+      exit(0);
+   }
+}
+
 init_timer();
 register_all_ciphers();
 register_all_hashes();
@@ -1374,7 +1399,9 @@ register_all_prngs();
       mpi_provider = argv[2];
    }
 
-   crypt_mp_init(mpi_provider);
+   if (crypt_mp_init(mpi_provider) != CRYPT_OK) {
+      fprintf(stderr, "Init of MPI provider \"%s\" failed\n", mpi_provider ? mpi_provider : "(null)");
+   }
 
 if ((err = rng_make_prng(128, find_prng("yarrow"), &yarrow_prng, NULL)) != CRYPT_OK) {
    fprintf(stderr, "rng_make_prng failed: %s\n", error_to_string(err));

+ 21 - 2
demos/tv_gen.c

@@ -11,7 +11,8 @@ static void hash_gen(void)
 
    out = fopen("hash_tv.txt", "w");
    if (out == NULL) {
-      perror("can't open hash_tv");
+      perror("can't open hash_tv.txt");
+      return;
    }
 
    fprintf(out, "Hash Test Vectors:\n\nThese are the hashes of nn bytes '00 01 02 03 .. (nn-1)'\n\n");
@@ -766,8 +767,26 @@ static void lrw_gen(void)
 }
 #endif
 
-int main(void)
+static void LTC_NORETURN die(int status)
 {
+   FILE* o = status == EXIT_SUCCESS ? stdout : stderr;
+   fprintf(o,
+         "Usage: tv_gen [<-h>]\n\n"
+         "Generate the internal test-vectors.\n\n"
+         "\t-h\tThe help you're looking at.\n"
+   );
+   exit(status);
+}
+
+int main(int argc, char **argv)
+{
+   if (argc > 1) {
+      if (strstr(argv[1], "-h")) {
+         die(EXIT_SUCCESS);
+      } else {
+         die(EXIT_FAILURE);
+      }
+   }
    register_all_ciphers();
    register_all_hashes();
    register_all_prngs();