1#include "EXTERN.h" 2#include "perl.h" 3#include "XSUB.h" 4 5/* try to be compatible with older perls */ 6/* SvPV_nolen() macro first defined in 5.005_55 */ 7/* this is slow, not threadsafe, but works */ 8#include "patchlevel.h" 9#if (PATCHLEVEL == 4) || ((PATCHLEVEL == 5) && (SUBVERSION < 55)) 10static STRLEN nolen_na; 11# define SvPV_nolen(sv) SvPV ((sv), nolen_na) 12#endif 13 14#include "rijndael.h" 15 16typedef struct cryptstate { 17 RIJNDAEL_context ctx; 18 UINT8 iv[RIJNDAEL_BLOCKSIZE]; 19 int mode; 20} *Crypt__Rijndael; 21 22MODULE = Crypt::Rijndael PACKAGE = Crypt::Rijndael 23 24PROTOTYPES: ENABLE 25 26 # newCONSTSUB is here as of 5.004_70 27 28BOOT: 29{ 30#if (PATCHLEVEL > 4) || ((PATCHLEVEL == 4) && (SUBVERSION >= 70)) 31 HV *stash = gv_stashpv("Crypt::Rijndael", 0); 32 33 newCONSTSUB (stash, "keysize", newSViv (32) ); 34 newCONSTSUB (stash, "blocksize", newSViv (16) ); 35 newCONSTSUB (stash, "MODE_ECB", newSViv (MODE_ECB) ); 36 newCONSTSUB (stash, "MODE_CBC", newSViv (MODE_CBC) ); 37 newCONSTSUB (stash, "MODE_CFB", newSViv (MODE_CFB) ); 38 newCONSTSUB (stash, "MODE_PCBC", newSViv (MODE_PCBC) ); 39 newCONSTSUB (stash, "MODE_OFB", newSViv (MODE_OFB) ); 40 newCONSTSUB (stash, "MODE_CTR", newSViv (MODE_CTR) ); 41#endif 42} 43 44#if (PATCHLEVEL < 4) || ((PATCHLEVEL == 4) && (SUBVERSION < 70)) 45 46int 47keysize(...) 48 CODE: 49 RETVAL=32; 50 OUTPUT: 51 RETVAL 52 53int 54blocksize(...) 55 CODE: 56 RETVAL=16; 57 OUTPUT: 58 RETVAL 59 60int 61MODE_ECB(...) 62 CODE: 63 RETVAL=MODE_ECB; 64 OUTPUT: 65 RETVAL 66 67int 68MODE_CBC(...) 69 CODE: 70 RETVAL=MODE_CBC; 71 OUTPUT: 72 RETVAL 73 74int 75MODE_CFB(...) 76 CODE: 77 RETVAL=MODE_CFB; 78 OUTPUT: 79 RETVAL 80 81int 82MODE_PCBC(...) 83 CODE: 84 RETVAL=MODE_PCBC; 85 OUTPUT: 86 RETVAL 87 88int 89MODE_OFB(...) 90 CODE: 91 RETVAL=MODE_OFB; 92 OUTPUT: 93 RETVAL 94 95int 96MODE_CTR(...) 97 CODE: 98 RETVAL=MODE_CTR; 99 OUTPUT: 100 RETVAL 101 102#endif 103 104 105Crypt::Rijndael 106new(class, key, mode=MODE_ECB) 107 SV * class 108 SV * key 109 int mode 110 CODE: 111 { 112 STRLEN keysize; 113 114 if (!SvPOK (key)) 115 croak("key must be a string scalar"); 116 117 keysize = SvCUR(key); 118 119 if (keysize != 16 && keysize != 24 && keysize != 32) 120 croak ("wrong key length: key must be 128, 192 or 256 bits long"); 121 if (mode != MODE_ECB && mode != MODE_CBC && mode != MODE_CFB && mode != MODE_OFB && mode != MODE_CTR) 122 croak ("illegal mode, see documentation for valid modes"); 123 124 Newz(0, RETVAL, 1, struct cryptstate); 125 RETVAL->ctx.mode = RETVAL->mode = mode; 126 /* set the IV to zero on initialization */ 127 memset(RETVAL->iv, 0, RIJNDAEL_BLOCKSIZE); 128 rijndael_setup(&RETVAL->ctx, keysize, (UINT8 *) SvPV_nolen(key)); 129 130 } 131 OUTPUT: 132 RETVAL 133 134SV * 135set_iv(self, data) 136 Crypt::Rijndael self 137 SV * data 138 139 CODE: 140 { 141 SV *res; 142 STRLEN size; 143 void *rawbytes = SvPV(data,size); 144 145 if( size != RIJNDAEL_BLOCKSIZE ) 146 croak( "set_iv: initial value must be the blocksize (%d bytes), but was %d bytes", RIJNDAEL_BLOCKSIZE, size ); 147 memcpy(self->iv, rawbytes, RIJNDAEL_BLOCKSIZE); 148 } 149 150SV * 151encrypt(self, data) 152 Crypt::Rijndael self 153 SV * data 154 ALIAS: 155 decrypt = 1 156 CODE: 157 { 158 SV *res; 159 STRLEN size; 160 void *rawbytes = SvPV(data,size); 161 162 if (size) { 163 if (size % RIJNDAEL_BLOCKSIZE) 164 croak ("encrypt: datasize not multiple of blocksize (%d bytes)", RIJNDAEL_BLOCKSIZE); 165 166 RETVAL = NEWSV (0, size); 167 SvPOK_only (RETVAL); 168 SvCUR_set (RETVAL, size); 169 (ix ? block_decrypt : block_encrypt) 170 (&self->ctx, rawbytes, size, (UINT8 *) SvPV_nolen(RETVAL), self->iv); 171 } else 172 RETVAL = newSVpv ("", 0); 173 } 174 OUTPUT: 175 RETVAL 176 177 178void 179DESTROY(self) 180 Crypt::Rijndael self 181 CODE: 182 Safefree(self); 183