1 /* -*- mode: c; c-file-style:"stroustrup"; -*- */
2 
3 /*
4  * Copyright (c) 2018 Mastercard
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include "pkcs11lib.h"
25 
26 #ifdef _WIN32
27 #include <openssl/applink.c>
28 #endif
29 
30 #define COMMAND_SUMMARY \
31     "Import data from a file onto PKCS#11 token.\n\n"
32 
33 /* prototypes */
34 void print_version_info(char *progname);
35 void print_usage(char *);
36 int main( int argc, char **argv);
37 
38 
39 
print_usage(char * progname)40 void print_usage(char *progname)
41 {
42     fprintf( stderr,
43 	     "USAGE: %s OPTIONS\n"
44 	     "\n"
45 	     COMMAND_SUMMARY
46 	     " OPTIONS:\n"
47 	     "* -l <pkcs#11 library path> : path to PKCS#11 library\n"
48 	     "  -m <NSS config dir> ( e.g. '.' or 'sql:.' ) : NSS db directory \n"
49 	     "  -s <slot number>\n"
50 	     "  -t <token label> : if present, -s option is ignored\n"
51 	     "  -p <token PIN> | :::exec:<command> | :::nologin\n"
52 	     "* -f <file> : path to a file\n"
53 	     "* -i <alias>: label/alias to give to data object\n"
54 	     "  -h : print usage information\n"
55 	     "  -V : print version information\n"
56 	     "|\n"
57 	     "+-> arguments marked with an asterix(*) are mandatory\n"
58              "|   (except if environment variable sets the value)\n"
59 	     "+-> arguments marked with a plus sign(+) can be repeated\n"
60 	     "\n"
61              " ENVIRONMENT VARIABLES:\n"
62 	     "    PKCS11LIB         : path to PKCS#11 library,\n"
63              "                        overriden by option -l\n"
64 	     "    PKCS11NSSDIR      : NSS configuration directory directive,\n"
65              "                        overriden by option -m\n"
66 	     "    PKCS11SLOT        : token slot (integer)\n"
67 	     "                        overriden by PKCS11TOKENLABEL,\n"
68 	     "                        options -t or -s\n"
69 	     "    PKCS11TOKENLABEL  : token label\n"
70 	     "                        overriden by options -t or -s\n"
71 	     "    PKCS11PASSWORD    : password\n"
72              "                        overriden by option -p\n"
73 	     "\n"
74 	     , pkcs11_ll_basename(progname) );
75 
76     exit( RC_ERROR_USAGE );
77 }
78 
main(int argc,char ** argv)79 int main( int argc, char ** argv )
80 {
81     extern char *optarg;
82     extern int optind, optopt;
83     int argnum = 0;
84     int errflag = 0;
85     char * library = NULL;
86     char * nsscfgdir = NULL;
87     char * filename = NULL;
88     char * password = NULL;
89     char * slotenv = NULL;
90     int slot = -1;
91     int interactive = 1;
92     char * tokenlabel = NULL;
93     char * label = NULL;
94 
95     pkcs11Context * p11Context = NULL;
96     func_rc retcode = rc_error_other_error;
97 
98     library = getenv("PKCS11LIB");
99     nsscfgdir = getenv("PKCS11NSSDIR");
100     tokenlabel = getenv("PKCS11TOKENLABEL");
101     if(tokenlabel==NULL) {
102 	slotenv = getenv("PKCS11SLOT");
103 	if (slotenv!=NULL) {
104 	    slot=atoi(slotenv);
105 	}
106     }
107     password = getenv("PKCS11PASSWORD");
108 
109     /* if a slot or a token is given, interactive is null */
110     if(slotenv!=NULL || tokenlabel!=NULL) {
111 	interactive=0;
112     }
113 
114     /* get the command-line arguments */
115     while ( ( argnum = getopt( argc, argv, "l:m:f:i:s:t:phV" ) ) != -1 )
116     {
117 	switch ( argnum )
118 	{
119 	case 'f':
120 	    filename = optarg;
121 	    break;
122 
123 	case 'l' :
124 	    library =  optarg;
125 	    break;
126 
127 	case 'm':
128 	    nsscfgdir = optarg;
129 	    break;
130 
131 	case 'p' :
132 	    password = optarg;
133 	    break;
134 
135 	case 's':
136 	    slot = atoi(optarg);
137 	    interactive = 0;
138 	    tokenlabel = NULL;
139 	    break;
140 
141 	case 't':
142 	    tokenlabel = optarg;
143 	    interactive = 0;
144 	    slot = -1;
145 	    break;
146 
147 	case 'i':
148 	    label= optarg;
149 	    break;
150 
151 	case 'h':
152 	    print_usage(argv[0]);
153 	    break;
154 
155 	case 'V':
156 	    print_version_info(argv[0]);
157 	    break;
158 
159 	default:
160 	    errflag++;
161 	    break;
162 
163 	}
164     }
165 
166     if ( errflag ) {
167 	fprintf(stderr, "Try `%s -h' for more information.\n", argv[0]);
168 	retcode = rc_error_usage;
169 	goto err;
170     }
171 
172     if ( library == NULL || label == NULL || filename == NULL ) {
173 	fprintf( stderr, "At least one required option or argument is wrong or missing.\n"
174 		 "Try `%s -h' for more information.\n", argv[0]);
175 	retcode = rc_error_usage;
176 	goto err;
177     }
178 
179     if((p11Context = pkcs11_newContext( library, nsscfgdir ))==NULL) {
180 	retcode = rc_error_library;
181 	goto err;
182     }
183 
184     /* validate the given provider library exists and can be opened */
185     if (( retcode = pkcs11_initialize( p11Context ) ) != CKR_OK ) {
186 	goto err;
187     }
188 
189     retcode = pkcs11_open_session( p11Context, slot, tokenlabel, password, 0, interactive);
190 
191     if ( retcode == rc_ok ) {
192 	CK_OBJECT_HANDLE imported_data = NULL_PTR;
193 
194 	if(pkcs11_data_exists(p11Context, label)) {
195 	    fprintf(stderr, "data object with this label already exists, aborting\n");
196 	    retcode = rc_error_object_exists;
197 	    goto err;
198 	}
199 
200 	imported_data = pkcs11_importdata( p11Context, filename, label);
201 
202 	if ( imported_data ) {
203 	    printf( "%s: importing file succeeded.\n", argv[0]);
204 	} else {
205 	    fprintf( stderr, "%s: importing file failed.\n", argv[0]);
206 	}
207 
208 	pkcs11_close_session( p11Context );
209     }
210 
211     pkcs11_finalize( p11Context );
212 
213 err:
214 
215     pkcs11_freeContext(p11Context);
216 
217     return retcode;
218 }
219