#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <Security/cssm.h>
#include "cspwrap.h"
#include "common.h"
#include <security_cdsa_utils/cuFileIo.h>
#define OPENSSL_ENABLE 1
#define USAGE_NAME "noUsage"
#define USAGE_NAME_LEN (strlen(USAGE_NAME))
#define DEFAULT_KEY_SIZE_BITS 512
typedef struct {
CSSM_ALGORITHMS alg;
uint32 keySizeInBits;
CSSM_CSP_HANDLE cspHand;
char *keyFileName;
char *outKeyFileName; char *plainFileName;
char *sigFileName;
char *cipherFileName;
char *dsaParamFileIn;
char *dsaParamFileOut;
CSSM_BOOL swapKeyClass;
CSSM_BOOL rawSign;
CSSM_BOOL noPad;
CSSM_BOOL quiet;
CSSM_KEYBLOB_FORMAT pubKeyFormat; CSSM_KEYBLOB_FORMAT privKeyFormat; CSSM_KEYBLOB_FORMAT outPubKeyFormat; CSSM_ALGORITHMS digestAlg; } opParams;
static void usage(char **argv)
{
printf("usage: %s op [options]\n", argv[0]);
printf(" op:\n");
printf(" g generate key pair\n");
printf(" e encrypt\n");
printf(" d decrypt\n");
printf(" s sign\n");
printf(" v verify\n");
printf(" S SHA-1 digest\n");
printf(" M MD5 digest\n");
printf(" C convert public key format\n");
printf(" options:\n");
printf(" k=keyfileBase keys are keyFileBase_pub.der, "
"keyFileBase_priv.der)\n");
printf(" K=outputPublicKey\n");
printf(" p=plainFile\n");
printf(" c=cipherFile\n");
printf(" s=sigfile\n");
printf(" z=keySizeInBits (default %d)\n", DEFAULT_KEY_SIZE_BITS);
printf(" w (swap key class)\n");
printf(" r (raw sign/verify)\n");
printf(" P (no padding)\n");
printf(" d=digestAlg digestAlg: s(SHA1) 5(MD5) for raw signing\n");
printf(" m=dsaParamFileIn\n");
printf(" M=dsaParamFileOut (must specify one of dsaParamFile{In,Out}\n");
printf(" b=[1xboOL] (pub key in PKCS1/X509/BSAFE/OpenSSH1/OpenSSH2/OpenSSL form)\n");
printf(" RSA = {PKCS1,X509,OpenSSH1,OpenSSH2} default = PKCS1\n");
printf(" DSA = {BSAFE,X509,OpenSSH2} default = X509\n");
printf(" ECDSA = {X509, OpenSSL} default = X509\n");
printf(" Note: RSA and DSA public keys in OpenSSL form are X509.\n");
printf(" v=[18sbo] (priv key in PKCS1/PKCS8/OpenSSH/BSAFE/OpenSSL form)\n");
printf(" RSA = {PKCS1,PKCS8,OpenSSH1} default = PKCS8\n");
printf(" DSA = {BSAFE,OpenSSL,PKCS8} default = OpenSSL\n");
printf(" ECDSA = {PKCS8,OpenSSL} default = OpenSSL}\n");
printf(" Note: RSA private key in OpenSSL form is PKCS1.\n");
printf(" B=[1xboO] output public key format\n");
printf(" a=alg d=DSA, r=RSA, e=ECDSA; default = RSA\n");
printf(" q(uiet)\n");
exit(1);
}
static CSSM_RETURN nullWrapKey(CSSM_CSP_HANDLE cspHand,
const CSSM_KEY *refKey,
CSSM_KEYBLOB_FORMAT blobFormat,
CSSM_KEY_PTR rawKey) {
CSSM_CC_HANDLE ccHand;
CSSM_RETURN crtn;
CSSM_ACCESS_CREDENTIALS creds;
CSSM_DATA descData = {0, 0};
memset(rawKey, 0, sizeof(CSSM_KEY));
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
CSSM_ALGID_NONE,
CSSM_ALGMODE_NONE,
&creds, NULL, NULL, CSSM_PADDING_NONE,
0, &ccHand);
if(crtn) {
printError("cspWrapKey/CreateContext", crtn);
return crtn;
}
if(blobFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) {
CSSM_ATTRIBUTE_TYPE attrType;
switch(refKey->KeyHeader.KeyClass) {
case CSSM_KEYCLASS_SESSION_KEY:
attrType = CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT;
break;
case CSSM_KEYCLASS_PUBLIC_KEY:
attrType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT;
break;
case CSSM_KEYCLASS_PRIVATE_KEY:
attrType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT;
break;
default:
printf("***Bogus KeyClass in nullWrapKey\n");
return -1;
}
CSSM_CONTEXT_ATTRIBUTE attr;
attr.AttributeType = attrType;
attr.AttributeLength = sizeof(uint32);
attr.Attribute.Uint32 = blobFormat;
crtn = CSSM_UpdateContextAttributes(
ccHand,
1,
&attr);
if(crtn) {
printError("CSSM_UpdateContextAttributes", crtn);
return crtn;
}
}
crtn = CSSM_WrapKey(ccHand,
&creds,
refKey,
&descData,
rawKey);
if(crtn != CSSM_OK) {
printError("CSSM_WrapKey", crtn);
}
if(CSSM_DeleteContext(ccHand)) {
printf("CSSM_DeleteContext failure\n");
}
return crtn;
}
static CSSM_RETURN sigSign(CSSM_CSP_HANDLE cspHand,
uint32 algorithm, CSSM_KEY_PTR key, const CSSM_DATA *text,
CSSM_DATA_PTR sig,
uint32 digestAlg, CSSM_BOOL noPad) {
CSSM_CC_HANDLE sigHand;
CSSM_RETURN crtn;
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
algorithm,
NULL, key,
&sigHand);
if(crtn) {
printError("CSSM_CSP_CreateSignatureContext", crtn);
return crtn;
}
if(noPad) {
crtn = AddContextAttribute(sigHand,
CSSM_ATTRIBUTE_PADDING,
sizeof(uint32),
CAT_Uint32,
NULL,
CSSM_PADDING_NONE);
if(crtn) {
return crtn;
}
}
crtn = CSSM_SignData(sigHand,
text,
1,
digestAlg,
sig);
if(crtn) {
printError("CSSM_SignData", crtn);
}
CSSM_DeleteContext(sigHand);
return crtn;
}
static CSSM_RETURN sigVerify(CSSM_CSP_HANDLE cspHand,
uint32 algorithm, CSSM_KEY_PTR key, const CSSM_DATA *text,
const CSSM_DATA *sig,
uint32 digestAlg, CSSM_BOOL noPad) {
CSSM_CC_HANDLE sigHand;
CSSM_RETURN crtn;
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
algorithm,
NULL, key,
&sigHand);
if(crtn) {
printError("CSSM_CSP_CreateSignatureContext", crtn);
return crtn;
}
if(noPad) {
crtn = AddContextAttribute(sigHand,
CSSM_ATTRIBUTE_PADDING,
sizeof(uint32),
CAT_Uint32,
NULL,
CSSM_PADDING_NONE);
if(crtn) {
return crtn;
}
}
crtn = CSSM_VerifyData(sigHand,
text,
1,
digestAlg,
sig);
if(crtn) {
printError("CSSM_VerifyData", crtn);
}
CSSM_DeleteContext(sigHand);
return crtn;
}
static CSSM_RETURN genDsaKeyPair(
CSSM_CSP_HANDLE cspHand,
const char *keyLabel,
unsigned keyLabelLen,
uint32 keySize, CSSM_KEY_PTR pubKey, CSSM_BOOL pubIsRef, uint32 pubKeyUsage, CSSM_KEYBLOB_FORMAT pubFormat, CSSM_KEY_PTR privKey, CSSM_BOOL privIsRef, uint32 privKeyUsage, CSSM_KEYBLOB_FORMAT privFormat, const CSSM_DATA *inParams, CSSM_DATA_PTR outParams) {
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATA keyLabelData;
uint32 pubAttr;
uint32 privAttr;
CSSM_RETURN ocrtn = CSSM_OK;
if(inParams && outParams) {
return CSSMERR_CSSM_INVALID_POINTER;
}
if(!inParams && !outParams) {
return CSSMERR_CSSM_INVALID_POINTER;
}
keyLabelData.Data = (uint8 *)keyLabel,
keyLabelData.Length = keyLabelLen;
memset(pubKey, 0, sizeof(CSSM_KEY));
memset(privKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
CSSM_ALGID_DSA,
keySize,
NULL, NULL, NULL, NULL, inParams, &ccHand);
if(crtn) {
printError("CSSM_CSP_CreateKeyGenContext", crtn);
return crtn;
}
if(pubIsRef) {
pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
}
else {
pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
}
if(privIsRef) {
privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
}
else {
privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
}
if(outParams) {
outParams->Data = NULL;
outParams->Length = 0;
crtn = CSSM_GenerateAlgorithmParams(ccHand,
keySize, outParams);
if(crtn) {
printError("CSSM_GenerateAlgorithmParams", crtn);
CSSM_DeleteContext(ccHand);
return crtn;
}
}
if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) {
crtn = AddContextAttribute(ccHand,
CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT,
sizeof(uint32),
CAT_Uint32,
NULL,
pubFormat);
if(crtn) {
printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn);
return crtn;
}
}
if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) {
crtn = AddContextAttribute(ccHand,
CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT,
sizeof(uint32),
CAT_Uint32,
NULL,
privFormat);
if(crtn) {
printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn);
return crtn;
}
}
crtn = CSSM_GenerateKeyPair(ccHand,
pubKeyUsage,
pubAttr,
&keyLabelData,
pubKey,
privKeyUsage,
privAttr,
&keyLabelData, NULL, privKey);
if(crtn) {
printError("CSSM_GenerateKeyPair", crtn);
ocrtn = crtn;
}
if(ccHand != 0) {
crtn = CSSM_DeleteContext(ccHand);
if(crtn) {
printError("CSSM_DeleteContext", crtn);
ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
}
}
return ocrtn;
}
#define KEY_FILE_NAME_MAX_LEN 256
static void rtKeyFileName(
const char *keyFileBase,
CSSM_BOOL isPub,
char *outFileName)
{
if(isPub) {
sprintf(outFileName, "%s_pub.der", keyFileBase);
}
else {
sprintf(outFileName, "%s_priv.der", keyFileBase);
}
}
static int rt_readKey(
CSSM_CSP_HANDLE cspHand,
const char *keyFileBase,
CSSM_BOOL isPub,
CSSM_ALGORITHMS alg,
CSSM_KEYBLOB_FORMAT format, CSSM_KEY_PTR key)
{
char fileName[KEY_FILE_NAME_MAX_LEN];
int irtn;
CSSM_DATA_PTR keyData = &key->KeyData;
CSSM_KEYHEADER_PTR hdr = &key->KeyHeader;
CSSM_RETURN crtn;
CSSM_KEY_SIZE keySize;
unsigned len;
memset(key, 0, sizeof(CSSM_KEY));
rtKeyFileName(keyFileBase, isPub, fileName);
irtn = readFile(fileName, &keyData->Data, &len);
if(irtn) {
printf("***error %d reading key file %s\n", irtn, fileName);
return irtn;
}
keyData->Length = len;
hdr->HeaderVersion = CSSM_KEYHEADER_VERSION;
hdr->BlobType = CSSM_KEYBLOB_RAW;
hdr->Format = format;
hdr->AlgorithmId = alg;
hdr->KeyClass = isPub ? CSSM_KEYCLASS_PUBLIC_KEY :
CSSM_KEYCLASS_PRIVATE_KEY;
hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
hdr->KeyUsage = CSSM_KEYUSE_ANY;
crtn = CSSM_QueryKeySizeInBits(cspHand, 0, key, &keySize);
if(crtn) {
printError("CSSM_QueryKeySizeInBits", crtn);
return 1;
}
hdr->LogicalKeySizeInBits = keySize.LogicalKeySizeInBits;
return 0;
}
static int rt_generate(opParams *op)
{
CSSM_RETURN crtn;
CSSM_KEY pubKey;
CSSM_KEY privKey;
char fileName[KEY_FILE_NAME_MAX_LEN];
int irtn;
CSSM_DATA paramIn = {0, NULL};
CSSM_DATA paramOut = {0, NULL};
CSSM_DATA_PTR paramInPtr = NULL;
CSSM_DATA_PTR paramOutPtr = NULL;
if(op->keyFileName == NULL) {
printf("***Need a keyFileName to generate key pair.\n");
return 1;
}
memset(&pubKey, 0, sizeof(CSSM_KEY));
memset(&privKey, 0, sizeof(CSSM_KEY));
if(op->alg == CSSM_ALGID_DSA) {
if(op->dsaParamFileIn && op->dsaParamFileOut) {
printf("***DSA key generation requires one parameter file spec.\n");
return 1;
}
if(!op->dsaParamFileIn && !op->dsaParamFileOut) {
printf("***DSA key generation requires one parameter file spec.\n");
return 1;
}
if(op->dsaParamFileIn) {
unsigned len;
irtn = readFile(op->dsaParamFileIn, ¶mIn.Data, &len);
if(irtn) {
printf("***Error reading DSA params from %s. Aborting.\n",
op->dsaParamFileIn);
}
paramIn.Length = len;
paramInPtr = ¶mIn;
}
else {
paramOutPtr = ¶mOut;
}
crtn = genDsaKeyPair(op->cspHand,
USAGE_NAME,
USAGE_NAME_LEN,
op->keySizeInBits,
&pubKey,
CSSM_FALSE, CSSM_KEYUSE_VERIFY, op->pubKeyFormat,
&privKey,
CSSM_FALSE, CSSM_KEYUSE_SIGN,
op->privKeyFormat,
paramInPtr,
paramOutPtr);
if(crtn) {
return 1;
}
if(paramOutPtr) {
irtn = writeFile(op->dsaParamFileOut, paramOut.Data, paramOut.Length);
if(irtn) {
printf("***Error writing DSA params to %s. Aborting.\n",
op->dsaParamFileOut);
return 1;
}
if(!op->quiet) {
printf("...wrote %lu bytes to %s\n", paramOut.Length,
op->dsaParamFileOut);
}
CSSM_FREE(paramOut.Data);
}
else {
free(paramIn.Data);
}
}
else {
crtn = cspGenKeyPair(op->cspHand,
op->alg,
USAGE_NAME,
USAGE_NAME_LEN,
op->keySizeInBits,
&pubKey,
CSSM_FALSE, CSSM_KEYUSE_VERIFY, op->pubKeyFormat,
&privKey,
CSSM_FALSE, CSSM_KEYUSE_SIGN,
op->privKeyFormat,
CSSM_FALSE); if(crtn) {
return 1;
}
}
rtKeyFileName(op->keyFileName, CSSM_TRUE, fileName);
irtn = writeFile(fileName, pubKey.KeyData.Data, pubKey.KeyData.Length);
if(irtn) {
printf("***Error %d writing to %s\n", irtn, fileName);
return irtn;
}
if(!op->quiet) {
printf("...wrote %lu bytes to %s\n", pubKey.KeyData.Length, fileName);
}
rtKeyFileName(op->keyFileName, CSSM_FALSE, fileName);
irtn = writeFile(fileName, privKey.KeyData.Data, privKey.KeyData.Length);
if(irtn) {
printf("***Error %d writing to %s\n", irtn, fileName);
return irtn;
}
if(!op->quiet) {
printf("...wrote %lu bytes to %s\n", privKey.KeyData.Length, fileName);
}
cspFreeKey(op->cspHand, &pubKey);
cspFreeKey(op->cspHand, &privKey);
return 0;
}
static int rt_encrypt(opParams *op)
{
CSSM_KEY pubKey;
int irtn;
CSSM_DATA ptext;
CSSM_DATA ctext;
CSSM_RETURN crtn;
CSSM_BOOL isPub;
CSSM_ENCRYPT_MODE mode = CSSM_ALGMODE_NONE;
CSSM_KEYBLOB_FORMAT format = op->pubKeyFormat;
unsigned len;
if(op->keyFileName == NULL) {
printf("***Need a keyFileName to encrypt.\n");
return 1;
}
if((op->plainFileName == NULL) || (op->cipherFileName == NULL)) {
printf("***Need plainFileName and cipherFileName to encrypt.\n");
return 1;
}
if(op->swapKeyClass) {
isPub = CSSM_FALSE;
mode = CSSM_ALGMODE_PRIVATE_KEY;
format = op->privKeyFormat;
}
else {
isPub = CSSM_TRUE;
}
irtn = rt_readKey(op->cspHand, op->keyFileName, isPub, op->alg,
format, &pubKey);
if(irtn) {
return irtn;
}
irtn = readFile(op->plainFileName, &ptext.Data, &len);
if(irtn) {
printf("***Error reading %s\n", op->plainFileName);
return irtn;
}
ptext.Length = len;
ctext.Data = NULL;
ctext.Length = 0;
crtn = cspEncrypt(op->cspHand,
op->alg,
mode,
op->noPad ? CSSM_PADDING_NONE : CSSM_PADDING_PKCS1,
&pubKey,
NULL,
0, 0, NULL, &ptext,
&ctext,
CSSM_FALSE); if(crtn) {
printError("cspEncrypt", crtn);
return 1;
}
irtn = writeFile(op->cipherFileName, ctext.Data, ctext.Length);
if(irtn) {
printf("***Error writing %s\n", op->cipherFileName);
}
else {
if(!op->quiet) {
printf("...wrote %lu bytes to %s\n", ctext.Length, op->cipherFileName);
}
}
free(pubKey.KeyData.Data); free(ptext.Data); appFreeCssmData(&ctext, CSSM_FALSE); return irtn;
}
static int rt_decrypt(opParams *op)
{
CSSM_KEY privKey;
int irtn;
CSSM_DATA ptext;
CSSM_DATA ctext;
CSSM_RETURN crtn;
CSSM_BOOL isPub;
CSSM_ENCRYPT_MODE mode = CSSM_ALGMODE_NONE;
CSSM_KEYBLOB_FORMAT format = op->privKeyFormat;
unsigned len;
if(op->keyFileName == NULL) {
printf("***Need a keyFileName to decrypt.\n");
return 1;
}
if((op->plainFileName == NULL) || (op->cipherFileName == NULL)) {
printf("***Need plainFileName and cipherFileName to decrypt.\n");
return 1;
}
if(op->swapKeyClass) {
isPub = CSSM_TRUE;
mode = CSSM_ALGMODE_PUBLIC_KEY;
format = op->pubKeyFormat;
}
else {
isPub = CSSM_FALSE;
}
irtn = rt_readKey(op->cspHand, op->keyFileName, isPub, op->alg,
format, &privKey);
if(irtn) {
return irtn;
}
irtn = readFile(op->cipherFileName, &ctext.Data, &len);
if(irtn) {
printf("***Error reading %s\n", op->cipherFileName);
return irtn;
}
ctext.Length = len;
ptext.Data = NULL;
ptext.Length = 0;
crtn = cspDecrypt(op->cspHand,
op->alg,
mode,
op->noPad ? CSSM_PADDING_NONE : CSSM_PADDING_PKCS1,
&privKey,
NULL,
0, 0, NULL, &ctext,
&ptext,
CSSM_FALSE); if(crtn) {
return 1;
}
irtn = writeFile(op->plainFileName, ptext.Data, ptext.Length);
if(irtn) {
printf("***Error writing %s\n", op->cipherFileName);
}
else {
if(!op->quiet) {
printf("...wrote %lu bytes to %s\n", ptext.Length, op->plainFileName);
}
}
free(privKey.KeyData.Data); free(ctext.Data); appFreeCssmData(&ptext, CSSM_FALSE); return irtn;
}
static int rt_sign(opParams *op)
{
CSSM_KEY privKey;
int irtn;
CSSM_DATA ptext;
CSSM_DATA sig;
CSSM_RETURN crtn;
CSSM_ALGORITHMS alg;
unsigned len;
if(op->keyFileName == NULL) {
printf("***Need a keyFileName to sign.\n");
return 1;
}
if((op->plainFileName == NULL) || (op->sigFileName == NULL)) {
printf("***Need plainFileName and sigFileName to sign.\n");
return 1;
}
irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_FALSE, op->alg,
op->privKeyFormat, &privKey);
if(irtn) {
return irtn;
}
irtn = readFile(op->plainFileName, &ptext.Data, &len);
if(irtn) {
printf("***Error reading %s\n", op->plainFileName);
return irtn;
}
ptext.Length = len;
sig.Data = NULL;
sig.Length = 0;
switch(op->alg) {
case CSSM_ALGID_RSA:
if(op->rawSign) {
alg = CSSM_ALGID_RSA;
}
else {
alg = CSSM_ALGID_SHA1WithRSA;
}
break;
case CSSM_ALGID_DSA:
alg = CSSM_ALGID_SHA1WithDSA;
break;
case CSSM_ALGID_ECDSA:
if(op->rawSign) {
alg = CSSM_ALGID_ECDSA;
}
else {
alg = CSSM_ALGID_SHA1WithECDSA;
}
break;
default:
printf("Hey! Try another alg!\n");
exit(1);
}
crtn = sigSign(op->cspHand,
alg,
&privKey,
&ptext,
&sig,
op->digestAlg,
op->noPad);
if(crtn) {
printError("cspSign", crtn);
return 1;
}
irtn = writeFile(op->sigFileName, sig.Data, sig.Length);
if(irtn) {
printf("***Error writing %s\n", op->sigFileName);
}
else if(!op->quiet) {
printf("...wrote %lu bytes to %s\n", sig.Length, op->sigFileName);
}
free(privKey.KeyData.Data); free(ptext.Data); appFreeCssmData(&sig, CSSM_FALSE); return irtn;
}
static int rt_verify(opParams *op)
{
CSSM_KEY pubKey;
int irtn;
CSSM_DATA ptext;
CSSM_DATA sig;
CSSM_RETURN crtn;
CSSM_ALGORITHMS alg;
unsigned len;
if(op->keyFileName == NULL) {
printf("***Need a keyFileName to verify.\n");
return 1;
}
if((op->plainFileName == NULL) || (op->sigFileName == NULL)) {
printf("***Need plainFileName and sigFileName to verify.\n");
return 1;
}
irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_TRUE, op->alg,
op->pubKeyFormat, &pubKey);
if(irtn) {
return irtn;
}
irtn = readFile(op->plainFileName, &ptext.Data, &len);
if(irtn) {
printf("***Error reading %s\n", op->plainFileName);
return irtn;
}
ptext.Length = len;
irtn = readFile(op->sigFileName, &sig.Data, (unsigned *)&sig.Length);
if(irtn) {
printf("***Error reading %s\n", op->sigFileName);
return irtn;
}
switch(op->alg) {
case CSSM_ALGID_RSA:
if(op->rawSign) {
alg = CSSM_ALGID_RSA;
}
else {
alg = CSSM_ALGID_SHA1WithRSA;
}
break;
case CSSM_ALGID_DSA:
alg = CSSM_ALGID_SHA1WithDSA;
break;
case CSSM_ALGID_ECDSA:
if(op->rawSign) {
alg = CSSM_ALGID_ECDSA;
}
else {
alg = CSSM_ALGID_SHA1WithECDSA;
}
break;
default:
printf("Hey! Try another alg!\n");
exit(1);
}
crtn = sigVerify(op->cspHand,
alg,
&pubKey,
&ptext,
&sig,
op->digestAlg,
op->noPad);
if(crtn) {
printError("sigVerify", crtn);
irtn = 1;
}
else if(!op->quiet){
printf("...signature verifies OK\n");
irtn = 0;
}
free(pubKey.KeyData.Data); free(ptext.Data); free(sig.Data); return irtn;
}
static int rt_digest(opParams *op)
{
int irtn;
CSSM_DATA ptext;
CSSM_DATA digest = {0, NULL};
CSSM_RETURN crtn;
unsigned len;
if((op->plainFileName == NULL) || (op->sigFileName == NULL)) {
printf("***Need plainFileName and sigFileName to digest.\n");
return 1;
}
irtn = readFile(op->plainFileName, &ptext.Data, &len);
if(irtn) {
printf("***Error reading %s\n", op->plainFileName);
return irtn;
}
ptext.Length = len;
crtn = cspDigest(op->cspHand,
op->alg,
CSSM_FALSE, &ptext,
&digest);
if(crtn) {
printError("cspDigest", crtn);
return 1;
}
irtn = writeFile(op->sigFileName, digest.Data, digest.Length);
if(irtn) {
printf("***Error writing %s\n", op->sigFileName);
}
else if(!op->quiet){
printf("...wrote %lu bytes to %s\n", digest.Length, op->sigFileName);
}
free(ptext.Data); appFreeCssmData(&digest, CSSM_FALSE); return irtn;
}
static int rt_convertPubKey(opParams *op)
{
CSSM_RETURN crtn;
int irtn;
CSSM_KEY pubKeyIn;
CSSM_KEY pubKeyOut;
CSSM_KEY refKey;
char fileName[KEY_FILE_NAME_MAX_LEN];
if((op->keyFileName == NULL) || (op->outKeyFileName == NULL)) {
printf("***I need input and output key file names for public key concersion.\n");
return 1;
}
irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_TRUE, op->alg,
op->pubKeyFormat, &pubKeyIn);
if(irtn) {
return irtn;
}
crtn = cspRawKeyToRef(op->cspHand, &pubKeyIn, &refKey);
if(crtn) {
printf("***Error on NULL unwrap of %s\n", op->keyFileName);
return -1;
}
crtn = nullWrapKey(op->cspHand, &refKey, op->outPubKeyFormat, &pubKeyOut);
if(crtn) {
printf("***Error on NULL wrap\n");
return 1;
}
rtKeyFileName(op->outKeyFileName, CSSM_TRUE, fileName);
irtn = writeFile(fileName, pubKeyOut.KeyData.Data, pubKeyOut.KeyData.Length);
if(irtn) {
printf("***Error %d writing to %s\n", irtn, fileName);
return irtn;
}
if(!op->quiet) {
printf("...wrote %lu bytes to %s\n", pubKeyOut.KeyData.Length, fileName);
}
cspFreeKey(op->cspHand, &pubKeyOut);
free(pubKeyIn.KeyData.Data);
cspFreeKey(op->cspHand, &refKey);
return 0;
}
static CSSM_KEYBLOB_FORMAT parsePubKeyFormat(char c, char **argv)
{
switch(c) {
case '1':
return CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
case 'x':
return CSSM_KEYBLOB_RAW_FORMAT_X509;
case 'b':
return CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
case 'o':
return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH;
case 'O':
return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2;
case 'L':
return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL;
default:
usage(argv);
}
return -1;
}
int main(int argc, char **argv)
{
int arg;
char *argp;
int rtn;
opParams op;
if(argc < 2) {
usage(argv);
}
memset(&op, 0, sizeof(opParams));
op.keySizeInBits = DEFAULT_KEY_SIZE_BITS;
op.alg = CSSM_ALGID_RSA;
op.swapKeyClass = CSSM_FALSE;
op.rawSign = CSSM_FALSE;
op.noPad = CSSM_FALSE;
for(arg=2; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'a':
if(argp[1] != '=') {
usage(argv);
}
switch(argp[2]) {
case 'r':
op.alg = CSSM_ALGID_RSA;
break;
case 'd':
op.alg = CSSM_ALGID_DSA;
break;
case 'e':
op.alg = CSSM_ALGID_ECDSA;
break;
default:
usage(argv);
}
break;
case 'z':
op.keySizeInBits = atoi(&argp[2]);
break;
case 'k':
op.keyFileName = &argp[2];
break;
case 'K':
op.outKeyFileName = &argp[2];
break;
case 'p':
op.plainFileName = &argp[2];
break;
case 'c':
op.cipherFileName = &argp[2];
break;
case 's':
op.sigFileName = &argp[2];
break;
case 'w':
op.swapKeyClass = CSSM_TRUE;
break;
case 'r':
op.rawSign = CSSM_TRUE;
break;
case 'P':
op.noPad = CSSM_TRUE;
break;
case 'm':
op.dsaParamFileIn = &argp[2];
break;
case 'M':
op.dsaParamFileOut = &argp[2];
break;
case 'q':
op.quiet = CSSM_TRUE;
break;
case 'b':
if(argp[1] != '=') {
usage(argv);
}
op.pubKeyFormat = parsePubKeyFormat(argp[2], argv);
break;
case 'B':
if(argp[1] != '=') {
usage(argv);
}
op.outPubKeyFormat = parsePubKeyFormat(argp[2], argv);
break;
case 'v':
if(argp[1] != '=') {
usage(argv);
}
switch(argp[2]) {
case '1':
op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
break;
case '8':
op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
break;
case 's':
op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH;
break;
case 'b':
op.pubKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
break;
#if OPENSSL_ENABLE
case 'o':
op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL;
break;
#endif
default:
usage(argv);
}
break;
case 'd':
if(argp[1] != '=') {
usage(argv);
}
switch(argp[2]) {
case 's':
op.digestAlg = CSSM_ALGID_SHA1;
break;
case '5':
op.digestAlg = CSSM_ALGID_MD5;
break;
default:
usage(argv);
}
break;
case 'h':
default:
usage(argv);
}
}
op.cspHand = cspDlDbStartup(CSSM_TRUE, NULL);
if(op.cspHand == 0) {
exit(1);
}
if(op.pubKeyFormat == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
switch(op.alg) {
case CSSM_ALGID_RSA:
op.pubKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
break;
case CSSM_ALGID_DSA:
case CSSM_ALGID_ECDSA:
op.pubKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_X509;
break;
default:
printf("BRRZAP!\n");
exit(1);
}
}
if(op.privKeyFormat == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
switch(op.alg) {
case CSSM_ALGID_RSA:
op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
break;
case CSSM_ALGID_DSA:
op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
break;
case CSSM_ALGID_ECDSA:
op.privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL;
break;
default:
printf("BRRZAP!\n");
exit(1);
}
}
switch(argv[1][0]) {
case 'g':
rtn = rt_generate(&op);
break;
case 'e':
rtn = rt_encrypt(&op);
break;
case 'd':
rtn = rt_decrypt(&op);
break;
case 's':
rtn = rt_sign(&op);
break;
case 'v':
rtn = rt_verify(&op);
break;
case 'S':
op.alg = CSSM_ALGID_SHA1;
rtn = rt_digest(&op);
break;
case 'M':
op.alg = CSSM_ALGID_MD5;
rtn = rt_digest(&op);
break;
case 'C':
rtn = rt_convertPubKey(&op);
break;
default:
usage(argv);
exit(1); }
CSSM_ModuleDetach(op.cspHand);
return rtn;
}