Print this page
6418676 encrypt(1) and decrypt(1) could benefit from being 64-bit programs


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /* Portions Copyright 2005 Richard Lowe */
  22 /*
  23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "@(#)decrypt.c  1.13    07/10/04 SMI"
  28 
  29 /*
  30  * decrypt.c
  31  *
  32  * Implements encrypt(1) and decrypt(1) commands
  33  *
  34  * One binary performs both encrypt/decrypt operation.
  35  *
  36  * usage:
  37  *
  38  *  algorithm - mechanism name without CKM_ prefix. Case
  39  *              does not matter
  40  *  keyfile - file containing key data. If not specified user is
  41  *            prompted to enter key. key length > 0 is required
  42  *  infile  - input file to encrypt/decrypt. If omitted, stdin used.
  43  *  outfile - output file to encrypt/decrypt. If omitted, stdout used.
  44  *            if infile & outfile are same, a temp file is used for
  45  *            output and infile is replaced with this file after
  46  *            operation is complete.




  47  *
  48  * Implementation notes:
  49  *   iv data - It is generated by random bytes equal to one block size.
  50  *
  51  *   encrypted output format -
  52  *   - Output format version number - 4 bytes in network byte order.
  53  *   - Iterations used in key gen function, 4 bytes in  network byte order.
  54  *   - IV ( 'ivlen' bytes)
  55  *   - Salt data used in key gen (16 bytes)
  56  *   - cipher text data.
  57  *
  58  */
  59 
  60 #include <stdio.h>
  61 #include <stdlib.h>
  62 #include <unistd.h>
  63 #include <errno.h>
  64 #include <fcntl.h>
  65 #include <ctype.h>
  66 #include <strings.h>
  67 #include <libintl.h>
  68 #include <libgen.h>
  69 #include <locale.h>
  70 #include <limits.h>
  71 #include <sys/types.h>
  72 #include <sys/stat.h>
  73 #include <netinet/in.h>
  74 #include <security/cryptoki.h>
  75 #include <cryptoutil.h>
  76 #include <kmfapi.h>
  77 


 148 };
 149 
 150 #define MECH_ALIASES_COUNT 4
 151 
 152 static struct mech_alias mech_aliases[] = {
 153         { CKM_AES_CBC_PAD, "aes", ULONG_MAX, 0L, 8, 16, B_FALSE },
 154         { CKM_RC4, "arcfour", ULONG_MAX, 0L, 1, 0, B_FALSE },
 155         { CKM_DES_CBC_PAD, "des", 8, 8, 8, 8, B_FALSE },
 156         { CKM_DES3_CBC_PAD, "3des", 24, 24, 8, 8, B_FALSE },
 157 };
 158 
 159 static CK_BBOOL truevalue = TRUE;
 160 static CK_BBOOL falsevalue = FALSE;
 161 
 162 static boolean_t aflag = B_FALSE; /* -a <algorithm> flag, required */
 163 static boolean_t kflag = B_FALSE; /* -k <keyfile> flag */
 164 static boolean_t iflag = B_FALSE; /* -i <infile> flag, use stdin if absent */
 165 static boolean_t oflag = B_FALSE; /* -o <outfile> flag, use stdout if absent */
 166 static boolean_t lflag = B_FALSE; /* -l flag (list) */
 167 static boolean_t vflag = B_FALSE; /* -v flag (verbose) */
 168 static boolean_t Tflag = B_FALSE;
 169 static boolean_t Kflag = B_FALSE;
 170 
 171 static char *keyfile = NULL;    /* name of keyfile */
 172 static char *inputfile = NULL;  /* name of input file */
 173 static char *outputfile = NULL; /* name of output file */
 174 static char *token_label = NULL;
 175 static char *key_label = NULL;
 176 
 177 static int status_pos = 0; /* current position of progress bar element */
 178 
 179 /*
 180  * function prototypes
 181  */
 182 static void usage(struct CommandInfo *cmd);
 183 static int execute_cmd(struct CommandInfo *cmd, char *algo_str);
 184 static int crypt_multipart(struct CommandInfo *cmd, CK_SESSION_HANDLE hSession,
 185         int infd, int outfd, off_t insize);
 186 
 187 int
 188 main(int argc, char **argv)
 189 {
 190 
 191         extern char *optarg;
 192         extern int optind;
 193         char *optstr;
 194         char c;                 /* current getopts flag */
 195         char *algo_str = NULL;  /* algorithm string */
 196         struct CommandInfo *cmd;
 197         char *cmdname;          /* name of command */
 198         boolean_t errflag = B_FALSE;
 199 
 200         (void) setlocale(LC_ALL, "");
 201 #if !defined(TEXT_DOMAIN)       /* Should be defiend by cc -D */
 202 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 203 #endif
 204         (void) textdomain(TEXT_DOMAIN);
 205 
 206         /*
 207          * Based on command name, determine
 208          * type of command.
 209          */
 210         cmdname = basename(argv[0]);
 211 
 212         cryptodebug_init(cmdname);
 213 
 214         if (strcmp(cmdname, encrypt_cmd.name) == 0) {
 215                 cmd = &encrypt_cmd;
 216         } else if (strcmp(cmdname, decrypt_cmd.name) == 0) {
 217                 cmd = &decrypt_cmd;
 218         } else {
 219                 cryptoerror(LOG_STDERR, gettext(
 220                     "command name must be either encrypt or decrypt"));
 221                 exit(EXIT_USAGE);


 419         CK_MECHANISM_INFO info, kg_info;
 420         CK_MECHANISM mech;
 421         CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
 422         CK_BYTE_PTR     pkeydata = NULL;
 423         CK_BYTE         salt[CK_PKCS5_PBKD2_SALT_SIZE];
 424         CK_ULONG        keysize = 0;
 425         int i, slot, mek;               /* index variables */
 426         int status;
 427         struct stat     insbuf;         /* stat buf for infile */
 428         struct stat     outsbuf;        /* stat buf for outfile */
 429         char    tmpnam[PATH_MAX];       /* tmp file name */
 430         CK_OBJECT_HANDLE key = (CK_OBJECT_HANDLE) 0;
 431         int infd = 0;                   /* input file, stdin default */
 432         int outfd = 1;                  /* output file, stdout default */
 433         char *outfilename = NULL;
 434         boolean_t errflag = B_TRUE;
 435         boolean_t inoutsame = B_FALSE;  /* if both input & output are same */
 436         CK_BYTE_PTR     pivbuf = NULL_PTR;
 437         CK_ULONG        ivlen = 0L;
 438         int mech_match = 0;
 439         CK_ULONG        iterations = CK_PKCS5_PBKD2_ITERATIONS;
 440         CK_ULONG        keylen;
 441         int version = SUNW_ENCRYPT_FILE_VERSION;
 442         CK_KEY_TYPE keytype;
 443         KMF_RETURN kmfrv;
 444         CK_SLOT_ID token_slot_id;
 445 
 446         if (aflag) {
 447                 /* Determine if algorithm is valid */
 448                 for (mech_match = 0; mech_match < MECH_ALIASES_COUNT;
 449                     mech_match++) {
 450                         if (strcmp(algo_str,
 451                             mech_aliases[mech_match].alias) == 0) {
 452                                 mech_type = mech_aliases[mech_match].type;
 453                                 break;
 454                         }
 455                 }
 456 
 457                 if (mech_match == MECH_ALIASES_COUNT) {
 458                         cryptoerror(LOG_STDERR,
 459                             gettext("unknown algorithm -- %s"), algo_str);
 460                         return (EXIT_FAILURE);
 461                 }


 723 
 724         /*
 725          * Read the version number from the head of the file
 726          * to know how to interpret the data that follows.
 727          */
 728         if (cmd->type == CKA_DECRYPT) {
 729                 if (read(infd, &version, sizeof (version)) !=
 730                     sizeof (version)) {
 731                         cryptoerror(LOG_STDERR, gettext(
 732                             "failed to get format version from "
 733                             "input file."));
 734                         goto cleanup;
 735                 }
 736                 /* convert to host byte order */
 737                 version = ntohl(version);
 738 
 739                 switch (version) {
 740                 case 1:
 741                 /*
 742                  * Version 1 output format:

 743                  *  - Iterations used in key gen function (4 bytes)
 744                  *  - IV ( 'ivlen' bytes)
 745                  *  - Salt data used in key gen (16 bytes)

 746                  *
 747                  * An encrypted file has IV as first block (0 or
 748                  * more bytes depending on mechanism) followed
 749                  * by cipher text.  Get the IV from the encrypted
 750                  * file.
 751                  */
 752                         /*
 753                          * Read iteration count and salt data.
 754                          */
 755                         if (read(infd, &iterations,
 756                             sizeof (iterations)) != sizeof (iterations)) {
 757                                 cryptoerror(LOG_STDERR, gettext(
 758                                     "failed to get iterations from "
 759                                     "input file."));
 760                                 goto cleanup;
 761                         }
 762                         /* convert to host byte order */
 763                         iterations = ntohl(iterations);
 764                         if (ivlen > 0 &&
 765                             read(infd, pivbuf, ivlen) != ivlen) {


 881                 goto cleanup;
 882         }
 883 
 884 
 885 do_crypto:
 886         /* Setup up mechanism */
 887         mech.mechanism = mech_type;
 888         mech.pParameter = (CK_VOID_PTR)pivbuf;
 889         mech.ulParameterLen = ivlen;
 890 
 891         if ((rv = cmd->Init(hSession, &mech, key)) != CKR_OK) {
 892                 cryptoerror(LOG_STDERR, gettext(
 893                     "failed to initialize crypto operation: %s"),
 894                     pkcs11_strerror(rv));
 895                 goto cleanup;
 896         }
 897 
 898         /* Write the version header encrypt command */
 899         if (cmd->type == CKA_ENCRYPT) {
 900                 /* convert to network order for storage */
 901                 int netversion = htonl(version);
 902                 CK_ULONG netiter;
 903 
 904                 if (write(outfd, &netversion, sizeof (netversion))
 905                     != sizeof (netversion)) {
 906                         cryptoerror(LOG_STDERR, gettext(
 907                             "failed to write version number "
 908                             "to output file."));
 909                         goto cleanup;
 910                 }
 911                 /*
 912                  * Write the iteration and salt data, even if they
 913                  * were not used to generate a key.
 914                  */
 915                 netiter = htonl(iterations);
 916                 if (write(outfd, &netiter,
 917                     sizeof (netiter)) != sizeof (netiter)) {
 918                         cryptoerror(LOG_STDERR, gettext(
 919                             "failed to write iterations to output"));
 920                         goto cleanup;
 921                 }
 922                 if (ivlen > 0 && write(outfd, pivbuf, ivlen) != ivlen) {




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /* Portions Copyright 2005 Richard Lowe */
  22 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "@(#)decrypt.c  1.14    08/04/30 SMI"
  28 
  29 /*
  30  * decrypt.c
  31  *
  32  * Implements encrypt(1) and decrypt(1) commands
  33  *
  34  * One binary performs both encrypt/decrypt operation.
  35  *
  36  * Usage:
  37  *  -a algorithm mechanism name without CKM_ prefix. Case

  38  *               does not matter
  39  *  -k keyfile   file containing key data. If not specified user is
  40  *               prompted to enter key. key length > 0 is required
  41  *  -i infile    input file to encrypt/decrypt. If omitted, stdin used.
  42  *  -o outfile   output file to encrypt/decrypt. If omitted, stdout used.
  43  *               if infile & outfile are same, a temp file is used for
  44  *               output and infile is replaced with this file after
  45  *               operation is complete
  46  *  -l           Display the list of  algorithms
  47  *  -v           Display verbose information
  48  *  -T tokenspec Specify a PKCS#11 token (optionally used with -K)
  49  *  -K keylabel  Specify the symmetric PKCS#11 token key label
  50  *
  51  * Implementation notes:
  52  *   IV data - It is generated by random bytes equal to one block size.
  53  *
  54  *   Encrypted output format -
  55  *   - Output format version number - 4 bytes in network byte order.
  56  *   - Iterations used in key gen function, 4 bytes in  network byte order.
  57  *   - IV ('ivlen' bytes).  Length is algorithm-dependent (see mech_aliases)
  58  *   - Salt data used in key gen (16 bytes)
  59  *   - Cipher text data (remainder of the file)

  60  */
  61 
  62 #include <stdio.h>
  63 #include <stdlib.h>
  64 #include <unistd.h>
  65 #include <errno.h>
  66 #include <fcntl.h>
  67 #include <ctype.h>
  68 #include <strings.h>
  69 #include <libintl.h>
  70 #include <libgen.h>
  71 #include <locale.h>
  72 #include <limits.h>
  73 #include <sys/types.h>
  74 #include <sys/stat.h>
  75 #include <netinet/in.h>
  76 #include <security/cryptoki.h>
  77 #include <cryptoutil.h>
  78 #include <kmfapi.h>
  79 


 150 };
 151 
 152 #define MECH_ALIASES_COUNT 4
 153 
 154 static struct mech_alias mech_aliases[] = {
 155         { CKM_AES_CBC_PAD, "aes", ULONG_MAX, 0L, 8, 16, B_FALSE },
 156         { CKM_RC4, "arcfour", ULONG_MAX, 0L, 1, 0, B_FALSE },
 157         { CKM_DES_CBC_PAD, "des", 8, 8, 8, 8, B_FALSE },
 158         { CKM_DES3_CBC_PAD, "3des", 24, 24, 8, 8, B_FALSE },
 159 };
 160 
 161 static CK_BBOOL truevalue = TRUE;
 162 static CK_BBOOL falsevalue = FALSE;
 163 
 164 static boolean_t aflag = B_FALSE; /* -a <algorithm> flag, required */
 165 static boolean_t kflag = B_FALSE; /* -k <keyfile> flag */
 166 static boolean_t iflag = B_FALSE; /* -i <infile> flag, use stdin if absent */
 167 static boolean_t oflag = B_FALSE; /* -o <outfile> flag, use stdout if absent */
 168 static boolean_t lflag = B_FALSE; /* -l flag (list) */
 169 static boolean_t vflag = B_FALSE; /* -v flag (verbose) */
 170 static boolean_t Tflag = B_FALSE; /* -T flag (tokenspec) */
 171 static boolean_t Kflag = B_FALSE; /* -K flag (keylabel) */
 172 
 173 static char *keyfile = NULL;     /* name of keyfile */
 174 static char *inputfile = NULL;   /* name of input file */
 175 static char *outputfile = NULL;  /* name of output file */
 176 static char *token_label = NULL; /* name of PKCS#11 token */
 177 static char *key_label = NULL;   /* name of PKCS#11 token key label */
 178 
 179 static int status_pos = 0; /* current position of progress bar element */
 180 
 181 /*
 182  * function prototypes
 183  */
 184 static void usage(struct CommandInfo *cmd);
 185 static int execute_cmd(struct CommandInfo *cmd, char *algo_str);
 186 static int crypt_multipart(struct CommandInfo *cmd, CK_SESSION_HANDLE hSession,
 187         int infd, int outfd, off_t insize);
 188 
 189 int
 190 main(int argc, char **argv)
 191 {
 192 
 193         extern char *optarg;
 194         extern int optind;
 195         char *optstr;
 196         char c;                 /* current getopts flag */
 197         char *algo_str = NULL;  /* algorithm string */
 198         struct CommandInfo *cmd;
 199         char *cmdname;          /* name of command */
 200         boolean_t errflag = B_FALSE;
 201 
 202         (void) setlocale(LC_ALL, "");
 203 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 204 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 205 #endif
 206         (void) textdomain(TEXT_DOMAIN);
 207 
 208         /*
 209          * Based on command name, determine
 210          * type of command.
 211          */
 212         cmdname = basename(argv[0]);
 213 
 214         cryptodebug_init(cmdname);
 215 
 216         if (strcmp(cmdname, encrypt_cmd.name) == 0) {
 217                 cmd = &encrypt_cmd;
 218         } else if (strcmp(cmdname, decrypt_cmd.name) == 0) {
 219                 cmd = &decrypt_cmd;
 220         } else {
 221                 cryptoerror(LOG_STDERR, gettext(
 222                     "command name must be either encrypt or decrypt"));
 223                 exit(EXIT_USAGE);


 421         CK_MECHANISM_INFO info, kg_info;
 422         CK_MECHANISM mech;
 423         CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
 424         CK_BYTE_PTR     pkeydata = NULL;
 425         CK_BYTE         salt[CK_PKCS5_PBKD2_SALT_SIZE];
 426         CK_ULONG        keysize = 0;
 427         int i, slot, mek;               /* index variables */
 428         int status;
 429         struct stat     insbuf;         /* stat buf for infile */
 430         struct stat     outsbuf;        /* stat buf for outfile */
 431         char    tmpnam[PATH_MAX];       /* tmp file name */
 432         CK_OBJECT_HANDLE key = (CK_OBJECT_HANDLE) 0;
 433         int infd = 0;                   /* input file, stdin default */
 434         int outfd = 1;                  /* output file, stdout default */
 435         char *outfilename = NULL;
 436         boolean_t errflag = B_TRUE;
 437         boolean_t inoutsame = B_FALSE;  /* if both input & output are same */
 438         CK_BYTE_PTR     pivbuf = NULL_PTR;
 439         CK_ULONG        ivlen = 0L;
 440         int             mech_match = 0;
 441         uint32_t        iterations = CK_PKCS5_PBKD2_ITERATIONS;
 442         CK_ULONG        keylen;
 443         uint32_t        version = SUNW_ENCRYPT_FILE_VERSION;
 444         CK_KEY_TYPE keytype;
 445         KMF_RETURN kmfrv;
 446         CK_SLOT_ID token_slot_id;
 447 
 448         if (aflag) {
 449                 /* Determine if algorithm is valid */
 450                 for (mech_match = 0; mech_match < MECH_ALIASES_COUNT;
 451                     mech_match++) {
 452                         if (strcmp(algo_str,
 453                             mech_aliases[mech_match].alias) == 0) {
 454                                 mech_type = mech_aliases[mech_match].type;
 455                                 break;
 456                         }
 457                 }
 458 
 459                 if (mech_match == MECH_ALIASES_COUNT) {
 460                         cryptoerror(LOG_STDERR,
 461                             gettext("unknown algorithm -- %s"), algo_str);
 462                         return (EXIT_FAILURE);
 463                 }


 725 
 726         /*
 727          * Read the version number from the head of the file
 728          * to know how to interpret the data that follows.
 729          */
 730         if (cmd->type == CKA_DECRYPT) {
 731                 if (read(infd, &version, sizeof (version)) !=
 732                     sizeof (version)) {
 733                         cryptoerror(LOG_STDERR, gettext(
 734                             "failed to get format version from "
 735                             "input file."));
 736                         goto cleanup;
 737                 }
 738                 /* convert to host byte order */
 739                 version = ntohl(version);
 740 
 741                 switch (version) {
 742                 case 1:
 743                 /*
 744                  * Version 1 output format:
 745                  *  - Output format version 1 (4 bytes)
 746                  *  - Iterations used in key gen function (4 bytes)
 747                  *  - IV ('ivlen' bytes). The length algorithm-dependent
 748                  *  - Salt data used in key gen (16 bytes)
 749                  *  - Cipher text data (remainder of the file)
 750                  *
 751                  * An encrypted file has IV as first block (0 or
 752                  * more bytes depending on mechanism) followed
 753                  * by cipher text.  Get the IV from the encrypted
 754                  * file.
 755                  */
 756                         /*
 757                          * Read iteration count and salt data.
 758                          */
 759                         if (read(infd, &iterations,
 760                             sizeof (iterations)) != sizeof (iterations)) {
 761                                 cryptoerror(LOG_STDERR, gettext(
 762                                     "failed to get iterations from "
 763                                     "input file."));
 764                                 goto cleanup;
 765                         }
 766                         /* convert to host byte order */
 767                         iterations = ntohl(iterations);
 768                         if (ivlen > 0 &&
 769                             read(infd, pivbuf, ivlen) != ivlen) {


 885                 goto cleanup;
 886         }
 887 
 888 
 889 do_crypto:
 890         /* Setup up mechanism */
 891         mech.mechanism = mech_type;
 892         mech.pParameter = (CK_VOID_PTR)pivbuf;
 893         mech.ulParameterLen = ivlen;
 894 
 895         if ((rv = cmd->Init(hSession, &mech, key)) != CKR_OK) {
 896                 cryptoerror(LOG_STDERR, gettext(
 897                     "failed to initialize crypto operation: %s"),
 898                     pkcs11_strerror(rv));
 899                 goto cleanup;
 900         }
 901 
 902         /* Write the version header encrypt command */
 903         if (cmd->type == CKA_ENCRYPT) {
 904                 /* convert to network order for storage */
 905                 uint32_t        netversion = htonl(version);
 906                 uint32_t        netiter;
 907 
 908                 if (write(outfd, &netversion, sizeof (netversion))
 909                     != sizeof (netversion)) {
 910                         cryptoerror(LOG_STDERR, gettext(
 911                             "failed to write version number "
 912                             "to output file."));
 913                         goto cleanup;
 914                 }
 915                 /*
 916                  * Write the iteration and salt data, even if they
 917                  * were not used to generate a key.
 918                  */
 919                 netiter = htonl(iterations);
 920                 if (write(outfd, &netiter,
 921                     sizeof (netiter)) != sizeof (netiter)) {
 922                         cryptoerror(LOG_STDERR, gettext(
 923                             "failed to write iterations to output"));
 924                         goto cleanup;
 925                 }
 926                 if (ivlen > 0 && write(outfd, pivbuf, ivlen) != ivlen) {