Bugtraq mailing list archives

Perl Crypt::CBC concern


From: darryl () NETBAUDS NET (Darryl Miles)
Date: Sun, 18 Jun 2000 04:31:43 +0100


I wonder if you can put my mind at rest, I have recently been developing
applications in C to be compatible with the Perl implementation of
Crypt-CBC and Crypt-Blowfish.  However in doing this I am concerned over
a small detail of the Perl CBC implementation.

Just recently I have reviewed the accompanying documentation with both
Perl modules and it clains compatability with SSLeasy and openssl.  When
I originaly tried to use these implementations I had trouble and ended
up porting the Crypt-CBC into C directly from the Perl module.  It was
at
this point my attention was raised a part of Crypt::CBC I don't
understand/
can't see the logic behind.

I have included my recent emails to the opensrs mailing list on the
subject, no one there is batted an eyelid in either agreeing with me, or
putting me right in the errors of my ways.

To summarise what I think I can see:

A fragment of code in the initialisation of the CBC, means that private
keys longer than 16 bytes are only as secure as a 16 byte key would be.
This would imply that it can affect any cypher which can be used with
Crypt::CBC that is able to use a key of more than 16 bytes.

The original longer than 16 byte (e.g. with Crypt::Blowfish this can be
56 bytes) "private key" is passed through MD5 once (resulting in hash
collisions and thus loss of bit information).  The result of this is
then used to initialise the cypher, all be it with the key beefed up
back to at least 56 bytes by calling MD5 in a factorial fashion.

My point is that the strength of the 56 bytes key of only as strong as
the 16 byte stem of the key actually used
after is has been passed through MD5 once.  That is to say bytes 17 thru
56 can be derived from knowing bytes 1 through to 16.  The reality of
this is that since a huge parts of the possible 56 byte keyspace is not
possible to obtain, and the number of permutations of the 56 byte key
passed to initialise the cypher is only 2^128 (16 bytes).

I am not sure here is if it indeed ad error in the CBC which claims some
form of compatability with SSLeasy/openssl, to which I am not sure if
128 bit SSL keys are possible anyway.  The problem could be in the documentation of Crypt::Blowfish with the 
perception that you get 56 byte keys (when used in conjunction with Crypt::CBC) and the security against brute force 
attack that provides with today^H^H^Hmorrows hardware.

As I say I am no crypto expert, so would appreciate comments either
way.  My only experience with using MD5 in this way has been as
documented in the RADIUS protocol, where a random number is generated,
sent in the clear, a shared secrey (key) is used and XOR with blocks of
16 byte data.  I understand how that works, but I can't at all see the
logic in this CBC implementation.

Thanks,

--
Darryl Miles

Webtraffik Netbauds Ltd
www.netbauds.net


From - Fri Jun 16 17:09:36 2000
Received: from www.opensrs.com ([207.136.98.175]:45835 "EHLO opensrs.org")
        by relay-1.netbauds.net with ESMTP id <S4068690AbQFMAZf>;
        Tue, 13 Jun 2000 01:25:35 +0100
Received: (from majordomo@localhost)
        by opensrs.org (8.9.3/8.9.3) id TAA25002
        for dev-list-outgoing; Mon, 12 Jun 2000 19:51:15 -0400
X-Authentication-Warning: opensrs.org: majordomo set sender to owner-dev-list () opensrs org using -f
Received: from ns1.netbauds.net (IDENT:root () ns1 netbauds net [194.207.240.11])
        by opensrs.org (8.9.3/8.9.3) with ESMTP id TAA24999
        for <dev-list () opensrs org>; Mon, 12 Jun 2000 19:51:14 -0400
