#pragma module WR2_3DES "WR2_3DES-1-A" /* **++ ** FACILITY: Wrapper to 3DES ** ** ENVIRONMENT: OpenVMS 7.x and SSL/OpenSSL package ** ** MODULE DESCRIPTION: ** ** This module contains a wrapper routines set, to calling 3DES (Triple DES) ** encrypt/decrypt routines from high level applications: ** wr2_3des_encrypt() ** wr2_3des_decrypt() ** wr2_3des_do() ** ** ** AUTHORS: ** ** Ruslan R. Laishev ** ** CREATION DATE: 5-MAR-2004 ** ** DESIGN ISSUES: ** ** This set of routines covers a 3DES/ECB functuionality. ** ** BUILD & LINKING: ** ** Firts at all declare in your application three (3) keys which will be used ** in the wrapper code, see example of declaration in the follows C-fragment: ** ... unsigned char key1 [16] = "0123456701234567", key2 [16] = "0123456701234567", key3 [16] = "0123456701234567"; int wr2_3des_encrypt(); int wr2_3des_decrypt(); ** ** $ CC /LIS .C ** $ CC /LIS/NODEBUG/INCLUDE=SSL$INCLUDE/PREFIX=ALL WR2_3DES.C ** ** $ LINK /NOTRACE/NODEBUG .OBJ,WR2_3DES.OBJ,SYS$INPUT/OPT SYS$SHARE:SSL$LIBCRYPTO_SHR32/SHARE ^Z ** ** ** ** ** ** MODIFICATION HISTORY: ** ** ** {@tbs@}... **-- */ #include #include #include #include #include #include #include #include #include /* ** ** MACRO DEFINITIONS ** */ #define INIT_DDESC(dsc) {(dsc).dsc$b_dtype = DSC$K_DTYPE_T;\ (dsc).dsc$b_class = DSC$K_CLASS_D;(dsc).dsc$w_length = 0;\ (dsc).dsc$a_pointer = 0;} #define INIT_SDESC(dsc, len, ptr) {(dsc).dsc$b_dtype = DSC$K_DTYPE_T;\ (dsc).dsc$b_class = DSC$K_CLASS_S; (dsc).dsc$w_length = (short) (len);\ (dsc).dsc$a_pointer = (ptr);} #ifdef __VAX #define LONGWORD_SZ 4 #else #define LONGWORD_SZ 8 #endif /* ** SECURITY KEYS */ /* unsigned char key1 [16] = {0x81,0xDB,0x78,0xE5,0x04,0xC2,0x5F,0x11,0xAD,0x40,0x36,0x78,0x01,0xDB,0xE9,0x1F}, key2 [16] = {0x81,0xDB,0x78,0xE5,0x04,0xC2,0x5F,0x11,0xAD,0x40,0x36,0x78,0x01,0xDB,0xE9,0x1F}, *key3 = key1; */ unsigned char key1 [8] = {0x81,0xDB,0x78,0xE5,0x04,0xC2,0x5F,0x11}, key2 [8] = {0xAD,0x40,0x36,0x78,0x01,0xDB,0xE9,0x1F}, *key3 = key1; /* ** Follows stuff only for debug purpose */ #ifdef WR2_3DES_DEBUG int wr2_3des_do (); int wr2_3des_encrypt(); int wr2_3des_decrypt(); int main (void) { unsigned status, len = 0,c = 0; unsigned char sts [] = "6011112536553957", obuf [ 128 ],ibuf [ 128 ]; printf("Source string (%u bytes) : '%.*s'\n",sizeof(sts)-1,sizeof(sts)-1,sts); status = wr2_3des_encrypt (sts,sizeof(sts)-1,ibuf,sizeof(ibuf),&len); printf("HEX Dump of encrypted data block, %u bytes:", len); for (int i = 0;i < len;i++) { if ( !(i%8) ) printf("\n"); c = ibuf[i]; c &= 255; printf("%02.2X ",c); } printf("\n"); status = wr2_3des_decrypt (ibuf,len,obuf,sizeof(obuf),&len); printf("Decrypted string (%u bytes) : '%.*s'\n",len,len,obuf); return status; } #endif /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Put message to standard output device (SYS$OUTPUT). ** ** FORMAL PARAMETERS: ** ** msgid: a CSSM error code ** tag: an routine tag ** ** RETURN VALUE: ** ** CSSM error code ** **-- */ $DESCRIPTOR(fao_dsc, "%WR2_3DES-S-ERROR, !AZ () returned status=%x!XL"); static int wr2_3des__log ( unsigned code, const char * tag ) { long status; char buf[1024]; struct dsc$descriptor buf_dsc; /* ** Format a message, put it to SYS$OUTPUT */ INIT_SDESC(buf_dsc, sizeof(buf),buf); if ( !(1 & (status = sys$fao(&fao_dsc,&buf_dsc.dsc$w_length,&buf_dsc,tag,code))) ) lib$signal(status); lib$put_output(&buf_dsc); return code; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Performs a EN/DE-cryption of the given octets block. It's assumed the ** input and output buffers is aligment on 8-bytes boundary. ** This routine used three (3) external keys, see key1, key2, key3 global ** variables. An output buffer size must be at least 8 bytes bigger ** then input buffer (ibuflen argument) to accept a possible padding. ** ** ** FORMAL PARAMETERS: ** ** doEncrypt: operation code:DES_ENCRYPT (1) or DES_DECRYPT (0) ** ibuf: input data buffer (8-bytes chunks) ** ibuflen: a size of the input data buffer ** obuf: output buffer to accept result of processing ** obuflen: a size of the output data buffer ** retlen: a actual size in the output data buffer ** ** ** RETURN VALUE: ** ** 0 - Ok. ** 0 <> - Weak keys. ** **-- */ int wr2_3des_do ( unsigned doEncrypt, unsigned char * ibuf, unsigned ibuflen, unsigned char * obuf, unsigned obuflen, unsigned * retlen ) { unsigned status,i, len = ibuflen; des_key_schedule ks1,ks2,ks3; unsigned char *pblock = ibuf, padding_char, ivec1 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, ivec2 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, ivec3 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; *retlen = 0; /* ** Check all keys for weakness */ if ( status = des_key_sched((C_Block *)key1,ks1) ) wr2_3des__log(status,"des_key_sched(k1)"); if ( status = des_key_sched((C_Block *)key2,ks2) ) wr2_3des__log(status,"des_key_sched(k2)"); if ( status = des_key_sched((C_Block *)key3,ks3) ) wr2_3des__log(status,"des_key_sched(k3)"); memset(ivec1,0,sizeof(ivec1)); memset(ivec2,0,sizeof(ivec2)); memset(ivec3,0,sizeof(ivec3)); if ( doEncrypt == DES_ENCRYPT ) { // des_ede2_cbc_encrypt(ibuf,obuf,ibuflen,ks1,ks2,ivec1,doEncrypt); des_ncbc_encrypt(ibuf,obuf,ibuflen,ks1,ivec1,DES_ENCRYPT); des_ncbc_encrypt(obuf,obuf,ibuflen,ks2,ivec1,DES_DECRYPT); des_ncbc_encrypt(obuf,obuf,ibuflen,ks3,ivec2,DES_ENCRYPT); } else { des_ede2_cbc_encrypt(ibuf,obuf,ibuflen,ks1,ks2,ivec1,doEncrypt); /* des_ncbc_encrypt(ibuf,obuf,ibuflen,ks1,ivec2,DES_DECRYPT); des_ncbc_encrypt(obuf,obuf,ibuflen,ks2,ivec1,DES_ENCRYPT); des_ncbc_encrypt(obuf,obuf,ibuflen,ks1,ivec1,DES_DECRYPT); */ } *retlen = ibuflen; return 0; if ( (doEncrypt == DES_ENCRYPT) && (ibuflen % 8) ) { /* ** If string length not a multiple of 8, ** then pad with the character having the ascii value of (length mod 8). */ padding_char = (unsigned char) (8 - (ibuflen % 8)); /* ** Compute new work buffer size, check the output buffer ** is enough to accept encrypted data */ if ( (len = ibuflen + padding_char) > obuflen ) lib$signal(SS$_BUFFEROVF & (~1)); /* ** Allocate new buffer for the source data */ if ( !(1 & (status = lib$get_vm(&len,&pblock,0))) ) lib$signal(status); /* ** Copy source data to the new work buffer and padding rest of buffer ** with the padding_char */ memcpy(pblock,ibuf,ibuflen); memset(pblock+ibuflen,padding_char,padding_char); ibuf = pblock; } /* ** Processing EN/DE-crypting */ for ( i = len / sizeof(des_cblock);i ; --i, ibuf += sizeof(des_cblock), obuf += sizeof(des_cblock) ) des_ecb3_encrypt((C_Block *)ibuf,(C_Block *)obuf,ks1,ks2,ks3,doEncrypt); *retlen = len; if ( (doEncrypt == DES_ENCRYPT) && (ibuflen % 8) ) { /* ** Release memory */ if ( !(1 & (status = lib$free_vm(&len,&pblock,0))) ) lib$signal(status); } if ( doEncrypt == DES_DECRYPT ) { /* ** Is there is padding correct returned length then. */ padding_char = *(obuf-1); if ( (padding_char > 0) && (padding_char < 8) ) *retlen -= padding_char; } return 0; } int wr2_3des_encrypt ( unsigned char * ibuf, unsigned ibuflen, unsigned char * obuf, unsigned obuflen, unsigned * retlen ) { return wr2_3des_do (DES_ENCRYPT,ibuf,ibuflen,obuf,obuflen,retlen); } int wr2_3des_decrypt ( unsigned char * ibuf, unsigned ibuflen, unsigned char * obuf, unsigned obuflen, unsigned * retlen ) { return wr2_3des_do (DES_DECRYPT,ibuf,ibuflen,obuf,obuflen,retlen); }