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 16static 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 33int 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 292