#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#ifndef bytes_from_utf8
/* 5.6.0 has UTF-8 scalars, but lacks the utility bytes_from_utf8() */
static U8 *
bytes_from_utf8(U8 *orig, STRLEN *len_p, bool *is_utf8_p)
{
STRLEN orig_len = *len_p;
U8 *orig_end = orig + orig_len;
STRLEN new_len = orig_len;
U8 *new;
U8 *p, *q;
if(!*is_utf8_p)
return orig;
for(p = orig; p != orig_end; ) {
U8 fb = *p++, sb;
if(fb <= 0x7f)
continue;
if(p == orig_end || !(fb >= 0xc2 && fb <= 0xc3))
return orig;
sb = *p++;
if(!(sb >= 0x80 && sb <= 0xbf))
return orig;
new_len--;
}
if(new_len == orig_len) {
*is_utf8_p = 0;
return orig;
}
Newz(0, new, new_len+1, U8);
for(p = orig, q = new; p != orig_end; ) {
U8 fb = *p++;
*q++ = fb <= 0x7f ? fb : ((fb & 0x03) << 6) | (*p++ & 0x3f);
}
*q = 0;
*len_p = new_len;
*is_utf8_p = 0;
return new;
}
#endif /* !bytes_from_utf8 */
#include <./fcrypt/fcrypt.h>
static void
sv_to_octets(U8 **octets_p, STRLEN *len_p, bool *must_free_p, SV *sv)
{
U8 *in_str = SvPV(sv, *len_p);
bool is_utf8 = !!SvUTF8(sv);
*octets_p = bytes_from_utf8(in_str, len_p, &is_utf8);
if(is_utf8)
croak("input must contain only octets");
*must_free_p = *octets_p != in_str;
}
static void
sv_to_cblock(des_cblock block, SV *in_block)
{
U8 *in_octets;
STRLEN in_len;
bool must_free;
sv_to_octets(&in_octets, &in_len, &must_free, in_block);
if(in_len != 8)
croak("data block must be eight octets long");
memcpy(block, in_octets, 8);
if(must_free)
Safefree(in_octets);
}
MODULE = Crypt::UnixCrypt_XS PACKAGE = Crypt::UnixCrypt_XS
char *
crypt( password, salt )
SV *password
SV *salt
CODE:
STRLEN password_len, salt_len;
U8 *password_octets, *salt_octets;
bool password_tofree, salt_tofree;
char outbuf[21];
sv_to_octets(&password_octets, &password_len, &password_tofree, password);
sv_to_octets(&salt_octets, &salt_len, &salt_tofree, salt);
des_fcrypt((char *)password_octets, password_len,
(char *)salt_octets, salt_len, outbuf);
if(password_tofree)
Safefree(password_octets);
if(salt_tofree)
Safefree(salt_octets);
RETVAL = outbuf;
OUTPUT:
RETVAL
SV *
crypt_rounds( password, nrounds, saltnum, in_block )
SV *password
unsigned long nrounds
unsigned long saltnum
SV *in_block
CODE:
STRLEN password_len;
U8 *password_octets;
bool password_tofree;
des_cblock key, block;
sv_to_octets(&password_octets, &password_len, &password_tofree, password);
sv_to_cblock(block, in_block);
trad_password_to_key(key, (char *)password_octets, password_len);
if(password_tofree)
Safefree(password_octets);
crypt_rounds(key, nrounds, saltnum, block);
RETVAL = newSVpvn(block, 8);
OUTPUT:
RETVAL
SV *
fold_password( password )
SV *password
CODE:
STRLEN password_len;
U8 *password_octets;
bool password_tofree;
des_cblock key;
int i;
sv_to_octets(&password_octets, &password_len, &password_tofree, password);
ext_password_to_key(key, (char *)password_octets, password_len);
if(password_tofree)
Safefree(password_octets);
for(i=0; i<8; i++)
key[i] = (key[i] & 0xfe) >> 1;
RETVAL = newSVpvn(key, 8);
OUTPUT:
RETVAL
SV *
base64_to_block( base64 )
SV *base64
CODE:
STRLEN base64_len;
U8 *base64_octets;
bool base64_tofree;
des_cblock block;
sv_to_octets(&base64_octets, &base64_len, &base64_tofree, base64);
if(base64_len != 11)
croak("data block in base 64 must be eleven characters long");
base64_to_block(block, (char *)base64_octets);
if(base64_tofree)
Safefree(base64_octets);
RETVAL = newSVpvn(block, 8);
OUTPUT:
RETVAL
char *
block_to_base64( in_block )
SV *in_block
CODE:
des_cblock block;
char base64[12];
sv_to_cblock(block, in_block);
block_to_base64(block, base64);
RETVAL = base64;
OUTPUT:
RETVAL
unsigned long
base64_to_int24( base64 )
SV *base64
CODE:
STRLEN base64_len;
U8 *base64_octets;
bool base64_tofree;
sv_to_octets(&base64_octets, &base64_len, &base64_tofree, base64);
if(base64_len != 4)
croak("24-bit integer in base 64 must be four characters long");
RETVAL = base64_to_int24((char *)base64_octets);
if(base64_tofree)
Safefree(base64_octets);
OUTPUT:
RETVAL
char *
int24_to_base64( val )
unsigned long val;
CODE:
char base64[5];
int24_to_base64(val, base64);
RETVAL = base64;
OUTPUT:
RETVAL
unsigned long
base64_to_int12( base64 )
SV *base64
CODE:
STRLEN base64_len;
U8 *base64_octets;
bool base64_tofree;
sv_to_octets(&base64_octets, &base64_len, &base64_tofree, base64);
if(base64_len != 2)
croak("12-bit integer in base 64 must be two characters long");
RETVAL = base64_to_int12((char *)base64_octets);
if(base64_tofree)
Safefree(base64_octets);
OUTPUT:
RETVAL
char *
int12_to_base64( val )
unsigned long val;
CODE:
char base64[3];
int12_to_base64(val, base64);
RETVAL = base64;
OUTPUT:
RETVAL