]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/cryptTool/cryptTool.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / cryptTool / cryptTool.c
1 /*
2 File: cryptTool.c
3
4 Description: simple encrypt/decrypt utility to demonstrate CDSA API
5 used for symmetric encryption
6
7 Author: dmitch
8
9 Copyright: Copyright (c) 2001,2003,2005-2006 Apple Computer, Inc. All Rights Reserved.
10
11 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
12 Computer, Inc. ("Apple") in consideration of your agreement to
13 the following terms, and your use, installation, modification
14 or redistribution of this Apple software constitutes acceptance
15 of these terms. If you do not agree with these terms, please
16 do not use, install, modify or redistribute this Apple software.
17
18 In consideration of your agreement to abide by the following
19 terms, and subject to these terms, Apple grants you a personal,
20 non-exclusive license, under Apple's copyrights in this
21 original Apple software (the "Apple Software"), to use,
22 reproduce, modify and redistribute the Apple Software, with
23 or without modifications, in source and/or binary forms;
24 provided that if you redistribute the Apple Software in
25 its entirety and without modifications, you must retain
26 this notice and the following text and disclaimers in all
27 such redistributions of the Apple Software. Neither the
28 name, trademarks, service marks or logos of Apple Computer,
29 Inc. may be used to endorse or promote products derived from the
30 Apple Software without specific prior written permission from
31 Apple. Except as expressly stated in this notice, no other
32 rights or licenses, express or implied, are granted by Apple
33 herein, including but not limited to any patent rights that
34 may be infringed by your derivative works or by other works
35 in which the Apple Software may be incorporated.
36
37 The Apple Software is provided by Apple on an "AS IS" basis.
38 APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
39 WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
40 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
41 REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE
42 OR IN COMBINATION WITH YOUR PRODUCTS.
43
44 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
45 INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
49 AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
50 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING
51 NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE
52 HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55 #include "common.h"
56 #include <security_cdsa_utils/cuFileIo.h>
57 #include <stdio.h>
58 #include <string.h>
59 #include <stdlib.h>
60
61 static void usage(char **argv)
62 {
63 printf("usage:\n");
64 printf(" %s op password keySize inFile outFile [a=algorithm]\n", argv[0]);
65 printf(" op:\n");
66 printf(" e encrypt\n");
67 printf(" d decrypt\n");
68 printf(" algorithm:\n");
69 printf(" 4 RC4 (default if no algorithm specified)\n");
70 printf(" c ASC/ComCryption\n");
71 printf(" d DES\n");
72 printf(" a AES\n");
73 exit(1);
74 }
75
76 /*
77 * Derive symmetric key.
78 */
79 static CSSM_RETURN ctDeriveKey(CSSM_CSP_HANDLE cspHand,
80 uint32 keyAlg, // CSSM_ALGID_RC5, etc.
81 const char *keyLabel,
82 unsigned keyLabelLen,
83 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
84 uint32 keySizeInBits,
85 CSSM_DATA_PTR password, // in PKCS-5 lingo
86 CSSM_DATA_PTR salt, // ditto
87 uint32 iterationCnt, // ditto
88 CSSM_KEY_PTR key)
89 {
90 CSSM_RETURN crtn;
91 CSSM_CC_HANDLE ccHand;
92 uint32 keyAttr;
93 CSSM_DATA dummyLabel;
94 CSSM_PKCS5_PBKDF2_PARAMS pbeParams;
95 CSSM_DATA pbeData;
96 CSSM_ACCESS_CREDENTIALS creds;
97
98 memset(key, 0, sizeof(CSSM_KEY));
99 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
100 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
101 CSSM_ALGID_PKCS5_PBKDF2,
102 keyAlg,
103 keySizeInBits,
104 &creds,
105 NULL, // BaseKey
106 iterationCnt,
107 salt,
108 NULL, // seed
109 &ccHand);
110 if(crtn) {
111 printError("CSSM_CSP_CreateDeriveKeyContext", crtn);
112 return crtn;
113 }
114 keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF |
115 CSSM_KEYATTR_SENSITIVE;
116 dummyLabel.Length = keyLabelLen;
117 dummyLabel.Data = (uint8 *)keyLabel;
118
119 /* passing in password is pretty strange....*/
120 pbeParams.Passphrase = *password;
121 pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1;
122 pbeData.Data = (uint8 *)&pbeParams;
123 pbeData.Length = sizeof(pbeParams);
124 crtn = CSSM_DeriveKey(ccHand,
125 &pbeData,
126 keyUsage,
127 keyAttr,
128 &dummyLabel,
129 NULL, // cred and acl
130 key);
131 if(crtn) {
132 printError("CSSM_DeriveKey", crtn);
133 return crtn;
134 }
135 crtn = CSSM_DeleteContext(ccHand);
136 if(crtn) {
137 printError("CSSM_DeleteContext", crtn);
138 }
139 return crtn;
140 }
141
142
143 int main(int argc, char **argv)
144 {
145 int rtn;
146 uint32 keySizeInBytes; // from cmd line
147 char *password; // ASCII password from cmd line
148 char *inFileName; // from cmd line
149 unsigned char *inFile; // raw infile data
150 unsigned inFileSize; // in bytes
151 char *outFileName; // from cmd line
152 CSSM_CSP_HANDLE cspHand;
153 CSSM_RETURN crtn;
154 int doEncrypt = 0;
155 CSSM_DATA passwordData;
156 CSSM_DATA saltData = {8, (uint8 *)"someSalt"};
157 CSSM_DATA inData; // data to encrypt/decrypt, from inFile
158 CSSM_DATA outData = {0, NULL};// result data, written to outFile
159 CSSM_CC_HANDLE ccHand; // crypto context
160 CSSM_DATA remData = {0, NULL};
161 CSSM_SIZE bytesProcessed;
162 CSSM_KEY symKey;
163 char algSpec = '4';
164 CSSM_ALGORITHMS keyAlg = 0;
165 CSSM_ALGORITHMS encrAlg = 0;
166 CSSM_ENCRYPT_MODE encrMode = 0;
167 CSSM_PADDING padding = 0;
168 /* max of 16 bytes of init vector for the algs we use */
169 CSSM_DATA initVect = {16, (uint8 *)"someStrangeInitVector"};
170 CSSM_DATA_PTR initVectPtr = NULL;
171
172 if(argc < 6) {
173 usage(argv);
174 }
175
176 /* gather up cmd line args */
177 switch(argv[1][0]) {
178 case 'e':
179 doEncrypt = 1;
180 break;
181 case 'd':
182 doEncrypt = 0;
183 break;
184 default:
185 usage(argv);
186 }
187 password = argv[2];
188 passwordData.Data = (uint8 *)password;
189 passwordData.Length = strlen(password);
190 keySizeInBytes = atoi(argv[3]);
191 if(keySizeInBytes == 0) {
192 printf("keySize of 0 illegal\n");
193 exit(1);
194 }
195 inFileName = argv[4];
196 outFileName = argv[5];
197
198 /* optional algorithm specifier */
199 if(argc == 7) {
200 if(argv[6][0] != 'a') {
201 usage(argv);
202 }
203 algSpec = argv[6][2];
204 }
205
206 /* algorithm-specific parameters */
207 switch(algSpec) {
208 case '4':
209 /* RC4 stream cipher - no padding, no IV, variable key size */
210 keyAlg = CSSM_ALGID_RC4;
211 encrAlg = CSSM_ALGID_RC4;
212 encrMode = CSSM_ALGMODE_NONE;
213 padding = CSSM_PADDING_NONE;
214 break;
215 case 'c':
216 /* ComCryption stream cipher - no padding, no IV, variable key size */
217 keyAlg = CSSM_ALGID_ASC;
218 encrAlg = CSSM_ALGID_ASC;
219 encrMode = CSSM_ALGMODE_NONE;
220 padding = CSSM_PADDING_NONE;
221 break;
222 case 'd':
223 /* DES block cipher, block size = 8 bytes, fixed key size */
224 if(keySizeInBytes != 8) {
225 printf("***DES must have key size of 8 bytes\n");
226 exit(1);
227 }
228 keyAlg = CSSM_ALGID_DES;
229 encrAlg = CSSM_ALGID_DES;
230 encrMode = CSSM_ALGMODE_CBCPadIV8;
231 padding = CSSM_PADDING_PKCS7;
232 initVect.Length = 8;
233 initVectPtr = &initVect;
234 break;
235 case 'a':
236 /* AES block cipher, block size = 16 bytes, fixed key size */
237 if(keySizeInBytes != 16) {
238 printf("***AES must have key size of 8 bytes\n");
239 exit(1);
240 }
241 keyAlg = CSSM_ALGID_AES;
242 encrAlg = CSSM_ALGID_AES;
243 encrMode = CSSM_ALGMODE_CBCPadIV8;
244 padding = CSSM_PADDING_PKCS7;
245 initVect.Length = 16;
246 initVectPtr = &initVect;
247 break;
248 default:
249 usage(argv);
250 }
251
252 /* read inFile from disk */
253 rtn = readFile(inFileName, &inFile, &inFileSize);
254 if(rtn) {
255 printf("Error reading %s: %s\n", inFileName, strerror(rtn));
256 exit(1);
257 }
258 inData.Data = inFile;
259 inData.Length = inFileSize;
260
261 /* attach to CSP */
262 cspHand = cspStartup();
263 if(cspHand == 0) {
264 exit(1);
265 }
266
267 /*
268 * Derive an actual encryption/decryption key from the password ASCII text.
269 * We could use the ASCII text directly as key material but using the DeriveKey
270 * function is much more secure (besides being an industry-standard way to
271 * convert an ASCII password into binary key material).
272 */
273 crtn = ctDeriveKey(cspHand,
274 keyAlg,
275 "someLabel", // keyLabel, not important
276 9, // keyLabelLen
277 doEncrypt ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
278 keySizeInBytes * 8, // keySizeInBits,
279 &passwordData,
280 &saltData,
281 1000, // iterCount, 1000 is the minimum
282 &symKey);
283 if(crtn) {
284 exit(1);
285 }
286
287 /*
288 * Cook up a symmetric encrypt/decrypt context using the key we just derived
289 */
290 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
291 encrAlg, // encryption algorithm
292 encrMode, // mode
293 NULL, // access cred
294 &symKey,
295 initVectPtr, // InitVector
296 padding, // Padding
297 NULL, // Params
298 &ccHand);
299 if(crtn) {
300 printError("CSSM_CSP_CreateSymmetricContext", crtn);
301 exit(1);
302 }
303
304 /*
305 * Do the encrypt/decrypt.
306 * We do this with the init/update/final sequence only to demonstrate its
307 * usage.
308 */
309 if(doEncrypt) {
310 crtn = CSSM_EncryptDataInit(ccHand);
311 if(crtn) {
312 printError("CSSM_EncryptDataInit", crtn);
313 exit(1);
314 }
315
316 /* this step can be performed an arbitrary number of times, with
317 * the appropriate housekeeping of inData and outData */
318 crtn = CSSM_EncryptDataUpdate(ccHand,
319 &inData,
320 1,
321 &outData,
322 1,
323 &bytesProcessed);
324 if(crtn) {
325 printError("CSSM_EncryptDataUpdate", crtn);
326 exit(1);
327 }
328 outData.Length = bytesProcessed;
329
330 /* one call more to clean up */
331 crtn = CSSM_EncryptDataFinal(ccHand, &remData);
332 if(crtn) {
333 printError("CSSM_EncryptDataFinal", crtn);
334 exit(1);
335 }
336 if(remData.Length != 0) {
337 /* append remaining data to outData */
338 uint32 newLen = outData.Length + remData.Length;
339 outData.Data = (uint8 *)appRealloc(outData.Data,
340 newLen,
341 NULL);
342 memmove(outData.Data + outData.Length, remData.Data, remData.Length);
343 outData.Length = newLen;
344 appFree(remData.Data, NULL);
345 }
346 }
347 else {
348 crtn = CSSM_DecryptDataInit(ccHand);
349 if(crtn) {
350 printError("CSSM_DecryptDataInit", crtn);
351 exit(1);
352 }
353
354 /* this step can be performed an arbitrary number of times, with
355 * the appropriate housekeeping of inData and outData */
356 crtn = CSSM_DecryptDataUpdate(ccHand,
357 &inData,
358 1,
359 &outData,
360 1,
361 &bytesProcessed);
362 if(crtn) {
363 printError("CSSM_DecryptDataUpdate", crtn);
364 exit(1);
365 }
366 outData.Length = bytesProcessed;
367
368 /* one call more to clean up */
369 crtn = CSSM_DecryptDataFinal(ccHand, &remData);
370 if(crtn) {
371 printError("CSSM_DecryptDataFinal", crtn);
372 exit(1);
373 }
374 if(remData.Length != 0) {
375 /* append remaining data to outData */
376 uint32 newLen = outData.Length + remData.Length;
377 outData.Data = (uint8 *)appRealloc(outData.Data,
378 newLen,
379 NULL);
380 memmove(outData.Data + outData.Length, remData.Data, remData.Length);
381 outData.Length = newLen;
382 appFree(remData.Data, NULL);
383 }
384 }
385 if(crtn == CSSM_OK) {
386 rtn = writeFile(outFileName, outData.Data, outData.Length);
387 if(rtn) {
388 printf("Error writing %s: %s\n", outFileName, strerror(rtn));
389 exit(1);
390 }
391 else {
392 printf("SUCCESS: inFile length %u bytes, outFile length %u bytes\n",
393 inFileSize, (unsigned)outData.Length);
394 }
395 }
396 /* free resources */
397 crtn = CSSM_DeleteContext(ccHand);
398 if(crtn) {
399 printError("CSSM_DeleteContext", crtn);
400 }
401 crtn = CSSM_FreeKey(cspHand,
402 NULL, // access cred
403 &symKey,
404 CSSM_FALSE); // don't delete since it wasn't permanent
405 if(crtn) {
406 printError("CSSM_FreeKey", crtn);
407 }
408 free(inFile); // mallocd by readFile()
409
410 /* this was mallocd by CSP */
411 appFree(outData.Data, NULL);
412 CSSM_ModuleDetach(cspHand);
413 return rtn;
414 }
415