]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/ascTool/ascTool.cpp
Security-57031.30.12.tar.gz
[apple/security.git] / SecurityTests / cspxutils / ascTool / ascTool.cpp
1 /*
2 * ascCrypt.c - simple ASC (ComCryption) encrypt/decrypt utility
3 */
4
5 #include "cspwrap.h"
6 #include "common.h"
7 #include <security_cdsa_utils/cuFileIo.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <time.h>
12 #include <Security/cssm.h>
13 #include <Security/cssmapple.h>
14 #include <CoreFoundation/CoreFoundation.h>
15
16 static void usage(char **argv)
17 {
18 printf("usage:\n");
19 printf(" %s op password inFile outFile [k=keysize] [o=optimize]\n", argv[0]);
20 printf(" op:\n");
21 printf(" e encrypt\n");
22 printf(" d decrypt\n");
23 printf(" optimize:\n");
24 printf(" d default\n");
25 printf(" s size\n");
26 printf(" e Security\n");
27 printf(" t time\n");
28 printf(" z time+size\n");
29 printf(" a ASCII\n");
30 exit(1);
31 }
32
33 int main(int argc, char **argv)
34 {
35 int rtn;
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;
44 CSSM_RETURN crtn;
45 int doEncrypt = 0;
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
50 CSSM_KEY_PTR symKey;
51 int arg;
52 char *argp;
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};
58
59 if(argc < 5) {
60 usage(argv);
61 }
62
63 /* gather up cmd line args */
64 switch(argv[1][0]) {
65 case 'e':
66 doEncrypt = 1;
67 break;
68 case 'd':
69 doEncrypt = 0;
70 break;
71 default:
72 usage(argv);
73 }
74 password = argv[2];
75 passwordData.Data = (uint8 *)password;
76 passwordData.Length = strlen(password);
77 inFileName = argv[3];
78 outFileName = argv[4];
79
80 /* optional args */
81 for(arg=5; arg<argc; arg++) {
82 argp = argv[arg];
83 switch(argp[0]) {
84 case 'k':
85 keySizeInBytes = atoi(&argp[2]);
86 if(keySizeInBytes == 0) {
87 printf("keySize of 0 illegal\n");
88 exit(1);
89 }
90 break;
91 case 'o':
92 switch(argp[2]) {
93 case 'd':
94 optimize = CSSM_ASC_OPTIMIZE_DEFAULT;
95 break;
96 case 's':
97 optimize = CSSM_ASC_OPTIMIZE_SIZE;
98 break;
99 case 'e':
100 optimize = CSSM_ASC_OPTIMIZE_SECURITY;
101 break;
102 case 't':
103 optimize = CSSM_ASC_OPTIMIZE_TIME;
104 break;
105 case 'z':
106 optimize = CSSM_ASC_OPTIMIZE_TIME_SIZE;
107 break;
108 case 'a':
109 optimize = CSSM_ASC_OPTIMIZE_ASCII;
110 break;
111 default:
112 usage(argv);
113 }
114 break;
115 default:
116 usage(argv);
117 }
118 }
119
120 /* read inFile from disk */
121 rtn = readFile(inFileName, &inFile, &inFileSize);
122 if(rtn) {
123 printf("Error reading %s: %s\n", inFileName, strerror(rtn));
124 exit(1);
125 }
126 inData.Data = inFile;
127 inData.Length = inFileSize;
128
129 /* attach to CSP */
130 cspHand = cspStartup();
131 if(cspHand == 0) {
132 exit(1);
133 }
134
135 /*
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).
140 */
141 symKey = cspDeriveKey(cspHand,
142 CSSM_ALGID_PKCS5_PBKDF2,
143 CSSM_ALGID_ASC,
144 "someLabel", // keyLabel, not important
145 9, // keyLabelLen
146 doEncrypt ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
147 keySizeInBytes * 8, // keySizeInBits,
148 CSSM_FALSE, // raw key
149 &passwordData,
150 &saltData,
151 1000, // iterCount, 1000 is the minimum
152 &iv);
153 if(symKey == NULL) {
154 exit(1);
155 }
156
157 /*
158 * Cook up a symmetric encrypt/decrypt context using the key we just derived
159 */
160 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
161 CSSM_ALGID_ASC, // encryption algorithm
162 CSSM_ALGMODE_NONE, // mode
163 NULL, // access cred
164 symKey,
165 NULL, // InitVector
166 CSSM_PADDING_NONE, // Padding
167 NULL, // Params
168 &ccHand);
169 if(crtn) {
170 printError("CSSM_CSP_CreateSymmetricContext", crtn);
171 exit(1);
172 }
173
174 /* add in optimal optimization attribute */
175 if(optimize != CSSM_ASC_OPTIMIZE_DEFAULT) {
176 crtn = AddContextAttribute(ccHand,
177 CSSM_ATTRIBUTE_ASC_OPTIMIZATION,
178 sizeof(uint32),
179 CAT_Uint32,
180 NULL,
181 optimize);
182 if(crtn) {
183 exit(1);
184 }
185 }
186
187 /*
188 * Do the encrypt/decrypt.
189 */
190 start = CFAbsoluteTimeGetCurrent();
191 if(doEncrypt) {
192 crtn = CSSM_EncryptDataInit(ccHand);
193 if(crtn) {
194 printError("CSSM_EncryptDataInit", crtn);
195 exit(1);
196 }
197
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,
201 &inData,
202 1,
203 &outData,
204 1,
205 &bytesProcessed);
206 if(crtn) {
207 printError("CSSM_EncryptDataUpdate", crtn);
208 exit(1);
209 }
210 outData.Length = bytesProcessed;
211
212 /* one call more to clean up */
213 crtn = CSSM_EncryptDataFinal(ccHand, &remData);
214 if(crtn) {
215 printError("CSSM_EncryptDataFinal", crtn);
216 exit(1);
217 }
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,
222 newLen,
223 NULL);
224 memmove(outData.Data + outData.Length, remData.Data, remData.Length);
225 outData.Length = newLen;
226 appFree(remData.Data, NULL);
227 }
228 }
229 else {
230 crtn = CSSM_DecryptDataInit(ccHand);
231 if(crtn) {
232 printError("CSSM_DecryptDataInit", crtn);
233 exit(1);
234 }
235
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,
239 &inData,
240 1,
241 &outData,
242 1,
243 &bytesProcessed);
244 if(crtn) {
245 printError("CSSM_DecryptDataUpdate", crtn);
246 exit(1);
247 }
248 outData.Length = bytesProcessed;
249
250 /* one call more to clean up */
251 crtn = CSSM_DecryptDataFinal(ccHand, &remData);
252 if(crtn) {
253 printError("CSSM_DecryptDataFinal", crtn);
254 exit(1);
255 }
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,
260 newLen,
261 NULL);
262 memmove(outData.Data + outData.Length, remData.Data, remData.Length);
263 outData.Length = newLen;
264 appFree(remData.Data, NULL);
265 }
266 }
267
268 end = CFAbsoluteTimeGetCurrent();
269 if(crtn == CSSM_OK) {
270 double inSizeD = (double)inFileSize;
271 double outSizeD = (double)outData.Length;
272 CFAbsoluteTime delta = end - start;
273
274 rtn = writeFile(outFileName, outData.Data, outData.Length);
275 if(rtn) {
276 printf("Error writing %s: %s\n", outFileName, strerror(rtn));
277 exit(1);
278 }
279 printf(" inFile length %d bytes, outFile length %lu bytes, "
280 "%d ms\n",
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);
285 }
286
287 /* free key, outData, etc. */
288 CSSM_ModuleDetach(cspHand);
289 return rtn;
290 }
291