diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2006-05-22 05:12:18 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2006-05-22 05:12:18 +0000 |
commit | aa0f5b38aec14428b4b80e06f90ff781f8bca5f1 (patch) | |
tree | 95f3d0c8cb0d59d88900dbbd72110d7ab6e15b2a /lib/libcrypto/include | |
parent | 7c383bc22113b23718be89fe18eeb251942d7356 (diff) | |
download | vyos-strongswan-aa0f5b38aec14428b4b80e06f90ff781f8bca5f1.tar.gz vyos-strongswan-aa0f5b38aec14428b4b80e06f90ff781f8bca5f1.zip |
Import initial strongswan 2.7.0 version into SVN.
Diffstat (limited to 'lib/libcrypto/include')
-rw-r--r-- | lib/libcrypto/include/cbc_generic.h | 110 | ||||
-rw-r--r-- | lib/libcrypto/include/hmac_generic.h | 60 | ||||
-rw-r--r-- | lib/libcrypto/include/md32_common.h | 607 |
3 files changed, 777 insertions, 0 deletions
diff --git a/lib/libcrypto/include/cbc_generic.h b/lib/libcrypto/include/cbc_generic.h new file mode 100644 index 000000000..0dd3a77d6 --- /dev/null +++ b/lib/libcrypto/include/cbc_generic.h @@ -0,0 +1,110 @@ +#ifndef _CBC_GENERIC_H +#define _CBC_GENERIC_H +/* + * CBC macro helpers + * + * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +/* + * Heavily inspired in loop_AES + */ +#define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \ +int name(ctx_type *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \ + int ret=ilen, pos; \ + const u_int32_t *iv_i; \ + if ((ilen) % 16) return 0; \ + if (encrypt) { \ + pos=0; \ + while(pos<ilen) { \ + if (pos==0) \ + iv_i=(const u_int32_t*) iv; \ + else \ + iv_i=(const u_int32_t*) (out-16); \ + *((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \ + *((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \ + *((u_int32_t *)(&out[ 8])) = iv_i[2]^*((const u_int32_t *)(&in[ 8])); \ + *((u_int32_t *)(&out[12])) = iv_i[3]^*((const u_int32_t *)(&in[12])); \ + enc_func(ctx, (addr_type) out, (addr_type) out); \ + in+=16; \ + out+=16; \ + pos+=16; \ + } \ + } else { \ + pos=ilen-16; \ + in+=pos; \ + out+=pos; \ + while(pos>=0) { \ + dec_func(ctx, (const addr_type) in, (addr_type) out); \ + if (pos==0) \ + iv_i=(const u_int32_t*) (iv); \ + else \ + iv_i=(const u_int32_t*) (in-16); \ + *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ + *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ + *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \ + *((u_int32_t *)(&out[12])) ^= iv_i[3]; \ + in-=16; \ + out-=16; \ + pos-=16; \ + } \ + } \ + return ret; \ +} +#define CBC_IMPL_BLK8(name, ctx_type, addr_type, enc_func, dec_func) \ +int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \ + int ret=ilen, pos; \ + const u_int32_t *iv_i; \ + if ((ilen) % 8) return 0; \ + if (encrypt) { \ + pos=0; \ + while(pos<ilen) { \ + if (pos==0) \ + iv_i=(const u_int32_t*) iv; \ + else \ + iv_i=(const u_int32_t*) (out-8); \ + *((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \ + *((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \ + enc_func(ctx, (addr_type)out, (addr_type)out); \ + in+=8; \ + out+=8; \ + pos+=8; \ + } \ + } else { \ + pos=ilen-8; \ + in+=pos; \ + out+=pos; \ + while(pos>=0) { \ + dec_func(ctx, (const addr_type)in, (addr_type)out); \ + if (pos==0) \ + iv_i=(const u_int32_t*) (iv); \ + else \ + iv_i=(const u_int32_t*) (in-8); \ + *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ + *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ + in-=8; \ + out-=8; \ + pos-=8; \ + } \ + } \ + return ret; \ +} +#define CBC_DECL(name, ctx_type) \ +int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) +/* +Eg.: +CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); +CBC_DECL(AES_cbc_encrypt, aes_context); +*/ +#endif /* _CBC_GENERIC_H */ diff --git a/lib/libcrypto/include/hmac_generic.h b/lib/libcrypto/include/hmac_generic.h new file mode 100644 index 000000000..a749228e3 --- /dev/null +++ b/lib/libcrypto/include/hmac_generic.h @@ -0,0 +1,60 @@ +#ifndef _HMAC_GENERIC_H +#define _HMAC_GENERIC_H +/* + * HMAC macro helpers + * + * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#ifndef DIVUP +#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */ +#endif +#ifndef HMAC_IPAD +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5C +#endif +#define HMAC_SET_KEY_IMPL(func_name, hctx_t, blocksize, func_init, func_update) \ +void func_name(hctx_t *hctx, const u_int8_t * key, int keylen) { \ + int i;\ + u_int8_t kb[blocksize]; \ + for (i = 0; i < DIVUP(keylen*8, 8); i++) { \ + kb[i] = key[i] ^ HMAC_IPAD; \ + } \ + for (; i < blocksize; i++) { \ + kb[i] = HMAC_IPAD; \ + } \ + func_init(&hctx->ictx); \ + func_update(&hctx->ictx, kb, blocksize); \ + for (i = 0; i < blocksize; i++) { \ + kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); \ + } \ + func_init(&hctx->octx); \ + func_update(&hctx->octx, kb, blocksize); \ +} +#define HMAC_HASH_IMPL(func_name, hctx_t, ctx_t, ahlen, func_update, func_result ) \ +void func_name(hctx_t *hctx, const u_int8_t * dat, int len, u_int8_t * hash, int hashlen) { \ + ctx_t ctx; \ + ctx=hctx->ictx; \ + if (dat) func_update(&ctx, dat, len); \ + if (hash) { \ + u_int8_t hash_buf[ahlen]; \ + func_result(&ctx, hash_buf, ahlen); \ + ctx=hctx->octx; \ + func_update(&ctx, hash_buf, ahlen); \ + func_result(&ctx, hash, hashlen); \ + memset(&ctx, 0, sizeof (ctx)); \ + memset(&hash_buf, 0, sizeof (hash_buf));\ + } \ +} +#endif /* _HMAC_GENERIC_H */ diff --git a/lib/libcrypto/include/md32_common.h b/lib/libcrypto/include/md32_common.h new file mode 100644 index 000000000..1a404a458 --- /dev/null +++ b/lib/libcrypto/include/md32_common.h @@ -0,0 +1,607 @@ +/* crypto/md32_common.h */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + * This is a generic 32 bit "collector" for message digest algorithms. + * Whenever needed it collects input character stream into chunks of + * 32 bit values and invokes a block function that performs actual hash + * calculations. + * + * Porting guide. + * + * Obligatory macros: + * + * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN + * this macro defines byte order of input stream. + * HASH_CBLOCK + * size of a unit chunk HASH_BLOCK operates on. + * HASH_LONG + * has to be at lest 32 bit wide, if it's wider, then + * HASH_LONG_LOG2 *has to* be defined along + * HASH_CTX + * context structure that at least contains following + * members: + * typedef struct { + * ... + * HASH_LONG Nl,Nh; + * HASH_LONG data[HASH_LBLOCK]; + * int num; + * ... + * } HASH_CTX; + * HASH_UPDATE + * name of "Update" function, implemented here. + * HASH_TRANSFORM + * name of "Transform" function, implemented here. + * HASH_FINAL + * name of "Final" function, implemented here. + * HASH_BLOCK_HOST_ORDER + * name of "block" function treating *aligned* input message + * in host byte order, implemented externally. + * HASH_BLOCK_DATA_ORDER + * name of "block" function treating *unaligned* input message + * in original (data) byte order, implemented externally (it + * actually is optional if data and host are of the same + * "endianess"). + * HASH_MAKE_STRING + * macro convering context variables to an ASCII hash string. + * + * Optional macros: + * + * B_ENDIAN or L_ENDIAN + * defines host byte-order. + * HASH_LONG_LOG2 + * defaults to 2 if not states otherwise. + * HASH_LBLOCK + * assumed to be HASH_CBLOCK/4 if not stated otherwise. + * HASH_BLOCK_DATA_ORDER_ALIGNED + * alternative "block" function capable of treating + * aligned input message in original (data) order, + * implemented externally. + * + * MD5 example: + * + * #define DATA_ORDER_IS_LITTLE_ENDIAN + * + * #define HASH_LONG MD5_LONG + * #define HASH_LONG_LOG2 MD5_LONG_LOG2 + * #define HASH_CTX MD5_CTX + * #define HASH_CBLOCK MD5_CBLOCK + * #define HASH_LBLOCK MD5_LBLOCK + * #define HASH_UPDATE MD5_Update + * #define HASH_TRANSFORM MD5_Transform + * #define HASH_FINAL MD5_Final + * #define HASH_BLOCK_HOST_ORDER md5_block_host_order + * #define HASH_BLOCK_DATA_ORDER md5_block_data_order + * + * <appro@fy.chalmers.se> + */ + +#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +#error "DATA_ORDER must be defined!" +#endif + +#ifndef HASH_CBLOCK +#error "HASH_CBLOCK must be defined!" +#endif +#ifndef HASH_LONG +#error "HASH_LONG must be defined!" +#endif +#ifndef HASH_CTX +#error "HASH_CTX must be defined!" +#endif + +#ifndef HASH_UPDATE +#error "HASH_UPDATE must be defined!" +#endif +#ifndef HASH_TRANSFORM +#error "HASH_TRANSFORM must be defined!" +#endif +#ifndef HASH_FINAL +#error "HASH_FINAL must be defined!" +#endif + +#ifndef HASH_BLOCK_HOST_ORDER +#error "HASH_BLOCK_HOST_ORDER must be defined!" +#endif + +#if 0 +/* + * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED + * isn't defined. + */ +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#ifndef HASH_LBLOCK +#define HASH_LBLOCK (HASH_CBLOCK/4) +#endif + +#ifndef HASH_LONG_LOG2 +#define HASH_LONG_LOG2 2 +#endif + +/* + * Engage compiler specific rotate intrinsic function if available. + */ +#undef ROTATE +#ifndef PEDANTIC +# if defined(_MSC_VER) +# define ROTATE(a,n) _lrotl(a,n) +# elif defined(__MWERKS__) +# if defined(__POWERPC__) +# define ROTATE(a,n) __rlwinm(a,n,0,31) +# elif defined(__MC68K__) + /* Motorola specific tweak. <appro@fy.chalmers.se> */ +# define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) ) +# else +# define ROTATE(a,n) __rol(a,n) +# endif +# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM) + /* + * Some GNU C inline assembler templates. Note that these are + * rotates by *constant* number of bits! But that's exactly + * what we need here... + * + * <appro@fy.chalmers.se> + */ +# if defined(__i386) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "roll %1,%0" \ + : "=r"(ret) \ + : "I"(n), "0"(a) \ + : "cc"); \ + ret; \ + }) +# elif defined(__powerpc) || defined(__ppc) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "rlwinm %0,%1,%2,0,31" \ + : "=r"(ret) \ + : "r"(a), "I"(n)); \ + ret; \ + }) +# endif +# endif + +/* + * Engage compiler specific "fetch in reverse byte order" + * intrinsic function if available. + */ +# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM) + /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */ +# if defined(__i386) && !defined(I386_ONLY) +# define BE_FETCH32(a) ({ register unsigned int l=(a);\ + asm ( \ + "bswapl %0" \ + : "=r"(l) : "0"(l)); \ + l; \ + }) +# elif defined(__powerpc) +# define LE_FETCH32(a) ({ register unsigned int l; \ + asm ( \ + "lwbrx %0,0,%1" \ + : "=r"(l) \ + : "r"(a)); \ + l; \ + }) + +# elif defined(__sparc) && defined(ULTRASPARC) +# define LE_FETCH32(a) ({ register unsigned int l; \ + asm ( \ + "lda [%1]#ASI_PRIMARY_LITTLE,%0"\ + : "=r"(l) \ + : "r"(a)); \ + l; \ + }) +# endif +# endif +#endif /* PEDANTIC */ + +#if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */ +/* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */ +#ifdef ROTATE +/* 5 instructions with rotate instruction, else 9 */ +#define REVERSE_FETCH32(a,l) ( \ + l=*(const HASH_LONG *)(a), \ + ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \ + ) +#else +/* 6 instructions with rotate instruction, else 8 */ +#define REVERSE_FETCH32(a,l) ( \ + l=*(const HASH_LONG *)(a), \ + l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \ + ROTATE(l,16) \ + ) +/* + * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|... + * It's rewritten as above for two reasons: + * - RISCs aren't good at long constants and have to explicitely + * compose 'em with several (well, usually 2) instructions in a + * register before performing the actual operation and (as you + * already realized:-) having same constant should inspire the + * compiler to permanently allocate the only register for it; + * - most modern CPUs have two ALUs, but usually only one has + * circuitry for shifts:-( this minor tweak inspires compiler + * to schedule shift instructions in a better way... + * + * <appro@fy.chalmers.se> + */ +#endif +#endif + +#ifndef ROTATE +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* + * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED + * and HASH_BLOCK_HOST_ORDER ought to be the same if input data + * and host are of the same "endianess". It's possible to mask + * this with blank #define HASH_BLOCK_DATA_ORDER though... + * + * <appro@fy.chalmers.se> + */ +#if defined(B_ENDIAN) +# if defined(DATA_ORDER_IS_BIG_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# ifndef HOST_FETCH32 +# ifdef LE_FETCH32 +# define HOST_FETCH32(p,l) LE_FETCH32(p) +# elif defined(REVERSE_FETCH32) +# define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l) +# endif +# endif +# endif +#elif defined(L_ENDIAN) +# if defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# elif defined(DATA_ORDER_IS_BIG_ENDIAN) +# ifndef HOST_FETCH32 +# ifdef BE_FETCH32 +# define HOST_FETCH32(p,l) BE_FETCH32(p) +# elif defined(REVERSE_FETCH32) +# define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l) +# endif +# endif +# endif +#endif + +#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ), \ + l) +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + case 3: l|=((unsigned long)(*((c)++))); \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<< 8; \ + case 2: l|=((unsigned long)(*(--(c))))<<16; \ + case 1: l|=((unsigned long)(*(--(c))))<<24; \ + } } +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24), \ + l) +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))); \ + } } +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + l) + +#endif + +/* + * Time for some action:-) + */ + +void HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len) + { + const unsigned char *data=data_; + register HASH_LONG * p; + register unsigned long l; + int sw,sc,ew,ec; + + if (len==0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to + * Wei Dai <weidai@eskimo.com> for pointing it out. */ + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= HASH_CBLOCK) + { + l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; + for (; sw<HASH_LBLOCK; sw++) + { + HOST_c2l(data,l); p[sw]=l; + } + HASH_BLOCK_HOST_ORDER (c,p,1); + len-=(HASH_CBLOCK-c->num); + c->num=0; + /* drop through and do the rest */ + } + else + { + c->num+=len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; + for (; sw < ew; sw++) + { + HOST_c2l(data,l); p[sw]=l; + } + if (ec) + { + HOST_c2l_p(data,l,ec); p[sw]=l; + } + } + return; + } + } + + sw=len/HASH_CBLOCK; + if (sw > 0) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + /* + * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined + * only if sizeof(HASH_LONG)==4. + */ + if ((((unsigned long)data)%4) == 0) + { + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } + else +#if !defined(HASH_BLOCK_DATA_ORDER) + while (sw--) + { + memcpy (p=c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1); + data+=HASH_CBLOCK; + len-=HASH_CBLOCK; + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + { + HASH_BLOCK_DATA_ORDER(c,data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } +#endif + } + + if (len!=0) + { + p = c->data; + c->num = len; + ew=len>>2; /* words to copy */ + ec=len&0x03; + for (; ew; ew--,p++) + { + HOST_c2l(data,l); *p=l; + } + HOST_c2l_p(data,l,ec); + *p=l; + } + } + + +void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + if ((((unsigned long)data)%4) == 0) + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1); + else +#if !defined(HASH_BLOCK_DATA_ORDER) + { + memcpy (c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1); + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + HASH_BLOCK_DATA_ORDER (c,data,1); +#endif + } + + +void HASH_FINAL (unsigned char *md, HASH_CTX *c) + { + register HASH_LONG *p; + register unsigned long l; + register int i,j; + static const unsigned char end[4]={0x80,0x00,0x00,0x00}; + const unsigned char *cp=end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + i=c->num>>2; + j=c->num&0x03; + +#if 0 + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + * Many thanks to Alex Tang <altitude@cic.net> for pickup this + * 'potential bug' */ +#ifdef PURIFY + if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */ +#endif + l=p[i]; +#else + l = (j==0) ? 0 : p[i]; +#endif + HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */ + + if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */ + { + if (i<HASH_LBLOCK) p[i]=0; + HASH_BLOCK_HOST_ORDER (c,p,1); + i=0; + } + for (; i<(HASH_LBLOCK-2); i++) + p[i]=0; + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + p[HASH_LBLOCK-2]=c->Nh; + p[HASH_LBLOCK-1]=c->Nl; +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + p[HASH_LBLOCK-2]=c->Nl; + p[HASH_LBLOCK-1]=c->Nh; +#endif + HASH_BLOCK_HOST_ORDER (c,p,1); + +#ifndef HASH_MAKE_STRING +#error "HASH_MAKE_STRING must be defined!" +#else + HASH_MAKE_STRING(c,md); +#endif + + c->num=0; + /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack + * but I'm not worried :-) + memset((void *)c,0,sizeof(HASH_CTX)); + */ + } |