4 Description: simple encrypt/decrypt utility to demonstrate CDSA API
5 used for symmetric encryption
9 Copyright: Copyright (c) 2001,2003,2005-2006 Apple Computer, Inc. All Rights Reserved.
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.
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.
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.
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.
56 #include <security_cdsa_utils/cuFileIo.h>
61 static void usage(char **argv
)
64 printf(" %s op password keySize inFile outFile [a=algorithm]\n", argv
[0]);
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");
77 * Derive symmetric key.
79 static CSSM_RETURN
ctDeriveKey(CSSM_CSP_HANDLE cspHand
,
80 uint32 keyAlg
, // CSSM_ALGID_RC5, etc.
83 uint32 keyUsage
, // CSSM_KEYUSE_ENCRYPT, etc.
85 CSSM_DATA_PTR password
, // in PKCS-5 lingo
86 CSSM_DATA_PTR salt
, // ditto
87 uint32 iterationCnt
, // ditto
91 CSSM_CC_HANDLE ccHand
;
94 CSSM_PKCS5_PBKDF2_PARAMS pbeParams
;
96 CSSM_ACCESS_CREDENTIALS creds
;
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
,
111 printError("CSSM_CSP_CreateDeriveKeyContext", crtn
);
114 keyAttr
= CSSM_KEYATTR_EXTRACTABLE
| CSSM_KEYATTR_RETURN_REF
|
115 CSSM_KEYATTR_SENSITIVE
;
116 dummyLabel
.Length
= keyLabelLen
;
117 dummyLabel
.Data
= (uint8
*)keyLabel
;
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
,
129 NULL
, // cred and acl
132 printError("CSSM_DeriveKey", crtn
);
135 crtn
= CSSM_DeleteContext(ccHand
);
137 printError("CSSM_DeleteContext", crtn
);
143 int main(int argc
, char **argv
)
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
;
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
;
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
;
176 /* gather up cmd line args */
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");
195 inFileName
= argv
[4];
196 outFileName
= argv
[5];
198 /* optional algorithm specifier */
200 if(argv
[6][0] != 'a') {
203 algSpec
= argv
[6][2];
206 /* algorithm-specific parameters */
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
;
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
;
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");
228 keyAlg
= CSSM_ALGID_DES
;
229 encrAlg
= CSSM_ALGID_DES
;
230 encrMode
= CSSM_ALGMODE_CBCPadIV8
;
231 padding
= CSSM_PADDING_PKCS7
;
233 initVectPtr
= &initVect
;
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");
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
;
252 /* read inFile from disk */
253 rtn
= readFile(inFileName
, &inFile
, &inFileSize
);
255 printf("Error reading %s: %s\n", inFileName
, strerror(rtn
));
258 inData
.Data
= inFile
;
259 inData
.Length
= inFileSize
;
262 cspHand
= cspStartup();
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).
273 crtn
= ctDeriveKey(cspHand
,
275 "someLabel", // keyLabel, not important
277 doEncrypt
? CSSM_KEYUSE_ENCRYPT
: CSSM_KEYUSE_DECRYPT
,
278 keySizeInBytes
* 8, // keySizeInBits,
281 1000, // iterCount, 1000 is the minimum
288 * Cook up a symmetric encrypt/decrypt context using the key we just derived
290 crtn
= CSSM_CSP_CreateSymmetricContext(cspHand
,
291 encrAlg
, // encryption algorithm
295 initVectPtr
, // InitVector
300 printError("CSSM_CSP_CreateSymmetricContext", crtn
);
305 * Do the encrypt/decrypt.
306 * We do this with the init/update/final sequence only to demonstrate its
310 crtn
= CSSM_EncryptDataInit(ccHand
);
312 printError("CSSM_EncryptDataInit", crtn
);
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
,
325 printError("CSSM_EncryptDataUpdate", crtn
);
328 outData
.Length
= bytesProcessed
;
330 /* one call more to clean up */
331 crtn
= CSSM_EncryptDataFinal(ccHand
, &remData
);
333 printError("CSSM_EncryptDataFinal", crtn
);
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
,
342 memmove(outData
.Data
+ outData
.Length
, remData
.Data
, remData
.Length
);
343 outData
.Length
= newLen
;
344 appFree(remData
.Data
, NULL
);
348 crtn
= CSSM_DecryptDataInit(ccHand
);
350 printError("CSSM_DecryptDataInit", crtn
);
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
,
363 printError("CSSM_DecryptDataUpdate", crtn
);
366 outData
.Length
= bytesProcessed
;
368 /* one call more to clean up */
369 crtn
= CSSM_DecryptDataFinal(ccHand
, &remData
);
371 printError("CSSM_DecryptDataFinal", crtn
);
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
,
380 memmove(outData
.Data
+ outData
.Length
, remData
.Data
, remData
.Length
);
381 outData
.Length
= newLen
;
382 appFree(remData
.Data
, NULL
);
385 if(crtn
== CSSM_OK
) {
386 rtn
= writeFile(outFileName
, outData
.Data
, outData
.Length
);
388 printf("Error writing %s: %s\n", outFileName
, strerror(rtn
));
392 printf("SUCCESS: inFile length %u bytes, outFile length %u bytes\n",
393 inFileSize
, (unsigned)outData
.Length
);
397 crtn
= CSSM_DeleteContext(ccHand
);
399 printError("CSSM_DeleteContext", crtn
);
401 crtn
= CSSM_FreeKey(cspHand
,
404 CSSM_FALSE
); // don't delete since it wasn't permanent
406 printError("CSSM_FreeKey", crtn
);
408 free(inFile
); // mallocd by readFile()
410 /* this was mallocd by CSP */
411 appFree(outData
.Data
, NULL
);
412 CSSM_ModuleDetach(cspHand
);