#include #include #include #include #define _NEW_STARLET 1 #include #include #include #include #include "desguid.h" #include #include "aaldefs.h" #include "aalproxy.h" #define VMS_Success 1 #define VMS_Failure 0 /*ARGSUSED*/ static void *MyMalloc(uint32 size, void *allocRef) { return malloc(size); } /*ARGSUSED*/ static void MyFree(void *p, void *allocRef) { free(p); } /*ARGSUSED*/ static void *MyRealloc(void *p, uint32 size, void *allocRef) { return realloc(p, size); } /*ARGSUSED*/ static void *MyCalloc(uint32 numElements, uint32 elementSize, void *allocRef) { return calloc(numElements, elementSize); } static const CSSM_API_MEMORY_FUNCS memoryFuncs = { MyMalloc, MyFree, MyRealloc, MyCalloc, NULL }; /*ARGSUSED*/ static void LogCssmError(CSSM_RETURN status, const char *tag) { fprintf(stderr, "%s: CSSM error 0x%x\n", tag, status); } static int ProcessInput(CSSM_CC_HANDLE hCC, int doEncrypt, struct RAB *inrab, struct RAB *outrab) { #define DES_BLOCK_SIZE 8 CSSM_DATA iData; CSSM_DATA oData; unsigned char iBuf[BUFSIZ + DES_BLOCK_SIZE]; unsigned char oBuf[BUFSIZ + DES_BLOCK_SIZE]; unsigned int iRem, iLen, pad; unsigned int oRem; unsigned __int32 oLen; CSSM_RETURN status; int rms_status; struct FAB infab, outfab, *fab; struct XABFHC *xabfhc; /* xab with file header characteristics */ long blk_size; long eof_blk; long bytes_read; int Eof; iData.Data = iBuf; oData.Data = oBuf; if (doEncrypt) { if ((status = CSSM_EncryptDataInit(hCC)) != CSSM_OK) { LogCssmError(status, "CSSM_EncryptDataInit"); return status; } } else { if ((status = CSSM_DecryptDataInit(hCC)) != CSSM_OK) { LogCssmError(status, "CSSM_DecryptDataInit"); return status; } } fab = inrab->rab$l_fab; xabfhc = fab->fab$l_xab; blk_size = fab->fab$w_bls; eof_blk = xabfhc->xab$l_ebk; bytes_read = 0; inrab->rab$l_ubf = (char*)iBuf; /* Point to buffer area */ inrab->rab$w_usz = BUFSIZ; /* indicate its size */ inrab->rab$l_bkt = 0; inrab->rab$v_bio = 1; outrab->rab$l_rbf = (char*)oBuf; rms_status = sys$read( inrab ); while ( rms_status & 1 ) { iLen = inrab->rab$w_rsz; bytes_read += inrab->rab$w_rsz; Eof = ( bytes_read/blk_size >= eof_blk-1 ); /* DES processes data in blocks of DES_BLOCK_SIZE bytes. */ iRem = iLen % DES_BLOCK_SIZE; iLen -= iRem; if (Eof && doEncrypt) { /* * Before encrypting the final input bytes, pad * them with 1-8 bytes to make them an even multiple of * DES_BLOCK_SIZE. Use random values for those pad bytes, * except for the last one. In the last one, save the * number of bytes in the final block that are real input * bytes (and not pad bytes). We'll use that number * during decryption to drop the pad bytes. */ srand(time(NULL)); for (pad = iLen + iRem; pad < iLen + DES_BLOCK_SIZE - 1; pad++) iBuf[pad] = rand(); iBuf[pad] = iRem; iLen += DES_BLOCK_SIZE; } if (iLen) { iData.Length = iLen; oData.Length = sizeof oBuf; if (doEncrypt) { if ((status = CSSM_EncryptDataUpdate(hCC, &iData, 1, &oData, 1, &oLen)) != CSSM_OK) { LogCssmError(status, "CSSM_EncryptDataUpdate"); return status; } } else { if ((status = CSSM_DecryptDataUpdate(hCC, &iData, 1, &oData, 1, &oLen)) != CSSM_OK) { LogCssmError(status, "CSSM_DecryptDataUpdate"); return status; } } if (Eof && !doEncrypt) { /* * Before writing the final decrypted bytes, drop the * pad bytes at the end. */ oRem = oBuf[oLen - 1]; if (oRem > 8) { fprintf(stderr, "invalid last byte\n"); return VMS_Failure; } oLen -= DES_BLOCK_SIZE - oRem; } outrab->rab$w_rsz = oLen; rms_status = sys$write( outrab ); if ( !rms_status & 1 ) exit( outrab->rab$l_sts ); if (iRem && !Eof) memcpy(iBuf, &iBuf[iLen], iRem); rms_status = sys$read( inrab ); } } oData.Length = sizeof oBuf; if (doEncrypt) { if ((status = CSSM_EncryptDataFinal(hCC, &oData)) != CSSM_OK) { LogCssmError(status, "CSSM_EncryptDataFinal"); return status; } } else { if ((status = CSSM_DecryptDataFinal(hCC, &oData)) != CSSM_OK) { LogCssmError(status, "CSSM_DecryptDataFinal"); return status; } } oLen = oData.Length; if( oLen > 0 ){ outrab->rab$w_rsz = oLen; rms_status = sys$write( outrab ); if ( !rms_status & 1 ) exit( outrab->rab$l_sts ); } return RMS$_NORMAL; } int DoDes(const char *keyBits, int keyLen, int doEncrypt, struct RAB *inrab, struct RAB *outrab) { int retStatus = VMS_Success; CSSM_VERSION version; CSSM_RETURN status; CSSM_PVC_MODE PvcPolicy = CSSM_PVC_SP | CSSM_PVC_APP; const CSSM_GUID csp_guid = vms_crypto_guid_init; const CSSM_GUID *pGUID = &csp_guid; CSSM_GUID cssm_guid = vms_cssm_guid_init; CSSM_GUID des3_ex_guid = des3_ex_guid_init; CSSM_MODULE_HANDLE hCSP; CSSM_KEY key; unsigned char iv[8]; CSSM_DATA ivData; CSSM_CC_HANDLE hCC; AAL_RETURN_CODE aalRtn = AAL_FAIL; /* LOAD CSSM via Application Adaption Layer */ aalRtn = AALProxyLoadCssm( &cssm_guid, NULL, 0); if (aalRtn != AAL_OK) { LogCssmError(aalRtn, "AALProxyLoadCssm"); retStatus = aalRtn; goto done; } version.Major = CSSM_MAJOR; version.Minor = CSSM_MINOR; status = CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &des3_ex_guid, CSSM_KEY_HIERARCHY_NONE, &PvcPolicy, NULL); if (status != CSSM_OK) { LogCssmError(status, "CSSM_Init"); retStatus = status; goto done; } status = CSSM_Introduce( &des3_ex_guid, CSSM_KEY_HIERARCHY_NONE ); if (status != CSSM_OK) { LogCssmError(status, "CSSM_Introduce"); retStatus = status; goto done; } status = CSSM_ModuleLoad(pGUID, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); if (status != CSSM_OK) { LogCssmError(status, "CSSM_ModuleLoad"); retStatus = status; goto terminate; } status = CSSM_ModuleAttach(pGUID, &version, &memoryFuncs, 0, CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &hCSP); if (status != CSSM_OK) { LogCssmError(status, "CSSM_ModuleAttach"); retStatus = status; goto unload; } memset(&key, 0, sizeof key); key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; key.KeyHeader.BlobType = CSSM_KEYBLOB_RAW; key.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; key.KeyHeader.AlgorithmId = CSSM_ALGID_DES; key.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY; key.KeyHeader.LogicalKeySizeInBits = keyLen * 8; key.KeyHeader.KeyUsage = CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_ENCRYPT; key.KeyHeader.WrapAlgorithmId = CSSM_ALGID_NONE; key.KeyData.Length = keyLen; key.KeyData.Data = (unsigned char *) keyBits; memset(iv, 0, sizeof iv); ivData.Length = sizeof iv; ivData.Data = iv; status = CSSM_CSP_CreateSymmetricContext(hCSP, key.KeyHeader.AlgorithmId, CSSM_ALGMODE_CBC_IV8, NULL, &key, &ivData, CSSM_PADDING_NONE, 0, &hCC); if (status != CSSM_OK) { LogCssmError(status, "CSSM_CSP_CreateSymmetricContext"); retStatus = status; goto detach; } status = ProcessInput(hCC, doEncrypt, inrab, outrab); if( status != RMS$_NORMAL ) retStatus = status; if ((status = CSSM_DeleteContext(hCC)) != CSSM_OK) { LogCssmError(status, "CSSM_DeleteContext"); retStatus = status; } detach: if ((status = CSSM_ModuleDetach(hCSP)) != CSSM_OK) { LogCssmError(status, "CSSM_ModuleDetach"); retStatus = status; } unload: if ((status = CSSM_ModuleUnload(pGUID, NULL, NULL)) != CSSM_OK) { LogCssmError(status, "CSSM_ModuleUnload"); retStatus = status; } terminate: if ((status = CSSM_Unintroduce(&des3_ex_guid)) != CSSM_OK) { LogCssmError(status, "CSSM_Unintroduce"); retStatus = status; } if ((status = CSSM_Terminate()) != CSSM_OK) { LogCssmError(status, "CSSM_Terminate"); retStatus = status; } AALProxyUnloadCssm(); done: return retStatus; }