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) {
|