#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
/* try to be compatible with older perls */
/* SvPV_nolen() macro first defined in 5.005_55 */
/* this is slow, not threadsafe, but works */
#include "patchlevel.h"
#if (PATCHLEVEL == 4) || ((PATCHLEVEL == 5) && (SUBVERSION < 55))
static STRLEN nolen_na;
# define SvPV_nolen(sv) SvPV ((sv), nolen_na)
#endif
#include "rijndael.h"
typedef struct cryptstate {
RIJNDAEL_context ctx;
UINT8 iv[RIJNDAEL_BLOCKSIZE];
int mode;
} *Crypt__Rijndael;
MODULE = Crypt::Rijndael PACKAGE = Crypt::Rijndael
PROTOTYPES: ENABLE
# newCONSTSUB is here as of 5.004_70
BOOT:
{
#if (PATCHLEVEL > 4) || ((PATCHLEVEL == 4) && (SUBVERSION >= 70))
HV *stash = gv_stashpv("Crypt::Rijndael", 0);
newCONSTSUB (stash, "keysize", newSViv (32));
newCONSTSUB (stash, "blocksize", newSViv (16));
newCONSTSUB (stash, "MODE_ECB", newSViv (MODE_ECB));
newCONSTSUB (stash, "MODE_CBC", newSViv (MODE_CBC));
newCONSTSUB (stash, "MODE_CFB", newSViv (MODE_CFB));
newCONSTSUB (stash, "MODE_OFB", newSViv (MODE_OFB));
newCONSTSUB (stash, "MODE_CTR", newSViv (MODE_CTR));
#endif
}
#if (PATCHLEVEL < 4) || ((PATCHLEVEL == 4) && (SUBVERSION < 70))
int
keysize(...)
CODE:
RETVAL=32;
OUTPUT:
RETVAL
int
blocksize(...)
CODE:
RETVAL=16;
OUTPUT:
RETVAL
int
MODE_ECB(...)
CODE:
RETVAL=MODE_ECB;
OUTPUT:
RETVAL
int
MODE_CBC(...)
CODE:
RETVAL=MODE_CBC;
OUTPUT:
RETVAL
int
MODE_CFB(...)
CODE:
RETVAL=MODE_CFB;
OUTPUT:
RETVAL
int
MODE_OFB(...)
CODE:
RETVAL=MODE_OFB;
OUTPUT:
RETVAL
int
MODE_CTR(...)
CODE:
RETVAL=MODE_CTR;
OUTPUT:
RETVAL
#endif
Crypt::Rijndael
new(class, key, mode=MODE_ECB)
SV * class
SV * key
int mode
CODE:
{
STRLEN keysize;
if (!SvPOK (key))
croak("key must be a string scalar");
keysize = SvCUR(key);
if (keysize != 16 && keysize != 24 && keysize != 32)
croak ("wrong key length: key must be 128, 192 or 256 bits long");
if (mode != MODE_ECB && mode != MODE_CBC && mode != MODE_CFB && mode != MODE_OFB && mode != MODE_CTR)
croak ("illegal mode, see documentation for valid modes");
Newz(0, RETVAL, 1, struct cryptstate);
RETVAL->ctx.mode = RETVAL->mode = mode;
/* set the IV to zero on initialization */
memset(RETVAL->iv, 0, RIJNDAEL_BLOCKSIZE);
rijndael_setup(&RETVAL->ctx, keysize, SvPV_nolen(key));
}
OUTPUT:
RETVAL
SV *
set_iv(self, data)
Crypt::Rijndael self
SV * data
CODE:
{
SV *res;
STRLEN size;
void *rawbytes = SvPV(data,size);
memcpy(self->iv, rawbytes, RIJNDAEL_BLOCKSIZE);
}
SV *
encrypt(self, data)
Crypt::Rijndael self
SV * data
ALIAS:
decrypt = 1
CODE:
{
SV *res;
STRLEN size;
void *rawbytes = SvPV(data,size);
if (size) {
if (size % RIJNDAEL_BLOCKSIZE)
croak ("encrypt: datasize not multiple of blocksize (%d bytes)", RIJNDAEL_BLOCKSIZE);
RETVAL = NEWSV (0, size);
SvPOK_only (RETVAL);
SvCUR_set (RETVAL, size);
(ix ? block_decrypt : block_encrypt)
(&self->ctx, rawbytes, size, SvPV_nolen(RETVAL), self->iv);
} else
RETVAL = newSVpv ("", 0);
}
OUTPUT:
RETVAL
void
DESTROY(self)
Crypt::Rijndael self
CODE:
Safefree(self);