]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/rsatool/rsatool.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / rsatool / rsatool.c
1 /*
2 * rsatool.c - RSA/DSA/ECDSA key pair generator, en/decrypt, sign/verify with file I/O
3 */
4
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <time.h>
8 #include <string.h>
9 #include <Security/cssm.h>
10 #include "cspwrap.h"
11 #include "common.h"
12 #include <security_cdsa_utils/cuFileIo.h>
13
14 /* For 3141770 - defined true when PR-3074739 merged to TOT Security */
15 #define OPENSSL_ENABLE 1
16
17 #define USAGE_NAME "noUsage"
18 #define USAGE_NAME_LEN (strlen(USAGE_NAME))
19 #define DEFAULT_KEY_SIZE_BITS 512
20
21 typedef struct {
22 CSSM_ALGORITHMS alg;
23 uint32 keySizeInBits;
24 CSSM_CSP_HANDLE cspHand;
25 char *keyFileName;
26 char *outKeyFileName; // for pub key convert
27 char *plainFileName;
28 char *sigFileName;
29 char *cipherFileName;
30 char *dsaParamFileIn;
31 char *dsaParamFileOut;
32 CSSM_BOOL swapKeyClass;
33 CSSM_BOOL rawSign;
34 CSSM_BOOL noPad;
35 CSSM_BOOL quiet;
36 CSSM_KEYBLOB_FORMAT pubKeyFormat; // FORMAT_NONE ==> default
37 CSSM_KEYBLOB_FORMAT privKeyFormat; // FORMAT_NONE ==> default
38 CSSM_KEYBLOB_FORMAT outPubKeyFormat;// FORMAT_NONE ==> default, for pub key convert
39 CSSM_ALGORITHMS digestAlg; // optional digest alg for raw sign/verify
40 } opParams;
41
42 static void usage(char **argv)
43 {
44 printf("usage: %s op [options]\n", argv[0]);
45 printf(" op:\n");
46 printf(" g generate key pair\n");
47 printf(" e encrypt\n");
48 printf(" d decrypt\n");
49 printf(" s sign\n");
50 printf(" v verify\n");
51 printf(" S SHA-1 digest\n");
52 printf(" M MD5 digest\n");
53 printf(" C convert public key format\n");
54 printf(" options:\n");
55 printf(" k=keyfileBase keys are keyFileBase_pub.der, "
56 "keyFileBase_priv.der)\n");
57 printf(" K=outputPublicKey\n");
58 printf(" p=plainFile\n");
59 printf(" c=cipherFile\n");
60 printf(" s=sigfile\n");
61 printf(" z=keySizeInBits (default %d)\n", DEFAULT_KEY_SIZE_BITS);
62 printf(" w (swap key class)\n");
63 printf(" r (raw sign/verify)\n");
64 printf(" P (no padding)\n");
65 printf(" d=digestAlg digestAlg: s(SHA1) 5(MD5) for raw signing\n");
66 printf(" m=dsaParamFileIn\n");
67 printf(" M=dsaParamFileOut (must specify one of dsaParamFile{In,Out}\n");
68 printf(" b=[1xboOL] (pub key in PKCS1/X509/BSAFE/OpenSSH1/OpenSSH2/OpenSSL form)\n");
69 printf(" RSA = {PKCS1,X509,OpenSSH1,OpenSSH2} default = PKCS1\n");
70 printf(" DSA = {BSAFE,X509,OpenSSH2} default = X509\n");
71 printf(" ECDSA = {X509, OpenSSL} default = X509\n");
72 printf(" Note: RSA and DSA public keys in OpenSSL form are X509.\n");
73 printf(" v=[18sbo] (priv key in PKCS1/PKCS8/OpenSSH/BSAFE/OpenSSL form)\n");
74 printf(" RSA = {PKCS1,PKCS8,OpenSSH1} default = PKCS8\n");
75 printf(" DSA = {BSAFE,OpenSSL,PKCS8} default = OpenSSL\n");
76 printf(" ECDSA = {PKCS8,OpenSSL} default = OpenSSL}\n");
77 printf(" Note: RSA private key in OpenSSL form is PKCS1.\n");
78 printf(" B=[1xboO] output public key format\n");
79 printf(" a=alg d=DSA, r=RSA, e=ECDSA; default = RSA\n");
80 printf(" q(uiet)\n");
81 exit(1);
82 }
83
84 /* NULL wrap a key to specified format. */
85 static CSSM_RETURN nullWrapKey(CSSM_CSP_HANDLE cspHand,
86 const CSSM_KEY *refKey,
87 CSSM_KEYBLOB_FORMAT blobFormat,
88 CSSM_KEY_PTR rawKey) // RETURNED
89 {
90 CSSM_CC_HANDLE ccHand;
91 CSSM_RETURN crtn;
92 CSSM_ACCESS_CREDENTIALS creds;
93 CSSM_DATA descData = {0, 0};
94
95 memset(rawKey, 0, sizeof(CSSM_KEY));
96 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
97 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
98 CSSM_ALGID_NONE,
99 CSSM_ALGMODE_NONE,
100 &creds, // passPhrase
101 NULL, // unwrappingKey
102 NULL, // initVector
103 CSSM_PADDING_NONE,
104 0, // Params
105 &ccHand);
106 if(crtn) {
107 printError("cspWrapKey/CreateContext", crtn);
108 return crtn;
109 }
110 if(blobFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) {
111 /* only add this attribute if it's not the default */
112 CSSM_ATTRIBUTE_TYPE attrType;
113
114 switch(refKey->KeyHeader.KeyClass) {
115 case CSSM_KEYCLASS_SESSION_KEY:
116 attrType = CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT;
117 break;
118 case CSSM_KEYCLASS_PUBLIC_KEY:
119 attrType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT;
120 break;
121 case CSSM_KEYCLASS_PRIVATE_KEY:
122 attrType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT;
123 break;
124 default:
125 printf("***Bogus KeyClass in nullWrapKey\n");
126 return -1;
127 }
128 CSSM_CONTEXT_ATTRIBUTE attr;
129 attr.AttributeType = attrType;
130 attr.AttributeLength = sizeof(uint32);
131 attr.Attribute.Uint32 = blobFormat;
132 crtn = CSSM_UpdateContextAttributes(
133 ccHand,
134 1,
135 &attr);
136 if(crtn) {
137 printError("CSSM_UpdateContextAttributes", crtn);
138 return crtn;
139 }
140 }
141 crtn = CSSM_WrapKey(ccHand,
142 &creds,
143 refKey,
144 &descData,
145 rawKey);
146 if(crtn != CSSM_OK) {
147 printError("CSSM_WrapKey", crtn);
148 }
149 if(CSSM_DeleteContext(ccHand)) {
150 printf("CSSM_DeleteContext failure\n");
151 }
152 return crtn;
153 }
154
155 /*
156 * Sign/verify optional "no padding" context attr
157 */
158 static CSSM_RETURN sigSign(CSSM_CSP_HANDLE cspHand,
159 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
160 CSSM_KEY_PTR key, // private key
161 const CSSM_DATA *text,
162 CSSM_DATA_PTR sig,
163 uint32 digestAlg, // optional for raw signing
164 CSSM_BOOL noPad) // true --> add PADDING_NONE to context
165 {
166 CSSM_CC_HANDLE sigHand;
167 CSSM_RETURN crtn;
168
169 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
170 algorithm,
171 NULL, // passPhrase
172 key,
173 &sigHand);
174 if(crtn) {
175 printError("CSSM_CSP_CreateSignatureContext", crtn);
176 return crtn;
177 }
178 if(noPad) {
179 crtn = AddContextAttribute(sigHand,
180 CSSM_ATTRIBUTE_PADDING,
181 sizeof(uint32),
182 CAT_Uint32,
183 NULL,
184 CSSM_PADDING_NONE);
185 if(crtn) {
186 return crtn;
187 }
188 }
189 crtn = CSSM_SignData(sigHand,
190 text,
191 1,
192 digestAlg,
193 sig);
194 if(crtn) {
195 printError("CSSM_SignData", crtn);
196 }
197 CSSM_DeleteContext(sigHand);
198 return crtn;
199 }
200
201 static CSSM_RETURN sigVerify(CSSM_CSP_HANDLE cspHand,
202 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
203 CSSM_KEY_PTR key, // public key
204 const CSSM_DATA *text,
205 const CSSM_DATA *sig,
206 uint32 digestAlg, // optional for raw signing
207 CSSM_BOOL noPad) // true --> add PADDING_NONE to context
208 {
209 CSSM_CC_HANDLE sigHand;
210 CSSM_RETURN crtn;
211
212 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
213 algorithm,
214 NULL, // passPhrase
215 key,
216 &sigHand);
217 if(crtn) {
218 printError("CSSM_CSP_CreateSignatureContext", crtn);
219 return crtn;
220 }
221 if(noPad) {
222 crtn = AddContextAttribute(sigHand,
223 CSSM_ATTRIBUTE_PADDING,
224 sizeof(uint32),
225 CAT_Uint32,
226 NULL,
227 CSSM_PADDING_NONE);
228 if(crtn) {
229 return crtn;
230 }
231 }
232 crtn = CSSM_VerifyData(sigHand,
233 text,
234 1,
235 digestAlg,
236 sig);
237 if(crtn) {
238 printError("CSSM_VerifyData", crtn);
239 }
240 CSSM_DeleteContext(sigHand);
241 return crtn;
242 }
243
244 /*
245 * Generate DSA key pair. Algorithm parameters are
246 * either specified by caller via inParams, or are generated here
247 * and returned to caller in outParams. Exactly one of (inParams,
248 * outParams) must be non-NULL.
249 */
250 static CSSM_RETURN genDsaKeyPair(
251 CSSM_CSP_HANDLE cspHand,
252 const char *keyLabel,
253 unsigned keyLabelLen,
254 uint32 keySize, // in bits
255 CSSM_KEY_PTR pubKey, // mallocd by caller
256 CSSM_BOOL pubIsRef, // true - reference key, false - data
257 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
258 CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Some algorithms (currently, FEE)
259 // provide for multiple key blob formats.
260 // Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE
261 // to get the default format.
262 CSSM_KEY_PTR privKey, // mallocd by caller
263 CSSM_BOOL privIsRef, // true - reference key, false - data
264 uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc.
265 CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default
266 const CSSM_DATA *inParams, // optional
267 CSSM_DATA_PTR outParams) // optional, we malloc
268 {
269 CSSM_RETURN crtn;
270 CSSM_CC_HANDLE ccHand;
271 CSSM_DATA keyLabelData;
272 uint32 pubAttr;
273 uint32 privAttr;
274 CSSM_RETURN ocrtn = CSSM_OK;
275
276 /* Caller must specify either inParams or outParams, not both */
277 if(inParams && outParams) {
278 return CSSMERR_CSSM_INVALID_POINTER;
279 }
280 if(!inParams && !outParams) {
281 return CSSMERR_CSSM_INVALID_POINTER;
282 }
283
284 keyLabelData.Data = (uint8 *)keyLabel,
285 keyLabelData.Length = keyLabelLen;
286 memset(pubKey, 0, sizeof(CSSM_KEY));
287 memset(privKey, 0, sizeof(CSSM_KEY));
288
289 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
290 CSSM_ALGID_DSA,
291 keySize,
292 NULL, // Seed
293 NULL, // Salt
294 NULL, // StartDate
295 NULL, // EndDate
296 inParams, // Params, may be NULL
297 &ccHand);
298 if(crtn) {
299 printError("CSSM_CSP_CreateKeyGenContext", crtn);
300 return crtn;
301 }
302 /* cook up attribute bits */
303 if(pubIsRef) {
304 pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
305 }
306 else {
307 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
308 }
309 if(privIsRef) {
310 privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
311 }
312 else {
313 privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
314 }
315
316 if(outParams) {
317 /* explicitly generate params and return them to caller */
318 outParams->Data = NULL;
319 outParams->Length = 0;
320 crtn = CSSM_GenerateAlgorithmParams(ccHand,
321 keySize, outParams);
322 if(crtn) {
323 printError("CSSM_GenerateAlgorithmParams", crtn);
324 CSSM_DeleteContext(ccHand);
325 return crtn;
326 }
327 }
328
329 /* optional format specifiers */
330 if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) {
331 crtn = AddContextAttribute(ccHand,
332 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT,
333 sizeof(uint32),
334 CAT_Uint32,
335 NULL,
336 pubFormat);
337 if(crtn) {
338 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn);
339 return crtn;
340 }
341 }
342 if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) {
343 crtn = AddContextAttribute(ccHand,
344 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT,
345 sizeof(uint32),
346 CAT_Uint32,
347 NULL,
348 privFormat);
349 if(crtn) {
350 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn);
351 return crtn;
352 }
353 }
354 crtn = CSSM_GenerateKeyPair(ccHand,
355 pubKeyUsage,
356 pubAttr,
357 &keyLabelData,
358 pubKey,
359 privKeyUsage,
360 privAttr,
361 &keyLabelData, // same labels
362 NULL, // CredAndAclEntry
363 privKey);
364 if(crtn) {
365 printError("CSSM_GenerateKeyPair", crtn);
366 ocrtn = crtn;
367 }
368 if(ccHand != 0) {
369 crtn = CSSM_DeleteContext(ccHand);
370 if(crtn) {
371 printError("CSSM_DeleteContext", crtn);
372 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
373 }
374 }
375 return ocrtn;
376 }
377
378 /*
379 * Given keyFileBase, obtain name of public or private name. Output names
380 * mallocd by caller.
381 */
382 #define KEY_FILE_NAME_MAX_LEN 256
383
384 static void rtKeyFileName(
385 const char *keyFileBase,
386 CSSM_BOOL isPub,
387 char *outFileName)
388 {
389 if(isPub) {
390 sprintf(outFileName, "%s_pub.der", keyFileBase);
391 }
392 else {
393 sprintf(outFileName, "%s_priv.der", keyFileBase);
394 }
395 }
396
397 /*
398 * Given keyFileBase and key type, init a CSSM_KEY.
399 */
400 static int rt_readKey(
401 CSSM_CSP_HANDLE cspHand,
402 const char *keyFileBase,
403 CSSM_BOOL isPub,
404 CSSM_ALGORITHMS alg,
405 CSSM_KEYBLOB_FORMAT format, // FORMAT_NONE ==> default
406 CSSM_KEY_PTR key)
407 {
408 char fileName[KEY_FILE_NAME_MAX_LEN];
409 int irtn;
410 CSSM_DATA_PTR keyData = &key->KeyData;
411 CSSM_KEYHEADER_PTR hdr = &key->KeyHeader;
412 CSSM_RETURN crtn;
413 CSSM_KEY_SIZE keySize;
414 unsigned len;
415
416 memset(key, 0, sizeof(CSSM_KEY));
417 rtKeyFileName(keyFileBase, isPub, fileName);
418 irtn = readFile(fileName, &keyData->Data, &len);
419 if(irtn) {
420 printf("***error %d reading key file %s\n", irtn, fileName);
421 return irtn;
422 }
423 keyData->Length = len;
424 hdr->HeaderVersion = CSSM_KEYHEADER_VERSION;
425 hdr->BlobType = CSSM_KEYBLOB_RAW;
426 hdr->Format = format;
427 hdr->AlgorithmId = alg;
428 hdr->KeyClass = isPub ? CSSM_KEYCLASS_PUBLIC_KEY :
429 CSSM_KEYCLASS_PRIVATE_KEY;
430 hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
431 hdr->KeyUsage = CSSM_KEYUSE_ANY;
432
433 /* ask the CSP for key size */
434 crtn = CSSM_QueryKeySizeInBits(cspHand, 0, key, &keySize);
435 if(crtn) {
436 printError("CSSM_QueryKeySizeInBits", crtn);
437 return 1;
438 }
439 hdr->LogicalKeySizeInBits = keySize.LogicalKeySizeInBits;
440 return 0;
441 }
442
443 static int rt_generate(opParams *op)
444 {
445 CSSM_RETURN crtn;
446 CSSM_KEY pubKey;
447 CSSM_KEY privKey;
448 char fileName[KEY_FILE_NAME_MAX_LEN];
449 int irtn;
450 CSSM_DATA paramIn = {0, NULL};
451 CSSM_DATA paramOut = {0, NULL};
452 CSSM_DATA_PTR paramInPtr = NULL;
453 CSSM_DATA_PTR paramOutPtr = NULL;
454
455 if(op->keyFileName == NULL) {
456 printf("***Need a keyFileName to generate key pair.\n");
457 return 1;
458 }
459 memset(&pubKey, 0, sizeof(CSSM_KEY));
460 memset(&privKey, 0, sizeof(CSSM_KEY));
461
462 if(op->alg == CSSM_ALGID_DSA) {
463 /* must specify either inParams or outParams, not both */
464 if(op->dsaParamFileIn && op->dsaParamFileOut) {
465 printf("***DSA key generation requires one parameter file spec.\n");
466 return 1;
467 }
468 if(!op->dsaParamFileIn && !op->dsaParamFileOut) {
469 printf("***DSA key generation requires one parameter file spec.\n");
470 return 1;
471 }
472 if(op->dsaParamFileIn) {
473 /* caller-specified params */
474 unsigned len;
475 irtn = readFile(op->dsaParamFileIn, &paramIn.Data, &len);
476 if(irtn) {
477 printf("***Error reading DSA params from %s. Aborting.\n",
478 op->dsaParamFileIn);
479 }
480 paramIn.Length = len;
481 paramInPtr = &paramIn;
482 }
483 else {
484 /* generate params --> paramOut */
485 paramOutPtr = &paramOut;
486 }
487 crtn = genDsaKeyPair(op->cspHand,
488 USAGE_NAME,
489 USAGE_NAME_LEN,
490 op->keySizeInBits,
491 &pubKey,
492 CSSM_FALSE, // not ref
493 CSSM_KEYUSE_VERIFY, // not really important
494 op->pubKeyFormat,
495 &privKey,
496 CSSM_FALSE, // not ref
497 CSSM_KEYUSE_SIGN,
498 op->privKeyFormat,
499 paramInPtr,
500 paramOutPtr);
501 if(crtn) {
502 return 1;
503 }
504 if(paramOutPtr) {
505 irtn = writeFile(op->dsaParamFileOut, paramOut.Data, paramOut.Length);
506 if(irtn) {
507 printf("***Error writing DSA params to %s. Aborting.\n",
508 op->dsaParamFileOut);
509 return 1;
510 }
511 if(!op->quiet) {
512 printf("...wrote %lu bytes to %s\n", paramOut.Length,
513 op->dsaParamFileOut);
514 }
515 CSSM_FREE(paramOut.Data);
516 }
517 else {
518 /* mallocd by readFile() */
519 free(paramIn.Data);
520 }
521 }
522 else {
523 /* RSA, ECDSA */
524 crtn = cspGenKeyPair(op->cspHand,
525 op->alg,
526 USAGE_NAME,
527 USAGE_NAME_LEN,
528 op->keySizeInBits,
529 &pubKey,
530 CSSM_FALSE, // not ref
531 CSSM_KEYUSE_VERIFY, // not really important
532 op->pubKeyFormat,
533 &privKey,
534 CSSM_FALSE, // not ref
535 CSSM_KEYUSE_SIGN,
536 op->privKeyFormat,
537 CSSM_FALSE); // genSeed, not used here
538 if(crtn) {
539 return 1;
540 }
541 }
542
543 /* write the blobs */
544 rtKeyFileName(op->keyFileName, CSSM_TRUE, fileName);
545 irtn = writeFile(fileName, pubKey.KeyData.Data, pubKey.KeyData.Length);
546 if(irtn) {
547 printf("***Error %d writing to %s\n", irtn, fileName);
548 return irtn;
549 }
550 if(!op->quiet) {
551 printf("...wrote %lu bytes to %s\n", pubKey.KeyData.Length, fileName);
552 }
553 rtKeyFileName(op->keyFileName, CSSM_FALSE, fileName);
554 irtn = writeFile(fileName, privKey.KeyData.Data, privKey.KeyData.Length);
555 if(irtn) {
556 printf("***Error %d writing to %s\n", irtn, fileName);
557 return irtn;
558 }
559 if(!op->quiet) {
560 printf("...wrote %lu bytes to %s\n", privKey.KeyData.Length, fileName);
561 }
562 cspFreeKey(op->cspHand, &pubKey);
563 cspFreeKey(op->cspHand, &privKey);
564 return 0;
565 }
566
567 /* encrypt using public key */
568 static int rt_encrypt(opParams *op)
569 {
570 CSSM_KEY pubKey;
571 int irtn;
572 CSSM_DATA ptext;
573 CSSM_DATA ctext;
574 CSSM_RETURN crtn;
575 CSSM_BOOL isPub;
576 CSSM_ENCRYPT_MODE mode = CSSM_ALGMODE_NONE;
577 CSSM_KEYBLOB_FORMAT format = op->pubKeyFormat;
578 unsigned len;
579
580 if(op->keyFileName == NULL) {
581 printf("***Need a keyFileName to encrypt.\n");
582 return 1;
583 }
584 if((op->plainFileName == NULL) || (op->cipherFileName == NULL)) {
585 printf("***Need plainFileName and cipherFileName to encrypt.\n");
586 return 1;
587 }
588 if(op->swapKeyClass) {
589 isPub = CSSM_FALSE;
590 mode = CSSM_ALGMODE_PRIVATE_KEY;
591 format = op->privKeyFormat;
592 }
593 else {
594 isPub = CSSM_TRUE;
595 }
596 irtn = rt_readKey(op->cspHand, op->keyFileName, isPub, op->alg,
597 format, &pubKey);
598 if(irtn) {
599 return irtn;
600 }
601 irtn = readFile(op->plainFileName, &ptext.Data, &len);
602 if(irtn) {
603 printf("***Error reading %s\n", op->plainFileName);
604 return irtn;
605 }
606 ptext.Length = len;
607 ctext.Data = NULL;
608 ctext.Length = 0;
609
610 crtn = cspEncrypt(op->cspHand,
611 op->alg,
612 mode,
613 op->noPad ? CSSM_PADDING_NONE : CSSM_PADDING_PKCS1,
614 &pubKey,
615 NULL,
616 0, // effectiveKeySize
617 0, // rounds
618 NULL, // initVector
619 &ptext,
620 &ctext,
621 CSSM_FALSE); // mallocCtext
622 if(crtn) {
623 printError("cspEncrypt", crtn);
624 return 1;
625 }
626 irtn = writeFile(op->cipherFileName, ctext.Data, ctext.Length);
627 if(irtn) {
628 printf("***Error writing %s\n", op->cipherFileName);
629 }
630 else {
631 if(!op->quiet) {
632 printf("...wrote %lu bytes to %s\n", ctext.Length, op->cipherFileName);
633 }
634 }
635
636 free(pubKey.KeyData.Data); // allocd by rt_readKey --> readFile
637 free(ptext.Data); // allocd by readFile
638 appFreeCssmData(&ctext, CSSM_FALSE); // by CSP
639 return irtn;
640 }
641
642 /* decrypt using private key */
643 static int rt_decrypt(opParams *op)
644 {
645 CSSM_KEY privKey;
646 int irtn;
647 CSSM_DATA ptext;
648 CSSM_DATA ctext;
649 CSSM_RETURN crtn;
650 CSSM_BOOL isPub;
651 CSSM_ENCRYPT_MODE mode = CSSM_ALGMODE_NONE;
652 CSSM_KEYBLOB_FORMAT format = op->privKeyFormat;
653 unsigned len;
654
655 if(op->keyFileName == NULL) {
656 printf("***Need a keyFileName to decrypt.\n");
657 return 1;
658 }
659 if((op->plainFileName == NULL) || (op->cipherFileName == NULL)) {
660 printf("***Need plainFileName and cipherFileName to decrypt.\n");
661 return 1;
662 }
663 if(op->swapKeyClass) {
664 isPub = CSSM_TRUE;
665 mode = CSSM_ALGMODE_PUBLIC_KEY;
666 format = op->pubKeyFormat;
667 }
668 else {
669 isPub = CSSM_FALSE;
670 }
671 irtn = rt_readKey(op->cspHand, op->keyFileName, isPub, op->alg,
672 format, &privKey);
673 if(irtn) {
674 return irtn;
675 }
676 irtn = readFile(op->cipherFileName, &ctext.Data, &len);
677 if(irtn) {
678 printf("***Error reading %s\n", op->cipherFileName);
679 return irtn;
680 }
681 ctext.Length = len;
682 ptext.Data = NULL;
683 ptext.Length = 0;
684
685 crtn = cspDecrypt(op->cspHand,
686 op->alg,
687 mode,
688 op->noPad ? CSSM_PADDING_NONE : CSSM_PADDING_PKCS1,
689 &privKey,
690 NULL,
691 0, // effectiveKeySize
692 0, // rounds
693 NULL, // initVector
694 &ctext,
695 &ptext,
696 CSSM_FALSE); // mallocCtext
697 if(crtn) {
698 return 1;
699 }
700 irtn = writeFile(op->plainFileName, ptext.Data, ptext.Length);
701 if(irtn) {
702 printf("***Error writing %s\n", op->cipherFileName);
703 }
704 else {
705 if(!op->quiet) {
706 printf("...wrote %lu bytes to %s\n", ptext.Length, op->plainFileName);
707 }
708 }
709 free(privKey.KeyData.Data); // allocd by rt_readKey --> readFile
710 free(ctext.Data); // allocd by readFile
711 appFreeCssmData(&ptext, CSSM_FALSE); // by CSP
712 return irtn;
713 }
714
715 static int rt_sign(opParams *op)
716 {
717 CSSM_KEY privKey;
718 int irtn;
719 CSSM_DATA ptext;
720 CSSM_DATA sig;
721 CSSM_RETURN crtn;
722 CSSM_ALGORITHMS alg;
723 unsigned len;
724
725 if(op->keyFileName == NULL) {
726 printf("***Need a keyFileName to sign.\n");
727 return 1;
728 }
729 if((op->plainFileName == NULL) || (op->sigFileName == NULL)) {
730 printf("***Need plainFileName and sigFileName to sign.\n");
731 return 1;
732 }
733 irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_FALSE, op->alg,
734 op->privKeyFormat, &privKey);
735 if(irtn) {
736 return irtn;
737 }
738 irtn = readFile(op->plainFileName, &ptext.Data, &len);
739 if(irtn) {
740 printf("***Error reading %s\n", op->plainFileName);
741 return irtn;
742 }
743 ptext.Length = len;
744 sig.Data = NULL;
745 sig.Length = 0;
746 switch(op->alg) {
747 case CSSM_ALGID_RSA:
748 if(op->rawSign) {
749 alg = CSSM_ALGID_RSA;
750 }
751 else {
752 alg = CSSM_ALGID_SHA1WithRSA;
753 }
754 break;
755 case CSSM_ALGID_DSA:
756 alg = CSSM_ALGID_SHA1WithDSA;
757 break;
758 case CSSM_ALGID_ECDSA:
759 if(op->rawSign) {
760 alg = CSSM_ALGID_ECDSA;
761 }
762 else {
763 alg = CSSM_ALGID_SHA1WithECDSA;
764 }
765 break;
766 default:
767 printf("Hey! Try another alg!\n");
768 exit(1);
769 }
770 crtn = sigSign(op->cspHand,
771 alg,
772 &privKey,
773 &ptext,
774 &sig,
775 op->digestAlg,
776 op->noPad);
777 if(crtn) {
778 printError("cspSign", crtn);
779 return 1;
780 }
781 irtn = writeFile(op->sigFileName, sig.Data, sig.Length);
782 if(irtn) {
783 printf("***Error writing %s\n", op->sigFileName);
784 }
785 else if(!op->quiet) {
786 printf("...wrote %lu bytes to %s\n", sig.Length, op->sigFileName);
787 }
788 free(privKey.KeyData.Data); // allocd by rt_readKey --> readFile
789 free(ptext.Data); // allocd by readFile
790 appFreeCssmData(&sig, CSSM_FALSE); // by CSP
791 return irtn;
792 }
793
794 static int rt_verify(opParams *op)
795 {
796 CSSM_KEY pubKey;
797 int irtn;
798 CSSM_DATA ptext;
799 CSSM_DATA sig;
800 CSSM_RETURN crtn;
801 CSSM_ALGORITHMS alg;
802 unsigned len;
803
804 if(op->keyFileName == NULL) {
805 printf("***Need a keyFileName to verify.\n");
806 return 1;
807 }
808 if((op->plainFileName == NULL) || (op->sigFileName == NULL)) {
809 printf("***Need plainFileName and sigFileName to verify.\n");
810 return 1;
811 }
812 irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_TRUE, op->alg,
813 op->pubKeyFormat, &pubKey);
814 if(irtn) {
815 return irtn;
816 }
817 irtn = readFile(op->plainFileName, &ptext.Data, &len);
818 if(irtn) {
819 printf("***Error reading %s\n", op->plainFileName);
820 return irtn;
821 }
822 ptext.Length = len;
823 irtn = readFile(op->sigFileName, &sig.Data, (unsigned *)&sig.Length);
824 if(irtn) {
825 printf("***Error reading %s\n", op->sigFileName);
826 return irtn;
827 }
828 switch(op->alg) {
829 case CSSM_ALGID_RSA:
830 if(op->rawSign) {
831 alg = CSSM_ALGID_RSA;
832 }
833 else {
834 alg = CSSM_ALGID_SHA1WithRSA;
835 }
836 break;
837 case CSSM_ALGID_DSA:
838 alg = CSSM_ALGID_SHA1WithDSA;
839 break;
840 case CSSM_ALGID_ECDSA:
841 if(op->rawSign) {
842 alg = CSSM_ALGID_ECDSA;
843 }
844 else {
845 alg = CSSM_ALGID_SHA1WithECDSA;
846 }
847 break;
848 default:
849 printf("Hey! Try another alg!\n");
850 exit(1);
851 }
852 crtn = sigVerify(op->cspHand,
853 alg,
854 &pubKey,
855 &ptext,
856 &sig,
857 op->digestAlg,
858 op->noPad);
859 if(crtn) {
860 printError("sigVerify", crtn);
861 irtn = 1;
862 }
863 else if(!op->quiet){
864 printf("...signature verifies OK\n");
865 irtn = 0;
866 }
867 free(pubKey.KeyData.Data); // allocd by rt_readKey --> readFile
868 free(ptext.Data); // allocd by readFile
869 free(sig.Data); // ditto
870 return irtn;
871 }
872
873 static int rt_digest(opParams *op)
874 {
875 int irtn;
876 CSSM_DATA ptext;
877 CSSM_DATA digest = {0, NULL};
878 CSSM_RETURN crtn;
879 unsigned len;
880
881 if((op->plainFileName == NULL) || (op->sigFileName == NULL)) {
882 printf("***Need plainFileName and sigFileName to digest.\n");
883 return 1;
884 }
885 irtn = readFile(op->plainFileName, &ptext.Data, &len);
886 if(irtn) {
887 printf("***Error reading %s\n", op->plainFileName);
888 return irtn;
889 }
890 ptext.Length = len;
891 crtn = cspDigest(op->cspHand,
892 op->alg,
893 CSSM_FALSE, // mallocDigest - let CSP do it
894 &ptext,
895 &digest);
896 if(crtn) {
897 printError("cspDigest", crtn);
898 return 1;
899 }
900 irtn = writeFile(op->sigFileName, digest.Data, digest.Length);
901 if(irtn) {
902 printf("***Error writing %s\n", op->sigFileName);
903 }
904 else if(!op->quiet){
905 printf("...wrote %lu bytes to %s\n", digest.Length, op->sigFileName);
906 }
907 free(ptext.Data); // allocd by readFile
908 appFreeCssmData(&digest, CSSM_FALSE); // by CSP
909 return irtn;
910 }
911
912 static int rt_convertPubKey(opParams *op)
913 {
914 CSSM_RETURN crtn;
915 int irtn;
916 CSSM_KEY pubKeyIn;
917 CSSM_KEY pubKeyOut;
918 CSSM_KEY refKey;
919 char fileName[KEY_FILE_NAME_MAX_LEN];
920
921 if((op->keyFileName == NULL) || (op->outKeyFileName == NULL)) {
922 printf("***I need input and output key file names for public key concersion.\n");
923 return 1;
924 }
925 irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_TRUE, op->alg,
926 op->pubKeyFormat, &pubKeyIn);
927 if(irtn) {
928 return irtn;
929 }
930 crtn = cspRawKeyToRef(op->cspHand, &pubKeyIn, &refKey);
931 if(crtn) {
932 printf("***Error on NULL unwrap of %s\n", op->keyFileName);
933 return -1;
934 }
935 crtn = nullWrapKey(op->cspHand, &refKey, op->outPubKeyFormat, &pubKeyOut);
936 if(crtn) {
937 printf("***Error on NULL wrap\n");
938 return 1;
939 }
940
941 /* write the blobs */
942 rtKeyFileName(op->outKeyFileName, CSSM_TRUE, fileName);
943 irtn = writeFile(fileName, pubKeyOut.KeyData.Data, pubKeyOut.KeyData.Length);
944 if(irtn) {
945 printf("***Error %d writing to %s\n", irtn, fileName);
946 return irtn;
947 }
948 if(!op->quiet) {
949 printf("...wrote %lu bytes to %s\n", pubKeyOut.KeyData.Length, fileName);
950 }
951 cspFreeKey(op->cspHand, &pubKeyOut);
952 free(pubKeyIn.KeyData.Data);
953 cspFreeKey(op->cspHand, &refKey);
954 return 0;
955 }
956
957 /* parse public key format character */
958 static CSSM_KEYBLOB_FORMAT parsePubKeyFormat(char c, char **argv)
959 {
960 switch(c) {
961 case '1':
962 return CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
963 case 'x':
964 return CSSM_KEYBLOB_RAW_FORMAT_X509;
965 case 'b':
966 return CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
967 case 'o':
968 return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH;
969 case 'O':
970 return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2;
971 case 'L':
972 /* This is the "parse a private+public key as public only" option */
973 return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL;
974 default:
975 usage(argv);
976 }
977 /* not reached */
978 return -1;
979 }
980
981 int main(int argc, char **argv)
982 {
983 int arg;
984 char *argp;
985 int rtn;
986 opParams op;
987
988 if(argc < 2) {
989 usage(argv);
990 }
991 memset(&op, 0, sizeof(opParams));
992 op.keySizeInBits = DEFAULT_KEY_SIZE_BITS;
993 op.alg = CSSM_ALGID_RSA;
994 op.swapKeyClass = CSSM_FALSE;
995 op.rawSign = CSSM_FALSE;
996 op.noPad = CSSM_FALSE;
997
998 for(arg=2; arg<argc; arg++) {
999 argp = argv[arg];
1000 switch(argp[0]) {
1001 case 'a':
1002 if(argp[1] != '=') {
1003 usage(argv);
1004 }
1005 switch(argp[2]) {
1006 case 'r':
1007 op.alg = CSSM_ALGID_RSA;
1008 break;
1009 case 'd':
1010 op.alg = CSSM_ALGID_DSA;
1011 break;
1012 case 'e':
1013 op.alg = CSSM_ALGID_ECDSA;
1014 break;
1015 default:
1016 usage(argv);
1017 }
1018 break;
1019 case 'z':
1020 op.keySizeInBits = atoi(&argp[2]);
1021 break;
1022 case 'k':
1023 op.keyFileName = &argp[2];
1024 break;
1025 case 'K':
1026 op.outKeyFileName = &argp[2];
1027 break;
1028 case 'p':
1029 op.plainFileName = &argp[2];
1030 break;
1031 case 'c':
1032 op.cipherFileName = &argp[2];
1033 break;
1034 case 's':
1035 op.sigFileName = &argp[2];
1036 break;
1037 case 'w':
1038 op.swapKeyClass = CSSM_TRUE;
1039 break;
1040 case 'r':
1041 op.rawSign = CSSM_TRUE;
1042 break;
1043 case 'P':
1044 op.noPad = CSSM_TRUE;
1045 break;
1046 case 'm':
1047 op.dsaParamFileIn = &argp[2];
1048 break;
1049 case 'M':
1050 op.dsaParamFileOut = &argp[2];
1051 break;
1052 case 'q':
1053 op.quiet = CSSM_TRUE;
1054 break;
1055 case 'b':
1056 if(argp[1] != '=') {
1057 usage(argv);
1058 }
1059 op.pubKeyFormat = parsePubKeyFormat(argp[2], argv);
1060 break;
1061 case 'B':
1062 if(argp[1] != '=') {
1063 usage(argv);
1064 }
1065 op.outPubKeyFormat = parsePubKeyFormat(argp[2], argv);
1066 break;
1067 case 'v':
1068 if(argp[1] != '=') {
1069 usage(argv);
1070 }
1071 switch(argp[2]) {
1072 case '1':
1073 op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
1074 break;
1075 case '8':
1076 op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
1077 break;
1078 case 's':
1079 op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH;
1080 break;
1081 case 'b':
1082 op.pubKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
1083 break;
1084 #if OPENSSL_ENABLE
1085 case 'o':
1086 op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL;
1087 break;
1088 #endif
1089 default:
1090 usage(argv);
1091 }
1092 break;
1093 case 'd':
1094 if(argp[1] != '=') {
1095 usage(argv);
1096 }
1097 switch(argp[2]) {
1098 case 's':
1099 op.digestAlg = CSSM_ALGID_SHA1;
1100 break;
1101 case '5':
1102 op.digestAlg = CSSM_ALGID_MD5;
1103 break;
1104 default:
1105 usage(argv);
1106 }
1107 break;
1108 case 'h':
1109 default:
1110 usage(argv);
1111 }
1112 }
1113 op.cspHand = cspDlDbStartup(CSSM_TRUE, NULL);
1114 if(op.cspHand == 0) {
1115 exit(1);
1116 }
1117
1118 /* specify blob formats if user didn't */
1119 if(op.pubKeyFormat == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
1120 switch(op.alg) {
1121 case CSSM_ALGID_RSA:
1122 op.pubKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
1123 break;
1124 case CSSM_ALGID_DSA:
1125 case CSSM_ALGID_ECDSA:
1126 op.pubKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_X509;
1127 break;
1128 default:
1129 printf("BRRZAP!\n");
1130 exit(1);
1131 }
1132 }
1133 if(op.privKeyFormat == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
1134 switch(op.alg) {
1135 case CSSM_ALGID_RSA:
1136 op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
1137 break;
1138 case CSSM_ALGID_DSA:
1139 op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
1140 break;
1141 case CSSM_ALGID_ECDSA:
1142 op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL;
1143 break;
1144 default:
1145 printf("BRRZAP!\n");
1146 exit(1);
1147 }
1148 }
1149 switch(argv[1][0]) {
1150 case 'g':
1151 rtn = rt_generate(&op);
1152 break;
1153 case 'e':
1154 rtn = rt_encrypt(&op);
1155 break;
1156 case 'd':
1157 rtn = rt_decrypt(&op);
1158 break;
1159 case 's':
1160 rtn = rt_sign(&op);
1161 break;
1162 case 'v':
1163 rtn = rt_verify(&op);
1164 break;
1165 case 'S':
1166 op.alg = CSSM_ALGID_SHA1;
1167 rtn = rt_digest(&op);
1168 break;
1169 case 'M':
1170 op.alg = CSSM_ALGID_MD5;
1171 rtn = rt_digest(&op);
1172 break;
1173 case 'C':
1174 rtn = rt_convertPubKey(&op);
1175 break;
1176 default:
1177 usage(argv);
1178 exit(1); // fool the compiler
1179 }
1180 CSSM_ModuleDetach(op.cspHand);
1181 return rtn;
1182 }