2 * ascCrypt.c - simple ASC (ComCryption) encrypt/decrypt utility
7 #include <security_cdsa_utils/cuFileIo.h>
12 #include <Security/cssm.h>
13 #include <Security/cssmapple.h>
14 #include <CoreFoundation/CoreFoundation.h>
16 static void usage(char **argv
)
19 printf(" %s op password inFile outFile [k=keysize] [o=optimize]\n", argv
[0]);
21 printf(" e encrypt\n");
22 printf(" d decrypt\n");
23 printf(" optimize:\n");
24 printf(" d default\n");
26 printf(" e Security\n");
28 printf(" z time+size\n");
33 int main(int argc
, char **argv
)
36 uint32 keySizeInBytes
= CSP_ASC_KEY_SIZE_DEFAULT
/ 8;
37 uint32 optimize
= CSSM_ASC_OPTIMIZE_DEFAULT
;
38 char *password
; // ASCII password from cmd line
39 char *inFileName
; // from cmd line
40 unsigned char *inFile
; // raw infile data
41 unsigned inFileSize
; // in bytes
42 char *outFileName
; // from cmd line
43 CSSM_CSP_HANDLE cspHand
;
46 CSSM_DATA passwordData
;
47 CSSM_DATA saltData
= {8, (uint8
*)"someSalt"};
48 CSSM_DATA inData
; // data to encrypt/decrypt, from inFile
49 CSSM_DATA outData
= {0, NULL
};// result data, written to outFile
53 CFAbsoluteTime start
, end
;
54 CSSM_CC_HANDLE ccHand
; // crypto context
55 CSSM_DATA remData
= {0, NULL
};
56 CSSM_SIZE bytesProcessed
;
57 CSSM_DATA iv
= {0, NULL
};
63 /* gather up cmd line args */
75 passwordData
.Data
= (uint8
*)password
;
76 passwordData
.Length
= strlen(password
);
78 outFileName
= argv
[4];
81 for(arg
=5; arg
<argc
; arg
++) {
85 keySizeInBytes
= atoi(&argp
[2]);
86 if(keySizeInBytes
== 0) {
87 printf("keySize of 0 illegal\n");
94 optimize
= CSSM_ASC_OPTIMIZE_DEFAULT
;
97 optimize
= CSSM_ASC_OPTIMIZE_SIZE
;
100 optimize
= CSSM_ASC_OPTIMIZE_SECURITY
;
103 optimize
= CSSM_ASC_OPTIMIZE_TIME
;
106 optimize
= CSSM_ASC_OPTIMIZE_TIME_SIZE
;
109 optimize
= CSSM_ASC_OPTIMIZE_ASCII
;
120 /* read inFile from disk */
121 rtn
= readFile(inFileName
, &inFile
, &inFileSize
);
123 printf("Error reading %s: %s\n", inFileName
, strerror(rtn
));
126 inData
.Data
= inFile
;
127 inData
.Length
= inFileSize
;
130 cspHand
= cspStartup();
136 * Derive an actual encryption/decryption key from the password ASCII text.
137 * We could use the ASCII text directly as key material but using the DeriveKey
138 * function is much more secure (besides being an industry-standard way to
139 * convert an ASCII password into binary key material).
141 symKey
= cspDeriveKey(cspHand
,
142 CSSM_ALGID_PKCS5_PBKDF2
,
144 "someLabel", // keyLabel, not important
146 doEncrypt
? CSSM_KEYUSE_ENCRYPT
: CSSM_KEYUSE_DECRYPT
,
147 keySizeInBytes
* 8, // keySizeInBits,
148 CSSM_FALSE
, // raw key
151 1000, // iterCount, 1000 is the minimum
158 * Cook up a symmetric encrypt/decrypt context using the key we just derived
160 crtn
= CSSM_CSP_CreateSymmetricContext(cspHand
,
161 CSSM_ALGID_ASC
, // encryption algorithm
162 CSSM_ALGMODE_NONE
, // mode
166 CSSM_PADDING_NONE
, // Padding
170 printError("CSSM_CSP_CreateSymmetricContext", crtn
);
174 /* add in optimal optimization attribute */
175 if(optimize
!= CSSM_ASC_OPTIMIZE_DEFAULT
) {
176 crtn
= AddContextAttribute(ccHand
,
177 CSSM_ATTRIBUTE_ASC_OPTIMIZATION
,
188 * Do the encrypt/decrypt.
190 start
= CFAbsoluteTimeGetCurrent();
192 crtn
= CSSM_EncryptDataInit(ccHand
);
194 printError("CSSM_EncryptDataInit", crtn
);
198 /* this step can be performed an arbitrary number of times, with
199 * the appropriate housekeeping of inData and outData */
200 crtn
= CSSM_EncryptDataUpdate(ccHand
,
207 printError("CSSM_EncryptDataUpdate", crtn
);
210 outData
.Length
= bytesProcessed
;
212 /* one call more to clean up */
213 crtn
= CSSM_EncryptDataFinal(ccHand
, &remData
);
215 printError("CSSM_EncryptDataFinal", crtn
);
218 if(remData
.Length
!= 0) {
219 /* append remaining data to outData */
220 uint32 newLen
= outData
.Length
+ remData
.Length
;
221 outData
.Data
= (uint8
*)appRealloc(outData
.Data
,
224 memmove(outData
.Data
+ outData
.Length
, remData
.Data
, remData
.Length
);
225 outData
.Length
= newLen
;
226 appFree(remData
.Data
, NULL
);
230 crtn
= CSSM_DecryptDataInit(ccHand
);
232 printError("CSSM_DecryptDataInit", crtn
);
236 /* this step can be performed an arbitrary number of times, with
237 * the appropriate housekeeping of inData and outData */
238 crtn
= CSSM_DecryptDataUpdate(ccHand
,
245 printError("CSSM_DecryptDataUpdate", crtn
);
248 outData
.Length
= bytesProcessed
;
250 /* one call more to clean up */
251 crtn
= CSSM_DecryptDataFinal(ccHand
, &remData
);
253 printError("CSSM_DecryptDataFinal", crtn
);
256 if(remData
.Length
!= 0) {
257 /* append remaining data to outData */
258 uint32 newLen
= outData
.Length
+ remData
.Length
;
259 outData
.Data
= (uint8
*)appRealloc(outData
.Data
,
262 memmove(outData
.Data
+ outData
.Length
, remData
.Data
, remData
.Length
);
263 outData
.Length
= newLen
;
264 appFree(remData
.Data
, NULL
);
268 end
= CFAbsoluteTimeGetCurrent();
269 if(crtn
== CSSM_OK
) {
270 double inSizeD
= (double)inFileSize
;
271 double outSizeD
= (double)outData
.Length
;
272 CFAbsoluteTime delta
= end
- start
;
274 rtn
= writeFile(outFileName
, outData
.Data
, outData
.Length
);
276 printf("Error writing %s: %s\n", outFileName
, strerror(rtn
));
279 printf(" inFile length %d bytes, outFile length %lu bytes, "
281 inFileSize
, outData
.Length
, (unsigned)(delta
* 1000.0));
282 printf(" compression = %.2f %.2f KBytes/s\n",
283 doEncrypt
? outSizeD
/ inSizeD
: inSizeD
/ outSizeD
,
284 inSizeD
/ delta
/ 1024.0);
287 /* free key, outData, etc. */
288 CSSM_ModuleDetach(cspHand
);