1/* rijndael - An implementation of the Rijndael cipher. 2 * Copyright (C) 2000, 2001 Rafael R. Sevilla <sevillar@team.ph.inter.net> 3 * 4 * Currently maintained by brian d foy, <bdfoy@cpan.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public 17 * License along with this library; if not, write to the Free 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#include "EXTERN.h" 22#include "perl.h" 23#include "XSUB.h" 24 25/* try to be compatible with older perls */ 26/* SvPV_nolen() macro first defined in 5.005_55 */ 27/* this is slow, not threadsafe, but works */ 28#include "patchlevel.h" 29#if (PATCHLEVEL == 4) || ((PATCHLEVEL == 5) && (SUBVERSION < 55)) 30static STRLEN nolen_na; 31# define SvPV_nolen(sv) SvPV ((sv), nolen_na) 32#endif 33 34#include "rijndael.h" 35 36typedef struct cryptstate { 37 RIJNDAEL_context ctx; 38 UINT8 iv[RIJNDAEL_BLOCKSIZE]; 39 int mode; 40} *Crypt__Rijndael; 41 42MODULE = Crypt::Rijndael PACKAGE = Crypt::Rijndael 43 44PROTOTYPES: ENABLE 45 46 # newCONSTSUB is here as of 5.004_70 47 48BOOT: 49{ 50#if (PATCHLEVEL > 4) || ((PATCHLEVEL == 4) && (SUBVERSION >= 70)) 51 HV *stash = gv_stashpv("Crypt::Rijndael", 0); 52 53 newCONSTSUB (stash, "keysize", newSViv (32) ); 54 newCONSTSUB (stash, "blocksize", newSViv (16) ); 55 newCONSTSUB (stash, "MODE_ECB", newSViv (MODE_ECB) ); 56 newCONSTSUB (stash, "MODE_CBC", newSViv (MODE_CBC) ); 57 newCONSTSUB (stash, "MODE_CFB", newSViv (MODE_CFB) ); 58 newCONSTSUB (stash, "MODE_PCBC", newSViv (MODE_PCBC) ); 59 newCONSTSUB (stash, "MODE_OFB", newSViv (MODE_OFB) ); 60 newCONSTSUB (stash, "MODE_CTR", newSViv (MODE_CTR) ); 61#endif 62} 63 64#if (PATCHLEVEL < 4) || ((PATCHLEVEL == 4) && (SUBVERSION < 70)) 65 66int 67keysize(...) 68 CODE: 69 RETVAL=32; 70 OUTPUT: 71 RETVAL 72 73int 74blocksize(...) 75 CODE: 76 RETVAL=16; 77 OUTPUT: 78 RETVAL 79 80int 81MODE_ECB(...) 82 CODE: 83 RETVAL=MODE_ECB; 84 OUTPUT: 85 RETVAL 86 87int 88MODE_CBC(...) 89 CODE: 90 RETVAL=MODE_CBC; 91 OUTPUT: 92 RETVAL 93 94int 95MODE_CFB(...) 96 CODE: 97 RETVAL=MODE_CFB; 98 OUTPUT: 99 RETVAL 100 101int 102MODE_PCBC(...) 103 CODE: 104 RETVAL=MODE_PCBC; 105 OUTPUT: 106 RETVAL 107 108int 109MODE_OFB(...) 110 CODE: 111 RETVAL=MODE_OFB; 112 OUTPUT: 113 RETVAL 114 115int 116MODE_CTR(...) 117 CODE: 118 RETVAL=MODE_CTR; 119 OUTPUT: 120 RETVAL 121 122#endif 123 124 125Crypt::Rijndael 126new(class, key, mode=MODE_ECB) 127 SV * class 128 SV * key 129 int mode 130 CODE: 131 { 132 STRLEN keysize; 133 134 if (!SvPOK (key)) 135 croak("key must be an untainted string scalar"); 136 137 keysize = SvCUR(key); 138 139 if (keysize != 16 && keysize != 24 && keysize != 32) 140 croak ("wrong key length: key must be 128, 192 or 256 bits long"); 141 if (mode != MODE_ECB && mode != MODE_CBC && mode != MODE_CFB && mode != MODE_OFB && mode != MODE_CTR) 142 croak ("illegal mode, see documentation for valid modes"); 143 144 Newz(0, RETVAL, 1, struct cryptstate); 145 RETVAL->ctx.mode = RETVAL->mode = mode; 146 /* set the IV to zero on initialization */ 147 memset(RETVAL->iv, 0, RIJNDAEL_BLOCKSIZE); 148 rijndael_setup(&RETVAL->ctx, keysize, (UINT8 *) SvPV_nolen(key)); 149 150 } 151 OUTPUT: 152 RETVAL 153 154SV * 155set_iv(self, data) 156 Crypt::Rijndael self 157 SV * data 158 159 CODE: 160 { 161 SV *res; 162 STRLEN size; 163 void *rawbytes = SvPV(data,size); 164 165 if( size != RIJNDAEL_BLOCKSIZE ) 166 croak( "set_iv: initial value must be the blocksize (%d bytes), but was %d bytes", RIJNDAEL_BLOCKSIZE, size ); 167 memcpy(self->iv, rawbytes, RIJNDAEL_BLOCKSIZE); 168 } 169 170SV * 171encrypt(self, data) 172 Crypt::Rijndael self 173 SV * data 174 ALIAS: 175 decrypt = 1 176 CODE: 177 { 178 SV *res; 179 STRLEN size; 180 void *rawbytes = SvPV(data,size); 181 182 if (size) { 183 if (size % RIJNDAEL_BLOCKSIZE) 184 croak ("encrypt: datasize not multiple of blocksize (%d bytes)", RIJNDAEL_BLOCKSIZE); 185 186 RETVAL = NEWSV (0, size); 187 SvPOK_only (RETVAL); 188 SvCUR_set (RETVAL, size); 189 (ix ? block_decrypt : block_encrypt) 190 (&self->ctx, rawbytes, size, (UINT8 *) SvPV_nolen(RETVAL), self->iv); 191 } else 192 RETVAL = newSVpv ("", 0); 193 } 194 OUTPUT: 195 RETVAL 196 197 198void 199DESTROY(self) 200 Crypt::Rijndael self 201 CODE: 202 Safefree(self); 203