Received: from gw.darryl.netbauds.net ([194.207.243.217]:10255 "EHLO
        netbauds.net") by relay-1.netbauds.net with ESMTP
        id <S4068874AbQFLXuz>; Tue, 13 Jun 2000 00:50:55 +0100
Message-ID: <39457757.8ACA69F7 () netbauds net>
Date:   Tue, 13 Jun 2000 00:50:47 +0100
From:   Darryl Miles <darryl () netbauds net>
Organization: Netbauds Ltd
X-Mailer: Mozilla 4.6 [en] (X11; I; Linux 2.2.11 i686)
X-Accept-Language: en
MIME-Version: 1.0
To:     William Porquet <wporquet () tucows com>, dev-list () opensrs org
Subject: Re: OpenSRS protocol spec DRAFT
References: <Pine.LNX.4.10.10006091724580.9586-100000 () toronto mail tucows com>
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Sender: owner-dev-list () opensrs org
Precedence: bulk
Return-Path: <owner-dev-list () opensrs org>
X-Mozilla-Status: 8011
X-Mozilla-Status2: 00000000
X-UIDL: <39457757.8ACA69F7 () netbauds net>

William Porquet wrote:
{Developer testing indicates that the server terminates the
connection without sending a status message in the event of failed
authentication.  This is bad behavior on the part of the server,
and furthermore not the documented behavior.}

Agreed.

Encryption
==========

The encryption algorithims DES and Blowfish are currently supported.

The suggested method of using these encryption types is through their
respective Perl modules, Crypt::DES and Crypt::Blowfish, which are then
accessed through a common interface created by Crypt::CBC. Crypt::CBC is
now included in the OpenSRS client distribution.

While DES only supports keys of 8 bytes, it has been scrutinized for many
years and has held up very well. Blowfish supports much larger keys (up
to 56 bytes) but is relatively new on the encryption scene. It is holding
up well under examination and is slowly being adopted by various vendors.
(OpenBSD, known for their attention to security, now uses the Blowfish
algorithim for encrypting system passwords.)

Hmm I wonder about this.  I have had to take Crypt::Blowfish apart to
use it from 'C', (I stupidly thought blowfish was blowfish and the
implementation in openssl would be compatible).  However the Perl::CBC
module does some interesting things, I am not completely sure if they
are for the better or worse.

The 56 byte key is put through MD5 (MD5 hashes always output 16 bytes),
so your 56 byte key always ends up truncated to 16 bytes.  This 16 bytes
is then repeatidly put through MD5 and appended to the first 16 bytes,
etc.. until we have enough (supposidly unguessable) data to setup the
key and the block size (which CBC needs to feedback on).

The extract is in my version of CBC 1.23 (Crypto/CBC.pm):

# the real key is computed from the first N bytes of the
# MD5 hash of the provided key.
my $material = MD5->hash($key);
while (length($material) < $ks + $bs)  {
    $material .= MD5->hash($material);
}

I am no crypto expert, but I think the code would be far better if it
used:

# the real key is computed from the first N bytes of the
# MD5 hash of the provided key.
my $material;
if(length($key) > 16) {
    $material = $key;
} else {
    $material = MD5->hash($key);
}
while (length($material) < $ks + $bs)  {
    $material .= MD5->hash($material);
}

My reasoning for this is that:

 If $key is 56 byte long binary data, (your private key).
 The first pass though MD5 ('my $material = MD5->hash($key);') truncates
it to 16 bytes, and therefore since you will get hash collisions and
thus loss of bit information, (i.e. at least two of the once 56 byte
keys have now been effectivly truncated to the same 16 byte start value,
mathmatically this must be true on an enormous scale, i.e. 2^(40 * 8) =
2^320 collisions will occur with a 56 byte input and 16 byte hash output
which is supposidly mathmatically evenly distrubited).
 Once you have truncated the key and accepted the collisions, you can
MD5 the result and append, and MD5 the result of this and append, any
number of times.  The number of possible output values you will get for
doing this is still 2^(16 * 8) = 2^128 = Number of bit permutations of
an MD5 hash.
 The $material value the goes on to initialise the actual key and first
block of data used to perform CBC.

I can only presume Crypt::DES came first, and in porting it to (keysize
16 bytes) Cryptos someone didn't notice this hole.

So really Crypt::CBC + Crypt::Blowfish only gives you 16 byte keys.

Further more!

The reason all this MD5->hash() appears to be going on is to generate a
few more bits from the key which can be used to initalise the first
block CBC contents for the CBC encoding to take place.

But when you call the perl function to encrypt() the data, it throws
this computation away.  It then calls rand(255) 8 times to generate the
new start pool and sends this just after the data 'RandomIV'.

So it appears the MD5 hashing it used to beef up to pool of data forming
the key, to only then be disregarded anyway.  This feature I think is
documented in the last comment to the new() function of Crypt::CBC.
Since the initialisation value will be known to both parties (without
needing to communicate it to each other, as Crypt::CBC seems to do now,
and yet you still theoretically can't derive a single bit from the
original key from knowing the starting CBC block value (IV,
initialisation value ??  inter-block value ?? ).

Which leaves its only useful purpose to take a small key (say 4 byte)
and turn it into the right keysize for the cypto, but in my book it
should simply error on this, since if you havn't supplied exactly the
right size key for the Crypto you are using then you don't know what you
are doing.  You can even ask the Cypto for the key length is wants if
you need to truncate something.

Knowing all this it is probably possible to greatly simplify new().

Another note of interest relates to the length of the private key that is
used.  Starting with this client release, private keys will be 112
characters in length to provide the maximum security for people using
Blowfish.  Clients who continue to use DES will not be affected as
Crypt::CBC only uses the portion of the private key that is needed.  DES,
therefore, simply ignores everything after the first 16 characters of the
key.

With my reasoning, the same might as well be true for Blowfish.  It just
goes about it in a round about way.


--
Darryl Miles

Webtraffik Netbauds Ltd
www.netbauds.net



From - Fri Jun 16 17:09:55 2000
Received: from www.opensrs.com ([207.136.98.175]:45317 "EHLO opensrs.org")
        by relay-1.netbauds.net with ESMTP id <S4068969AbQFMWxj>;
        Tue, 13 Jun 2000 23:53:39 +0100
Received: (from majordomo@localhost)
        by opensrs.org (8.9.3/8.9.3) id SAA16195
        for dev-list-outgoing; Tue, 13 Jun 2000 18:26:12 -0400
X-Authentication-Warning: opensrs.org: majordomo set sender to owner-dev-list () opensrs org using -f
Received: from ns1.netbauds.net (IDENT:root () ns1 netbauds net [194.207.240.11])
        by opensrs.org (8.9.3/8.9.3) with ESMTP id SAA16192
        for <dev-list () opensrs org>; Tue, 13 Jun 2000 18:26:10 -0400
Received: from gw.darryl.netbauds.net ([194.207.243.217]:41989 "EHLO
        netbauds.net") by relay-1.netbauds.net with ESMTP
        id <S4068960AbQFMWZk>; Tue, 13 Jun 2000 23:25:40 +0100
Message-ID: <3946B4E0.517F175C () netbauds net>
Date:   Tue, 13 Jun 2000 23:25:36 +0100
From:   Darryl Miles <darryl () netbauds net>
Organization: Netbauds Ltd
X-Mailer: Mozilla 4.6 [en] (X11; I; Linux 2.2.11 i686)
X-Accept-Language: en
MIME-Version: 1.0
To:     Paul Khavkine <paul () inet-interactive com>, dev-list () opensrs org
Subject: Re: Heeeeeeeeeerrre's Johnny! <think Jack Nicholson>
References: <Pine.BSF.4.10.10006131618180.83593-100000 () compaq inet-interactif com>
Content-Type: multipart/mixed;
 boundary="------------A239B5C130215740D9C133D4"
Sender: owner-dev-list () opensrs org
Precedence: bulk
Return-Path: <owner-dev-list () opensrs org>
X-Mozilla-Status: 8011
X-Mozilla-Status2: 00000000
X-UIDL: <3946B4E0.517F175C () netbauds net>

This is a multi-part message in MIME format.
--------------A239B5C130215740D9C133D4
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Paul Khavkine wrote:
HTML part is th easiest. The hard part is the authentication and
encryption since it's using Crypt::CBC and it's kind of proprietary perl
implementation.

Cheers
Paul

Not any more.  Just add blowfish.o (from Crypt::Blowfish) and md5.o
(from anywhere).

cc -o perl_blowfish -DMAIN perl_blowfish.c blowfish.o md5.o

Please let me know if this works for you too.

I still stand by my recent contribution that the 56 byte Blowfish key
you are using is only as strong as a 16 byte Blowfish key is, because
Crypt::CBC truncates the 56 byte private key into a 16 byte private
key.  This is because bytes 17 through to 56 can be derived from knowing
the value of bytes 1 through to 16 of the internally mangled key it
actually uses for the encryption.  Crypt::CBC then proceeds to send the
random initialised value for the first CBC block in the clear.  So all
that remains now is for someone to monitor an OpenSRS session and try a
brute force attack on the weaker 16 byte (128 bit) key.  The attacher
does not need to know what your private key actually is, only what your
private key hashes to after being put through MD5 once.

Happy hacking :)


--
Darryl Miles

Webtraffik Netbauds Ltd
www.netbauds.net
--------------A239B5C130215740D9C133D4
Content-Type: text/plain; charset=us-ascii;
 name="perl_blowfish.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="perl_blowfish.c"

/*
 *      $Id$
 *
 *      $Log$
 *
 *
 *      Copyright (C) 2000 Darryl L. Miles
 *
 *
 *      Argh!  Crypt::CBC + Crypt::Blowfish aren't compatible with say
 *      OpenSSLs BF_cbc_crypt() function.
 *
 *      The root of the problem seems to be the implementation of blowfish
 *      in the CPAN PErl module Crypt::Blowfish is not compatible with the
 *      OpenSSL one.  Given the SAME initialisation key they product
 *      different crypto output!
 *
 */

#include <stdio.h>
#include <malloc.h>
#include <limits.h>

#include <md5.h>

#ifdef OPENSSL_IMPLEMENTATION
 #include <openssl/blowfish.h>
#endif

#include "perl_blowfish.h"

struct perl_blowfish *
PerlBlowfishDestroy(struct perl_blowfish *pb)
{
        PerlBlowfishEnd(pb);

        free(pb);

        return NULL;
}

struct perl_blowfish *
PerlBlowfishCreate(const void *key, unsigned int keylen)
{
        struct perl_blowfish *pb;

        pb = malloc(sizeof(*pb));

        if(pb == NULL)
                return NULL;

        if(PerlBlowfishInit(pb, key, keylen) < 0) {
                free(pb);
                pb = NULL;
        }

        return pb;
}

void
PerlBlowfishClear(struct perl_blowfish *pb)
{
        memset(pb, 0, sizeof(*pb));

        return;
}

void
PerlBlowfishEnd(struct perl_blowfish *pb)
{
        PerlBlowfishClear(pb);

        return;
}

int
PerlBlowfishInit(struct perl_blowfish *pb, const void *key, unsigned int keylen)
{
        const int keysize = 56;
        const int blocksize = BF_BLOCK;
        unsigned char fuzzykey[56 + BF_BLOCK + 16];
        int fuzzykey_len;

        memset(pb, 0, sizeof(*pb));

        if(keylen > keysize)
                keylen = keysize;

        /* Hmm this has been gleened from the perl CBC module
         *   Crypt::CBC.
         *
         * We take the private key, and repeatidly perform an
         *  MD5 hash on it, and then its result, etc.. until the
         *  length of the data is longer than the keysize + blocksize.
         * For Blowfish keysize = 56, blocksize = 8.
         * Once the output is the same length or longer we take the
         *  for keysize bytes for the key.  The next blocksize number
         *  of bytes to init the 'ivec' with.
         */

        md5_calc(fuzzykey, key, keylen);
        fuzzykey_len = 16;

        while(fuzzykey_len < (blocksize + keysize)) {
                md5_calc(fuzzykey + fuzzykey_len, fuzzykey, fuzzykey_len);
                fuzzykey_len += 16;
        }

#ifdef OPENSSL_IMPLEMENTATION
        BF_set_key(&pb->blowfish_key, keysize, fuzzykey);
#else
        blowfish_make_bfkey(fuzzykey, keysize, &pb->blowfish_key);
#endif
        /* This is actually just randomly grouped */
        memcpy(pb->blowfish_ivec_enc, fuzzykey + keysize, blocksize);
        memcpy(pb->blowfish_ivec_dec, fuzzykey + keysize, blocksize);

        /* FIXME: Open up /dev/random here and fill in 'blowfish_ivec_enc'
         *  and 'blowfish_ivec_dec' with that data.
         */

        pb->left = 0;
        pb->f_first_enc = 1;
        pb->f_first_dec = 1;

        return 0;
}

static void
string_xor(unsigned char *dest, const unsigned char *a, const unsigned char *b, unsigned int len)
{
        while(len > 0) {
                volatile unsigned char val;

                val = *a++ ^ *b++;

                *dest++ = val;
                len--;
        }

        return;
}

void *
PerlBlowfishEncrypt(struct perl_blowfish *pb, void *dest, unsigned int *destlenptr, const void *src, unsigned int 
srclen)
{
        unsigned int nblock;
        unsigned int nrem;
        unsigned int destlen;

        if(destlenptr != NULL)
                destlen = *destlenptr;
        else
                destlen = INT_MAX;

        srclen += pb->left;

        nblock = srclen / BF_BLOCK;
        nrem = srclen % BF_BLOCK;

        if(pb->f_first_enc) {
                memcpy(dest, "RandomIV", 8);
                dest += 8;
                destlen -= 8;

                memcpy(dest, pb->blowfish_ivec_enc, BF_BLOCK);
                dest += BF_BLOCK;
                destlen -= BF_BLOCK;

                pb->f_first_enc = 0;
        }

        while(nblock > 0) {
                unsigned char xblock[BF_BLOCK];
                unsigned char block[BF_BLOCK];

                if(pb->left > 0) {
                        unsigned int flen;

                        flen = BF_BLOCK - pb->left;

                        /* Use up leftover */
                        memcpy(block, pb->leftover, pb->left);
        
                        /* Then take from src */
                        memcpy(block + pb->left, src, flen);

                        src += flen;
                        srclen -= flen;

                        pb->left = 0;
                } else {
                        memcpy(block, src, BF_BLOCK);

                        src += BF_BLOCK;
                        srclen -= BF_BLOCK;
                }

                string_xor(xblock, block, pb->blowfish_ivec_enc, BF_BLOCK);

#ifdef OPENSSL_IMPLEMENTATION
                BF_encrypt((void *)xblock, &pb->blowfish_key);
#else
                blowfish_crypt_8bytes(xblock, xblock, &pb->blowfish_key, 0);
#endif

                memcpy(dest, xblock, BF_BLOCK);
                dest += BF_BLOCK;
                destlen -= BF_BLOCK;

                memcpy(pb->blowfish_ivec_enc, xblock, BF_BLOCK);

                nblock--;
        }

        memcpy(pb->leftover + pb->left, src, srclen);
        pb->left += srclen;

        if(destlenptr != NULL)
                *destlenptr = destlen;

        return dest;
}

void *
PerlBlowfishEncryptFlush(struct perl_blowfish *pb, void *dest, unsigned int *destlenptr)
{
        unsigned int destlen;

        if(destlenptr != NULL)
                destlen = *destlenptr;
        else
                destlen = INT_MAX;

        if(pb->f_first_enc)     /* You've not called Encrypt() */
                return NULL;

        {
                unsigned char xblock[BF_BLOCK];
                unsigned char block[BF_BLOCK];
                unsigned int flen;

                flen = BF_BLOCK - pb->left;

                if(pb->left > 0) {
                        /* Use up leftover */
                        memcpy(block, pb->leftover, pb->left);
                }

                memset(block + pb->left, flen, flen);

                string_xor(xblock, block, pb->blowfish_ivec_enc, BF_BLOCK);

#ifdef OPENSSL_IMPLEMENTATION
                BF_encrypt((void *)xblock, &pb->blowfish_key);
#else
                blowfish_crypt_8bytes(xblock, xblock, &pb->blowfish_key, 0);
#endif

                memcpy(dest, xblock, BF_BLOCK);
                dest += BF_BLOCK;
                destlen -= BF_BLOCK;

                memcpy(pb->blowfish_ivec_enc, xblock, BF_BLOCK);
        }

        pb->left = 0;

        pb->f_first_enc = 1;

        if(destlenptr != NULL)
                *destlenptr = destlen;

        return dest;
}

void *
PerlBlowfishDecrypt(struct perl_blowfish *pb, void *dest, unsigned int *destlenptr, const void *src, unsigned int 
srclen)
{
        unsigned int nblock;
        unsigned int destlen;

        if(destlenptr != NULL)
                destlen = *destlenptr;
        else
                destlen = INT_MAX;

        if(pb->f_first_dec) {
                if(srclen < 8)
                        return NULL;

                if(memcmp(src, "RandomIV", 8) == 0) {
                        src += 8;
                        srclen -= 8;

                        if(srclen < 8)
                                return NULL;

                        memcpy(pb->blowfish_ivec_dec, src, BF_BLOCK);
                        src += BF_BLOCK;
                        srclen -= BF_BLOCK;
                }

                pb->f_first_dec = 0;
        }

        if((srclen % BF_BLOCK) != 0)
                return NULL;

        nblock = srclen / BF_BLOCK;

        while(nblock > 1) {
                unsigned char xblock[BF_BLOCK];
                unsigned char block[BF_BLOCK];

                memcpy(block, src, BF_BLOCK);
                src += BF_BLOCK;
                srclen -= BF_BLOCK;

#ifdef OPENSSL_IMPLEMENTATION
                BF_decrypt((void *)block, &pb->blowfish_key);
#else
                /* (src, dest, key, f_dec) */
                blowfish_crypt_8bytes(block, xblock, &pb->blowfish_key, 1);
#endif

                string_xor(xblock, xblock, pb->blowfish_ivec_dec, BF_BLOCK);

                memcpy(dest, xblock, BF_BLOCK);
                dest += BF_BLOCK;
                destlen -= BF_BLOCK;

                memcpy(pb->blowfish_ivec_dec, block, BF_BLOCK);

                nblock--;
        }

        /* Okay no we're on the last block */
        if(nblock == 1) {
                unsigned char xblock[BF_BLOCK];
                unsigned char block[BF_BLOCK];
                unsigned int padlen;

                memcpy(block, src, BF_BLOCK);
                src += BF_BLOCK;
                srclen -= BF_BLOCK;

#ifdef OPENSSL_IMPLEMENTATION
                BF_decrypt((void *)block, &pb->blowfish_key);
#else
                /* (src, dest, key, f_dec) */
                blowfish_crypt_8bytes(block, xblock, &pb->blowfish_key, 1);
#endif

                string_xor(xblock, xblock, pb->blowfish_ivec_dec, BF_BLOCK);

                padlen = xblock[BF_BLOCK - 1];

                if(padlen < 1 || padlen > BF_BLOCK)
                        return NULL;

                memcpy(dest, xblock, BF_BLOCK - padlen);
                dest += (BF_BLOCK - padlen);
                destlen -= (BF_BLOCK - padlen);

                memcpy(pb->blowfish_ivec_dec, block, BF_BLOCK);
        }

        if(destlenptr != NULL)
                *destlenptr = destlen;

        return dest;
}

void
PerlBlowfishDecryptFlush(struct perl_blowfish *pb)
{
        pb->f_first_dec = 1;

        return;
}

#ifdef MAIN
int
main(int argc, char *argv[])
{
        struct perl_blowfish pb;
        char private_key[56];
        const char *data = "hello world";
        char output[4096];
        char *nptr;
        int outlen;

        /* Fill in the private_key here */
        memset(private_key, 0, sizeof(private_key));

        PerlBlowfishInit(&pb, private_key, sizeof(private_key));

        outlen = sizeof(output);

        /* Data to encrypt is in 'data' and its length is 'strlen(data)' */

        nptr = PerlBlowfishEncrypt(&pb, output, &outlen, data, strlen(data));
        nptr = PerlBlowfishEncryptFlush(&pb, nptr, &outlen);

        printf("outlen=%d\n", sizeof(output) - outlen);

        /* Encrypted data is in 'buffer' and its length is 'outlen' */
}
#endif

--------------A239B5C130215740D9C133D4
Content-Type: text/plain; charset=us-ascii;
 name="perl_blowfish.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="perl_blowfish.h"

/*
 *      $Id$
 *
 *      $Log$
 *
 */

#ifndef _CRYPTO_PERL_BLOWFISH_H
#define _CRYPTO_PERL_BLOWFISH_H

#ifdef OPENSSL_IMPLEMENTATION
#include <openssl/blowfish.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

#ifndef OPENSSL_IMPLEMENTATION
typedef unsigned int IntU32 ;
typedef unsigned char IntU8 ;
#define NROUNDS         16
typedef struct
{
  IntU32 p[2][NROUNDS+2],
         sbox[4][256] ;
} BFkey_type ;

#define BF_BLOCK        8
#endif

struct perl_blowfish {
#ifdef OPENSSL_IMPLEMENTATION
        BF_KEY blowfish_key;
#else
        BFkey_type blowfish_key;
#endif

        unsigned char blowfish_ivec_enc[BF_BLOCK];
        unsigned char blowfish_ivec_dec[BF_BLOCK];

        unsigned char leftover[BF_BLOCK];
        unsigned int left;

        int f_first_enc;
        int f_first_dec;
};

typedef struct perl_blowfish perl_blowfish_t;

extern void PerlBlowfishEnd(struct perl_blowfish *);
extern int PerlBlowfishInit(struct perl_blowfish *, const void *, unsigned int);
extern struct perl_blowfish *PerlBlowfishDestroy(struct perl_blowfish *);
extern struct perl_blowfish *PerlBlowfishCreate(const void *, unsigned int);
extern void *PerlBlowfishEncrypt(struct perl_blowfish *, void *, unsigned int *, const void *, unsigned int);
extern void *PerlBlowfishEncryptFlush(struct perl_blowfish *, void *, unsigned int *);
extern void *PerlBlowfishDecrypt(struct perl_blowfish *, void *, unsigned int *, const void *, unsigned int);
extern void PerlBlowfishDecryptFlush(struct perl_blowfish *);

#ifndef OPENSSL_IMPLEMENTATION
extern void blowfish_crypt_8bytes(IntU8 *, IntU8 *, BFkey_type *, short);
extern int blowfish_make_bfkey(unsigned char *, int, BFkey_type *);
#endif

#ifdef __cplusplus
}
#endif

#endif /* _CRYPTO_PERL_BLOWFISH_H */

--------------A239B5C130215740D9C133D4--



Current thread: