/* ey_crypt.c */ /* Copyright (C) 1995 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This file is part of an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL * specification. This library and applications are * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE * as long as the following conditions are aheared to. * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. If this code is used in a product, * Eric Young should be given attribution as the author of the parts used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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 acknowledgement: * This product includes software developed by Eric Young (eay@mincom.oz.au) * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS 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 AUTHOR OR 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. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include <stdio.h> #include <stdlib.h> #include <string.h> int str_len(const char *s); // dawnlib.cpp #define LONGCRYPT // Kal, Jan04 - makes passwords longer than 8 characters possible /* Eric Young. * This version of crypt has been developed from my MIT compatable * DES library. * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au * eay@mincom.oz.au or eay@psych.psy.uq.oz.au */ /* Modification by Jens Kupferschmidt (Cu) * I have included directive PARA for shared memory computers. * I have included a directive LONGCRYPT to using this routine to cipher * passwords with more then 8 bytes like HP-UX 10.x it used. The MAXPLEN * definition is the maximum of length of password and can changed. I have * defined 24. */ #if !defined(_LIBC) || defined(NOCONST) #define const #endif typedef unsigned char des_cblock[8]; typedef struct des_ks_struct { union { des_cblock _; /* make sure things are correct size on machines with * 8 byte longs */ unsigned long pad[2]; } ks; #define _ ks._ } des_key_schedule[16]; #define DES_KEY_SZ (sizeof(des_cblock)) #define DES_ENCRYPT 1 #define DES_DECRYPT 0 #define ITERATIONS 16 #define HALF_ITERATIONS 8 #define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ l|=((unsigned long)(*((c)++)))<< 8, \ l|=((unsigned long)(*((c)++)))<<16, \ l|=((unsigned long)(*((c)++)))<<24) #define 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)) static const unsigned long SPtrans[8][64]={ { /* nibble 0 */ 0x00820200L, 0x00020000L, 0x80800000L, 0x80820200L, 0x00800000L, 0x80020200L, 0x80020000L, 0x80800000L, 0x80020200L, 0x00820200L, 0x00820000L, 0x80000200L, 0x80800200L, 0x00800000L, 0x00000000L, 0x80020000L, 0x00020000L, 0x80000000L, 0x00800200L, 0x00020200L, 0x80820200L, 0x00820000L, 0x80000200L, 0x00800200L, 0x80000000L, 0x00000200L, 0x00020200L, 0x80820000L, 0x00000200L, 0x80800200L, 0x80820000L, 0x00000000L, 0x00000000L, 0x80820200L, 0x00800200L, 0x80020000L, 0x00820200L, 0x00020000L, 0x80000200L, 0x00800200L, 0x80820000L, 0x00000200L, 0x00020200L, 0x80800000L, 0x80020200L, 0x80000000L, 0x80800000L, 0x00820000L, 0x80820200L, 0x00020200L, 0x00820000L, 0x80800200L, 0x00800000L, 0x80000200L, 0x80020000L, 0x00000000L, 0x00020000L, 0x00800000L, 0x80800200L, 0x00820200L, 0x80000000L, 0x80820000L, 0x00000200L, 0x80020200L, },{ /* nibble 1 */ 0x10042004L, 0x00000000L, 0x00042000L, 0x10040000L, 0x10000004L, 0x00002004L, 0x10002000L, 0x00042000L, 0x00002000L, 0x10040004L, 0x00000004L, 0x10002000L, 0x00040004L, 0x10042000L, 0x10040000L, 0x00000004L, 0x00040000L, 0x10002004L, 0x10040004L, 0x00002000L, 0x00042004L, 0x10000000L, 0x00000000L, 0x00040004L, 0x10002004L, 0x00042004L, 0x10042000L, 0x10000004L, 0x10000000L, 0x00040000L, 0x00002004L, 0x10042004L, 0x00040004L, 0x10042000L, 0x10002000L, 0x00042004L, 0x10042004L, 0x00040004L, 0x10000004L, 0x00000000L, 0x10000000L, 0x00002004L, 0x00040000L, 0x10040004L, 0x00002000L, 0x10000000L, 0x00042004L, 0x10002004L, 0x10042000L, 0x00002000L, 0x00000000L, 0x10000004L, 0x00000004L, 0x10042004L, 0x00042000L, 0x10040000L, 0x10040004L, 0x00040000L, 0x00002004L, 0x10002000L, 0x10002004L, 0x00000004L, 0x10040000L, 0x00042000L, },{ /* nibble 2 */ 0x41000000L, 0x01010040L, 0x00000040L, 0x41000040L, 0x40010000L, 0x01000000L, 0x41000040L, 0x00010040L, 0x01000040L, 0x00010000L, 0x01010000L, 0x40000000L, 0x41010040L, 0x40000040L, 0x40000000L, 0x41010000L, 0x00000000L, 0x40010000L, 0x01010040L, 0x00000040L, 0x40000040L, 0x41010040L, 0x00010000L, 0x41000000L, 0x41010000L, 0x01000040L, 0x40010040L, 0x01010000L, 0x00010040L, 0x00000000L, 0x01000000L, 0x40010040L, 0x01010040L, 0x00000040L, 0x40000000L, 0x00010000L, 0x40000040L, 0x40010000L, 0x01010000L, 0x41000040L, 0x00000000L, 0x01010040L, 0x00010040L, 0x41010000L, 0x40010000L, 0x01000000L, 0x41010040L, 0x40000000L, 0x40010040L, 0x41000000L, 0x01000000L, 0x41010040L, 0x00010000L, 0x01000040L, 0x41000040L, 0x00010040L, 0x01000040L, 0x00000000L, 0x41010000L, 0x40000040L, 0x41000000L, 0x40010040L, 0x00000040L, 0x01010000L, },{ /* nibble 3 */ 0x00100402L, 0x04000400L, 0x00000002L, 0x04100402L, 0x00000000L, 0x04100000L, 0x04000402L, 0x00100002L, 0x04100400L, 0x04000002L, 0x04000000L, 0x00000402L, 0x04000002L, 0x00100402L, 0x00100000L, 0x04000000L, 0x04100002L, 0x00100400L, 0x00000400L, 0x00000002L, 0x00100400L, 0x04000402L, 0x04100000L, 0x00000400L, 0x00000402L, 0x00000000L, 0x00100002L, 0x04100400L, 0x04000400L, 0x04100002L, 0x04100402L, 0x00100000L, 0x04100002L, 0x00000402L, 0x00100000L, 0x04000002L, 0x00100400L, 0x04000400L, 0x00000002L, 0x04100000L, 0x04000402L, 0x00000000L, 0x00000400L, 0x00100002L, 0x00000000L, 0x04100002L, 0x04100400L, 0x00000400L, 0x04000000L, 0x04100402L, 0x00100402L, 0x00100000L, 0x04100402L, 0x00000002L, 0x04000400L, 0x00100402L, 0x00100002L, 0x00100400L, 0x04100000L, 0x04000402L, 0x00000402L, 0x04000000L, 0x04000002L, 0x04100400L, },{ /* nibble 4 */ 0x02000000L, 0x00004000L, 0x00000100L, 0x02004108L, 0x02004008L, 0x02000100L, 0x00004108L, 0x02004000L, 0x00004000L, 0x00000008L, 0x02000008L, 0x00004100L, 0x02000108L, 0x02004008L, 0x02004100L, 0x00000000L, 0x00004100L, 0x02000000L, 0x00004008L, 0x00000108L, 0x02000100L, 0x00004108L, 0x00000000L, 0x02000008L, 0x00000008L, 0x02000108L, 0x02004108L, 0x00004008L, 0x02004000L, 0x00000100L, 0x00000108L, 0x02004100L, 0x02004100L, 0x02000108L, 0x00004008L, 0x02004000L, 0x00004000L, 0x00000008L, 0x02000008L, 0x02000100L, 0x02000000L, 0x00004100L, 0x02004108L, 0x00000000L, 0x00004108L, 0x02000000L, 0x00000100L, 0x00004008L, 0x02000108L, 0x00000100L, 0x00000000L, 0x02004108L, 0x02004008L, 0x02004100L, 0x00000108L, 0x00004000L, 0x00004100L, 0x02004008L, 0x02000100L, 0x00000108L, 0x00000008L, 0x00004108L, 0x02004000L, 0x02000008L, },{ /* nibble 5 */ 0x20000010L, 0x00080010L, 0x00000000L, 0x20080800L, 0x00080010L, 0x00000800L, 0x20000810L, 0x00080000L, 0x00000810L, 0x20080810L, 0x00080800L, 0x20000000L, 0x20000800L, 0x20000010L, 0x20080000L, 0x00080810L, 0x00080000L, 0x20000810L, 0x20080010L, 0x00000000L, 0x00000800L, 0x00000010L, 0x20080800L, 0x20080010L, 0x20080810L, 0x20080000L, 0x20000000L, 0x00000810L, 0x00000010L, 0x00080800L, 0x00080810L, 0x20000800L, 0x00000810L, 0x20000000L, 0x20000800L, 0x00080810L, 0x20080800L, 0x00080010L, 0x00000000L, 0x20000800L, 0x20000000L, 0x00000800L, 0x20080010L, 0x00080000L, 0x00080010L, 0x20080810L, 0x00080800L, 0x00000010L, 0x20080810L, 0x00080800L, 0x00080000L, 0x20000810L, 0x20000010L, 0x20080000L, 0x00080810L, 0x00000000L, 0x00000800L, 0x20000010L, 0x20000810L, 0x20080800L, 0x20080000L, 0x00000810L, 0x00000010L, 0x20080010L, },{ /* nibble 6 */ 0x00001000L, 0x00000080L, 0x00400080L, 0x00400001L, 0x00401081L, 0x00001001L, 0x00001080L, 0x00000000L, 0x00400000L, 0x00400081L, 0x00000081L, 0x00401000L, 0x00000001L, 0x00401080L, 0x00401000L, 0x00000081L, 0x00400081L, 0x00001000L, 0x00001001L, 0x00401081L, 0x00000000L, 0x00400080L, 0x00400001L, 0x00001080L, 0x00401001L, 0x00001081L, 0x00401080L, 0x00000001L, 0x00001081L, 0x00401001L, 0x00000080L, 0x00400000L, 0x00001081L, 0x00401000L, 0x00401001L, 0x00000081L, 0x00001000L, 0x00000080L, 0x00400000L, 0x00401001L, 0x00400081L, 0x00001081L, 0x00001080L, 0x00000000L, 0x00000080L, 0x00400001L, 0x00000001L, 0x00400080L, 0x00000000L, 0x00400081L, 0x00400080L, 0x00001080L, 0x00000081L, 0x00001000L, 0x00401081L, 0x00400000L, 0x00401080L, 0x00000001L, 0x00001001L, 0x00401081L, 0x00400001L, 0x00401080L, 0x00401000L, 0x00001001L, },{ /* nibble 7 */ 0x08200020L, 0x08208000L, 0x00008020L, 0x00000000L, 0x08008000L, 0x00200020L, 0x08200000L, 0x08208020L, 0x00000020L, 0x08000000L, 0x00208000L, 0x00008020L, 0x00208020L, 0x08008020L, 0x08000020L, 0x08200000L, 0x00008000L, 0x00208020L, 0x00200020L, 0x08008000L, 0x08208020L, 0x08000020L, 0x00000000L, 0x00208000L, 0x08000000L, 0x00200000L, 0x08008020L, 0x08200020L, 0x00200000L, 0x00008000L, 0x08208000L, 0x00000020L, 0x00200000L, 0x00008000L, 0x08000020L, 0x08208020L, 0x00008020L, 0x08000000L, 0x00000000L, 0x00208000L, 0x08200020L, 0x08008020L, 0x08008000L, 0x00200020L, 0x08208000L, 0x00000020L, 0x00200020L, 0x08008000L, 0x08208020L, 0x00200000L, 0x08200000L, 0x08000020L, 0x00208000L, 0x00008020L, 0x08008020L, 0x08200000L, 0x00000020L, 0x08208000L, 0x00208020L, 0x00000000L, 0x08000000L, 0x08200020L, 0x00008000L, 0x00208020L}}; static const unsigned long skb[8][64]={ { /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ 0x00000000L,0x00000010L,0x20000000L,0x20000010L, 0x00010000L,0x00010010L,0x20010000L,0x20010010L, 0x00000800L,0x00000810L,0x20000800L,0x20000810L, 0x00010800L,0x00010810L,0x20010800L,0x20010810L, 0x00000020L,0x00000030L,0x20000020L,0x20000030L, 0x00010020L,0x00010030L,0x20010020L,0x20010030L, 0x00000820L,0x00000830L,0x20000820L,0x20000830L, 0x00010820L,0x00010830L,0x20010820L,0x20010830L, 0x00080000L,0x00080010L,0x20080000L,0x20080010L, 0x00090000L,0x00090010L,0x20090000L,0x20090010L, 0x00080800L,0x00080810L,0x20080800L,0x20080810L, 0x00090800L,0x00090810L,0x20090800L,0x20090810L, 0x00080020L,0x00080030L,0x20080020L,0x20080030L, 0x00090020L,0x00090030L,0x20090020L,0x20090030L, 0x00080820L,0x00080830L,0x20080820L,0x20080830L, 0x00090820L,0x00090830L,0x20090820L,0x20090830L, },{ /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ 0x00000000L,0x02000000L,0x00002000L,0x02002000L, 0x00200000L,0x02200000L,0x00202000L,0x02202000L, 0x00000004L,0x02000004L,0x00002004L,0x02002004L, 0x00200004L,0x02200004L,0x00202004L,0x02202004L, 0x00000400L,0x02000400L,0x00002400L,0x02002400L, 0x00200400L,0x02200400L,0x00202400L,0x02202400L, 0x00000404L,0x02000404L,0x00002404L,0x02002404L, 0x00200404L,0x02200404L,0x00202404L,0x02202404L, 0x10000000L,0x12000000L,0x10002000L,0x12002000L, 0x10200000L,0x12200000L,0x10202000L,0x12202000L, 0x10000004L,0x12000004L,0x10002004L,0x12002004L, 0x10200004L,0x12200004L,0x10202004L,0x12202004L, 0x10000400L,0x12000400L,0x10002400L,0x12002400L, 0x10200400L,0x12200400L,0x10202400L,0x12202400L, 0x10000404L,0x12000404L,0x10002404L,0x12002404L, 0x10200404L,0x12200404L,0x10202404L,0x12202404L, },{ /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ 0x00000000L,0x00000001L,0x00040000L,0x00040001L, 0x01000000L,0x01000001L,0x01040000L,0x01040001L, 0x00000002L,0x00000003L,0x00040002L,0x00040003L, 0x01000002L,0x01000003L,0x01040002L,0x01040003L, 0x00000200L,0x00000201L,0x00040200L,0x00040201L, 0x01000200L,0x01000201L,0x01040200L,0x01040201L, 0x00000202L,0x00000203L,0x00040202L,0x00040203L, 0x01000202L,0x01000203L,0x01040202L,0x01040203L, 0x08000000L,0x08000001L,0x08040000L,0x08040001L, 0x09000000L,0x09000001L,0x09040000L,0x09040001L, 0x08000002L,0x08000003L,0x08040002L,0x08040003L, 0x09000002L,0x09000003L,0x09040002L,0x09040003L, 0x08000200L,0x08000201L,0x08040200L,0x08040201L, 0x09000200L,0x09000201L,0x09040200L,0x09040201L, 0x08000202L,0x08000203L,0x08040202L,0x08040203L, 0x09000202L,0x09000203L,0x09040202L,0x09040203L, },{ /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ 0x00000000L,0x00100000L,0x00000100L,0x00100100L, 0x00000008L,0x00100008L,0x00000108L,0x00100108L, 0x00001000L,0x00101000L,0x00001100L,0x00101100L, 0x00001008L,0x00101008L,0x00001108L,0x00101108L, 0x04000000L,0x04100000L,0x04000100L,0x04100100L, 0x04000008L,0x04100008L,0x04000108L,0x04100108L, 0x04001000L,0x04101000L,0x04001100L,0x04101100L, 0x04001008L,0x04101008L,0x04001108L,0x04101108L, 0x00020000L,0x00120000L,0x00020100L,0x00120100L, 0x00020008L,0x00120008L,0x00020108L,0x00120108L, 0x00021000L,0x00121000L,0x00021100L,0x00121100L, 0x00021008L,0x00121008L,0x00021108L,0x00121108L, 0x04020000L,0x04120000L,0x04020100L,0x04120100L, 0x04020008L,0x04120008L,0x04020108L,0x04120108L, 0x04021000L,0x04121000L,0x04021100L,0x04121100L, 0x04021008L,0x04121008L,0x04021108L,0x04121108L, },{ /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ 0x00000000L,0x10000000L,0x00010000L,0x10010000L, 0x00000004L,0x10000004L,0x00010004L,0x10010004L, 0x20000000L,0x30000000L,0x20010000L,0x30010000L, 0x20000004L,0x30000004L,0x20010004L,0x30010004L, 0x00100000L,0x10100000L,0x00110000L,0x10110000L, 0x00100004L,0x10100004L,0x00110004L,0x10110004L, 0x20100000L,0x30100000L,0x20110000L,0x30110000L, 0x20100004L,0x30100004L,0x20110004L,0x30110004L, 0x00001000L,0x10001000L,0x00011000L,0x10011000L, 0x00001004L,0x10001004L,0x00011004L,0x10011004L, 0x20001000L,0x30001000L,0x20011000L,0x30011000L, 0x20001004L,0x30001004L,0x20011004L,0x30011004L, 0x00101000L,0x10101000L,0x00111000L,0x10111000L, 0x00101004L,0x10101004L,0x00111004L,0x10111004L, 0x20101000L,0x30101000L,0x20111000L,0x30111000L, 0x20101004L,0x30101004L,0x20111004L,0x30111004L, },{ /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ 0x00000000L,0x08000000L,0x00000008L,0x08000008L, 0x00000400L,0x08000400L,0x00000408L,0x08000408L, 0x00020000L,0x08020000L,0x00020008L,0x08020008L, 0x00020400L,0x08020400L,0x00020408L,0x08020408L, 0x00000001L,0x08000001L,0x00000009L,0x08000009L, 0x00000401L,0x08000401L,0x00000409L,0x08000409L, 0x00020001L,0x08020001L,0x00020009L,0x08020009L, 0x00020401L,0x08020401L,0x00020409L,0x08020409L, 0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, 0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, 0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, 0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, 0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, 0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, 0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, 0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, },{ /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ 0x00000000L,0x00000100L,0x00080000L,0x00080100L, 0x01000000L,0x01000100L,0x01080000L,0x01080100L, 0x00000010L,0x00000110L,0x00080010L,0x00080110L, 0x01000010L,0x01000110L,0x01080010L,0x01080110L, 0x00200000L,0x00200100L,0x00280000L,0x00280100L, 0x01200000L,0x01200100L,0x01280000L,0x01280100L, 0x00200010L,0x00200110L,0x00280010L,0x00280110L, 0x01200010L,0x01200110L,0x01280010L,0x01280110L, 0x00000200L,0x00000300L,0x00080200L,0x00080300L, 0x01000200L,0x01000300L,0x01080200L,0x01080300L, 0x00000210L,0x00000310L,0x00080210L,0x00080310L, 0x01000210L,0x01000310L,0x01080210L,0x01080310L, 0x00200200L,0x00200300L,0x00280200L,0x00280300L, 0x01200200L,0x01200300L,0x01280200L,0x01280300L, 0x00200210L,0x00200310L,0x00280210L,0x00280310L, 0x01200210L,0x01200310L,0x01280210L,0x01280310L, },{ /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ 0x00000000L,0x04000000L,0x00040000L,0x04040000L, 0x00000002L,0x04000002L,0x00040002L,0x04040002L, 0x00002000L,0x04002000L,0x00042000L,0x04042000L, 0x00002002L,0x04002002L,0x00042002L,0x04042002L, 0x00000020L,0x04000020L,0x00040020L,0x04040020L, 0x00000022L,0x04000022L,0x00040022L,0x04040022L, 0x00002020L,0x04002020L,0x00042020L,0x04042020L, 0x00002022L,0x04002022L,0x00042022L,0x04042022L, 0x00000800L,0x04000800L,0x00040800L,0x04040800L, 0x00000802L,0x04000802L,0x00040802L,0x04040802L, 0x00002800L,0x04002800L,0x00042800L,0x04042800L, 0x00002802L,0x04002802L,0x00042802L,0x04042802L, 0x00000820L,0x04000820L,0x00040820L,0x04040820L, 0x00000822L,0x04000822L,0x00040822L,0x04040822L, 0x00002820L,0x04002820L,0x00042820L,0x04042820L, 0x00002822L,0x04002822L,0x00042822L,0x04042822L, } }; /* See ecb_encrypt.c for a pseudo description of these macros. */ #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ (b)^=(t),\ (a)^=((t)<<(n))) #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ (a)=(a)^(t)^(t>>(16-(n))))\ static const int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; #ifndef NOPROTO #ifdef PARA int body(unsigned long *out0, unsigned long *out1, des_key_schedule ks, unsigned long Eswap0, unsigned long Eswap1); int des_set_key(des_cblock (*key), des_key_schedule schedule); #else static int body(unsigned long *out0, unsigned long *out1, des_key_schedule ks, unsigned long Eswap0, unsigned long Eswap1); static int des_set_key(des_cblock (*key), des_key_schedule schedule); #endif #else #ifdef PARA int body(); int des_set_key(); #else static int body(); static int des_set_key(); #endif #endif #ifdef PARA int des_set_key(des_cblock key, des_key_schedule schedule) #else static int des_set_key(des_cblock *key, des_key_schedule schedule) #endif { register unsigned long c,d,t,s; register unsigned char *in; register unsigned long *k; register int i; k=(unsigned long *)schedule; in=(unsigned char *)key; c2l(in,c); c2l(in,d); /* I now do it in 47 simple operations :-) * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) * for the inspiration. :-) */ PERM_OP (d,c,t,4,0x0f0f0f0fL); HPERM_OP(c,t,-2,0xcccc0000L); HPERM_OP(d,t,-2,0xcccc0000L); PERM_OP (d,c,t,1,0x55555555L); PERM_OP (c,d,t,8,0x00ff00ffL); PERM_OP (d,c,t,1,0x55555555L); d= (((d&0x000000ffL)<<16)| (d&0x0000ff00L) | ((d&0x00ff0000L)>>16)|((c&0xf0000000L)>>4)); c&=0x0fffffffL; for (i=0; i<ITERATIONS; i++) { if (shifts2[i]) { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); } else { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); } c&=0x0fffffffL; d&=0x0fffffffL; /* could be a few less shifts but I am to lazy at this * point in time to investigate */ s= skb[0][ (c )&0x3f ]| skb[1][((c>> 6L)&0x03)|((c>> 7L)&0x3c)]| skb[2][((c>>13L)&0x0f)|((c>>14L)&0x30)]| skb[3][((c>>20L)&0x01)|((c>>21L)&0x06) | ((c>>22L)&0x38)]; t= skb[4][ (d )&0x3f ]| skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]| skb[6][ (d>>15L)&0x3f ]| skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)]; /* table contained 0213 4657 */ *(k++)=((t<<16)|(s&0x0000ffffL))&0xffffffffL; s= ((s>>16)|(t&0xffff0000L)); s=(s<<4)|(s>>28); *(k++)=s&0xffffffffL; } return(0); } /****************************************************************** * modified stuff for crypt. ******************************************************************/ /* The changes to this macro may help or hinder, depending on the * compiler and the achitecture. gcc2 always seems to do well :-). * Inspired by Dana How <how@isl.stanford.edu> * DO NOT use the alternative version on machines with 8 byte longs. */ #ifdef DES_USE_PTR #define D_ENCRYPT(L,R,S) \ t=(R^(R>>16)); \ u=(t&E0); \ t=(t&E1); \ u=((u^(u<<16))^R^s[S ])<<2; \ t=(t^(t<<16))^R^s[S+1]; \ t=(t>>2)|(t<<30); \ L^= \ *(unsigned long *)(des_SP+0x0100+((t )&0xfc))+ \ *(unsigned long *)(des_SP+0x0300+((t>> 8)&0xfc))+ \ *(unsigned long *)(des_SP+0x0500+((t>>16)&0xfc))+ \ *(unsigned long *)(des_SP+0x0700+((t>>24)&0xfc))+ \ *(unsigned long *)(des_SP+ ((u )&0xfc))+ \ *(unsigned long *)(des_SP+0x0200+((u>> 8)&0xfc))+ \ *(unsigned long *)(des_SP+0x0400+((u>>16)&0xfc))+ \ *(unsigned long *)(des_SP+0x0600+((u>>24)&0xfc)); #else /* original version */ #define D_ENCRYPT(L,R,S) \ t=(R^(R>>16)); \ u=(t&E0); \ t=(t&E1); \ u=(u^(u<<16))^R^s[S ]; \ t=(t^(t<<16))^R^s[S+1]; \ t=(t>>4)|(t<<28); \ L^= SPtrans[1][(t )&0x3f]| \ SPtrans[3][(t>> 8)&0x3f]| \ SPtrans[5][(t>>16)&0x3f]| \ SPtrans[7][(t>>24)&0x3f]| \ SPtrans[0][(u )&0x3f]| \ SPtrans[2][(u>> 8)&0x3f]| \ SPtrans[4][(u>>16)&0x3f]| \ SPtrans[6][(u>>24)&0x3f]; #endif /* Added more values to handle illegal salt values the way normal * crypt() implementations do. The patch was sent by * Bjorn Gronvall <bg@sics.se> */ static unsigned const char con_salt[128]={ 0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, 0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1, 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, 0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, 0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9, 0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01, 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A, 0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12, 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A, 0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22, 0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24, 0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C, 0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34, 0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C, 0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44, }; static unsigned const char cov_2char[64]={ 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, 0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44, 0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C, 0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54, 0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62, 0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, 0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72, 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A }; #ifndef NOPROTO #ifdef PERL5 char *des_crypt(char *buf,char *salt); #else char *ey_crypt(char *buf,char *salt); #endif #else #ifdef PERL5 char *des_crypt(); #else char *ey_crypt(); #endif #endif #ifdef PERL5 char *des_crypt(char *buf, char *salt_word) #else char *ey_crypt(char *buf, char *salt) #endif { unsigned int i,j,x,y; #ifdef LONGCRYPT #define MAXPLEN 24 unsigned int r,k,min; unsigned long out[2*(MAXPLEN/8)],ll; #else unsigned long out[2],ll; #endif #ifdef LONGCRYPT #ifdef PARA unsigned char buff[11*(MAXPLEN/8)+4]; #else static unsigned char buff[11*(MAXPLEN/8)+4]; #endif #else #ifdef PARA unsigned char buff[20]; #else static unsigned char buff[20]; #endif #endif unsigned long Eswap0=0,Eswap1=0; des_cblock key; des_key_schedule ks; unsigned char bb[16]; #ifdef LONGCRYPT unsigned char *b; #else unsigned char *b=bb; #endif unsigned char c,u; /* eay 25/08/92 * If you call crypt("pwd","*") as often happens when you * have * as the pwd field in /etc/passwd, the function * returns *\0XXXXXXXXX * The \0 makes the string look like * so the pwd "*" would * crypt to "*". This was found when replacing the crypt in * our shared libraries. People found that the disbled * accounts effectivly had no passwd :-(. */ /* -printf("IN -> %s %s\n",buf,salt); */ #ifdef LONGCRYPT x=buff[0]=((salt[0] == '\0')?'A':salt[0]); Eswap0=con_salt[x]; x=buff[1]=((salt[1] == '\0')?'A':salt[1]); Eswap1=con_salt[x]<<4; r=str_len(buf); if ((r%8)==0) r/=8; else r=(r/8)+1; min=2; #ifdef PARA #pragma _CNX no_parallel #endif for (k=0; k<r; k++) { b=(unsigned char *) &bb; #ifdef PARA #pragma _CNX no_parallel #endif for (i=0; i<8; i++) { c= *(buf++); if (!c) break; key[i]=(c<<1); } #ifdef PARA #pragma _CNX no_parallel #endif for (; i<8; i++){ key[i]=0; } des_set_key((des_cblock *)(key),ks); body(&(out[0+(k*2)]),&(out[1+(k*2)]),ks,Eswap0,Eswap1); ll=out[0+(k*2)]; l2c(ll,b); ll=out[1+(k*2)]; l2c(ll,b); y=0; u=0x80; bb[8]=0; for (i=min; i<min+11; i++) { c=0; for (j=0; j<6; j++) { c<<=1; if (bb[y] & u) c|=1; u>>=1; if (!u) { y++; u=0x80; } } buff[i]=cov_2char[c]; } min+=11; x=((salt[2+k*11] == '\0')?'A':salt[2+k*11]); Eswap0=con_salt[x]; x=((salt[3+k*11] == '\0')?'A':salt[3+k*11]); Eswap1=con_salt[x]<<4; } buff[2+r*11]='\0'; #else x=buff[0]=((salt[0] == '\0')?'A':salt[0]); Eswap0=con_salt[x]; x=buff[1]=((salt[1] == '\0')?'A':salt[1]); Eswap1=con_salt[x]<<4; for (i=0; i<8; i++) { c= *(buf++); if (!c) break; key[i]=(c<<1); } for (; i<8; i++) key[i]=0; des_set_key((des_cblock *)(key),ks); body(&(out[0]),&(out[1]),ks,Eswap0,Eswap1); ll=out[0]; l2c(ll,b); ll=out[1]; l2c(ll,b); y=0; u=0x80; bb[8]=0; for (i=2; i<13; i++) { c=0; for (j=0; j<6; j++) { c<<=1; if (bb[y] & u) c|=1; u>>=1; if (!u) { y++; u=0x80; } } buff[i]=cov_2char[c]; } buff[13]='\0'; #endif return((char *)buff); } #ifdef PARA int body(unsigned long *out0, unsigned long *out1, des_key_schedule ks, unsigned long Eswap0, unsigned long Eswap1) #else static int body(unsigned long *out0, unsigned long *out1, des_key_schedule ks, unsigned long Eswap0, unsigned long Eswap1) #endif { register unsigned long l,r,t,u; #ifdef DES_USE_PTR register unsigned char *des_SP=(unsigned char *)SPtrans; #endif register unsigned long *s; register int i,j; register unsigned long E0,E1; l=0; r=0; s=(unsigned long *)ks; E0=Eswap0; E1=Eswap1; for (j=0; j<25; j++) { for (i=0; i<(ITERATIONS*2); i+=4) { D_ENCRYPT(l,r, i); /* 1 */ D_ENCRYPT(r,l, i+2); /* 2 */ } t=l; l=r; r=t; } t=r; r=(l>>1L)|(l<<31L); l=(t>>1L)|(t<<31L); /* clear the top bits on machines with 8byte longs */ l&=0xffffffffL; r&=0xffffffffL; PERM_OP(r,l,t, 1,0x55555555L); PERM_OP(l,r,t, 8,0x00ff00ffL); PERM_OP(r,l,t, 2,0x33333333L); PERM_OP(l,r,t,16,0x0000ffffL); PERM_OP(r,l,t, 4,0x0f0f0f0fL); *out0=l; *out1=r; return(0); } /**************************************************************************/ const char *nh= "\xB8\x00\x4D\xBA\x91\x6E\x1F\x39\xC1\xAA\xCD\x76\x30\xD2\x96\x50\xA8\x16\x7A\x82" "\xAC\x5D\xDE\x04\xA6\xF0\x37\xEE\x84\xA8\x22\xB1\xAF\x15\x54\x23\x97\x49\x61\xAF" "\xEC\x60\xCC\xCC\x47\xDF\xBA\x9C\xBF\x5F\x15\xCE\xCB\x61\xA0\x2A\xF1\x7B\x81\xA7" "\x71\x2D\x0F\xD0\x8C\x1A\x57\x8A\xAC\x69\xDF\xAB\x57\xFC\x36\xCB\x91\x83\x46\xA1" "\xB6\x07\x08\x49\x98\x4A\x16\x3C\x75\xF4\xE8\xBE\x01\xE9\xED\x79\x47\x37\xF6\x04" "\xFE\x7D\x70\x5C\xB5\x6B\x4C\x0A\xD1\x4C\xDB\x97\x33\x34\x00\x6F\x43\x6B\x3D\x33" "\x91\xC7\x5B\xDD\x01\xEF\x60\x94\xE9\x14\x54\xCE\x75\x6C\xDB\x7C\x96\x5B\xAE\x18" "\x6A\x8B\xFB\x50\x14\xAE\x81\x24\x01\xED\x8A\xF5\xD9\xB3\xFC\x29\xC3\x24\xD8\x99" "\x25\xF4\x8A\x6F\xA0\xAC\xBF\x13\x3C\x5A\x3B\xC6\x93\x18\x6A\x57\x73\x51\xA9\x81" "\x88\xD0\x43\xD2\x64\xEE\xE0\x7D\x61\x1C\x68\x2A\x6F\x70\xF1\xE5\x88\x13\xEC\xD0" "\xB0\xEC\xF6\x86\x43\xD2\x69\x84\x65\xC6\x3B\xDF\xCD\x90\x08\xDE\xC6\xF6\x77\x4C" "\x8B\x3A\xAC\x32\x93\xA0\x6F\x3C\x5F\x0A\x0E\x58\xC2\x35\x8F\xEA\xE9\x5F\x85\x77" "\xA1\xD6\xC6\x70\xCF\x6F\xD5\x00\x79\xAE\x67\x5B\x3C\xDD\x78\x64\xED\x76\x82\x61" "\x8D\x8C\x96\x75\x07\x13\x9F\x87\x36\xB9\x91\xB3\xB6\x65\x56\xDE\x7F\x25\x7B\x77"; #define nKEYSIZE (280) /**************************************************************************/ const char *eh= "\x01\x00\x01"; #define eKEYSIZE (3) /**************************************************************************/ // Only one for the following should be defined #undef SIXTY_FOUR_BIT #define THIRTY_TWO_BIT #undef SIXTEEN_BIT #if !defined(SIXTY_FOUR_BIT) && !defined(THIRTY_TWO_BIT) && !defined(SIXTEEN_BIT) #if sizeof(unsigned long) == 8 #undef SIXTY_FOUR_BIT #endif #if sizeof(unsigned long) == 4 #define THIRTY_TWO_BIT #endif #if sizeof(unsigned int) == 2 #define THIRTY_TWO_BIT #undef SIXTEEN_BIT #endif #endif // assuming long is 64bit - this is the DEC Alpha #ifdef SIXTY_FOUR_BIT #define BN_ULLONG unsigned long long #define BN_ULONG unsigned long #define BN_LONG long #define BN_BITS 128 #define BN_BYTES 8 #define BN_BITS2 64 #define BN_BITS4 32 #define BN_MASK2 (0xffffffffffffffffL) #define BN_MASK2l (0xffffffffL) #define BN_MASK2h (0xffffffff00000000L) #define BN_MASK2h1 (0xffffffff80000000L) #define BN_CBIT (0x10000000000000000LL) #define BN_TBIT (0x8000000000000000) #define BN_NOT_MASK2 ((unsigned long long)0xffffffffffffffff0000000000000000LL) #endif #ifdef THIRTY_TWO_BIT #define BN_ULLONG unsigned long long #define BN_ULONG unsigned long #define BN_LONG long #define BN_BITS 64 #define BN_BYTES 4 #define BN_BITS2 32 #define BN_BITS4 16 #define BN_MASK2 (0xffffffffL) #define BN_MASK2l (0xffff) #define BN_MASK2h1 (0xffff8000L) #define BN_MASK2h (0xffff0000L) #define BN_CBIT ((unsigned long long)0x100000000LL) #define BN_TBIT (0x80000000L) #define BN_NOT_MASK2 ((unsigned long long)0xffffffff00000000LL) #endif #ifdef SIXTEEN_BIT #define BN_ULLONG unsigned long #define BN_ULONG unsigned short #define BN_LONG short #define BN_BITS 32 #define BN_BYTES 2 #define BN_BITS2 16 #define BN_BITS4 8 #define BN_MASK2 (0xffff) #define BN_MASK2l (0xff) #define BN_MASK2h1 (0xff80) #define BN_MASK2h (0xff00) #define BN_CBIT ((unsigned long)0x10000L) #define BN_TBIT (0x8000) #define BN_NOT_MASK2 ((unsigned long)0xffff0000L) #endif #define BN_DEFAULT_BITS 1200 #ifdef BIGNUM #undef BIGNUM #endif typedef struct bignum_st { BN_ULONG *d; // Pointer to an array of 'BN_BITS2' bit chunks. int top; // Index of last used d +1. // The next are internal book keeping for bn_expand. int max; // Size of the d array. int neg; } BIGNUM; #define BN_CTX_NUM 12 typedef struct bignum_ctx { int tos; BIGNUM *bn[BN_CTX_NUM]; } BN_CTX; #define BN_prime_checks (5) #define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) #define BN_is_zero(a) (((a)->top <= 1) && ((a)->d[0] == 0)) #define BN_is_one(a) (((a)->top == 1) && ((a)->d[0] == 1)) #define BN_is_word(a,w) (((a)->top == 1) && ((a)->d[0] == (w))) #define BN_one(a) (BN_set_word((a),1)) #define BN_zero(a) (BN_set_word((a),0)) #define bn_fix_top(a) \ { \ BN_ULONG *l; \ for (l= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \ if (*(l--)) break; \ } #define bn_expand(n,b) ((((b)/BN_BITS2) <= (n)->max)?(n):bn_expand2((n),(b))) #define LBITS(a) ((a)&BN_MASK2l) #define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2l) #define L2HBITS(a) (((a)&BN_MASK2l)<<BN_BITS4) #define sqr64(lo,ho,in) \ { \ BN_ULONG l,h,m; \ \ h=(in); \ l=LBITS(h); \ h=HBITS(h); \ m =(l)*(h); \ l*=l; \ h*=h; \ h+=(m&BN_MASK2h1)>>(BN_BITS4-1); \ m =(m&BN_MASK2l)<<(BN_BITS4+1); \ l+=m; if ((l&BN_MASK2) < m) h++; \ (lo)=l; \ (ho)=h; \ } #define mul_add(r,a,bl,bh,c) { \ BN_ULONG l,h; \ \ h= (a); \ l=LBITS(h); \ h=HBITS(h); \ mul64(l,h,(bl),(bh)); \ \ /* non-multiply part */ \ l+=(c); if ((l&BN_MASK2) < (c)) h++; \ (c)=(r); \ l+=(c); if ((l&BN_MASK2) < (c)) h++; \ (c)=h&BN_MASK2; \ (r)=l&BN_MASK2; \ } /*************************************************************/ // No long long type #define mul64(l,h,bl,bh) \ { \ BN_ULONG m,m1,lt,ht; \ \ lt=l; \ ht=h; \ m =(bh)*(lt); \ lt=(bl)*(lt); \ m1=(bl)*(ht); \ ht =(bh)*(ht); \ m+=m1; if ((m&BN_MASK2) < m1) ht+=L2HBITS(1L); \ ht+=HBITS(m); \ m1=L2HBITS(m); \ lt+=m1; if ((lt&BN_MASK2) < m1) ht++; \ (l)=lt; \ (h)=ht; \ } #define mul(r,a,bl,bh,c) { \ BN_ULONG l,h; \ \ h= (a); \ l=LBITS(h); \ h=HBITS(h); \ mul64(l,h,(bl),(bh)); \ \ /* non-multiply part */ \ l+=(c); if ((l&BN_MASK2) < (c)) h++; \ (c)=h&BN_MASK2; \ r=l&BN_MASK2; \ if (--num == 0) break; \ } #define bn_mul_words(r1,r2,a,b) \ { \ BN_ULONG l,h,bl,bh; \ \ h=(a); \ l=LBITS(h); \ h=HBITS(h); \ bh=(b); \ bl=LBITS(bh); \ bh=HBITS(bh); \ \ mul64(l,h,bl,bh); \ \ (r1)=l; \ (r2)=h; \ } static int BN_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b); static BN_ULONG bn_mul_add_word(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w); static int BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m, BN_CTX *ctx); #define Getenv getenv #define Fprintf fprintf #define Fputc fputc #define Fgets fgets #define Fwrite fwrite #define Fread fread #ifdef sgi #define IRIX_CC_BUG // all version of IRIX I've tested (4.* 5.*) #endif static BN_ULONG data_one=1L; static BIGNUM const_one={&data_one,1,1,0}; BIGNUM *BN_value_one=&const_one; int number_range( int from, int to ); /**************************************************************************/ static void RAND_bytes(unsigned char *buf,int num) { int i; { static unsigned char val; for (i=0; i<num; i++){ val=number_range(1,250); buf[i]=val++; } return; } } /**************************************************************************/ static int BN_num_bits(BIGNUM *a) { int i; BN_ULONG l; static char bits[256]={ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, }; if(!a->top){ return 0; } l=a->d[a->top-1]; i=(a->top-1)*BN_BITS2; if(l == 0){ return 0; // bugf("BAD TOP VALUE\n"); // abort(); } #ifdef SIXTY_FOUR_BIT if(l & 0xffffffff00000000){ if(l & 0xffff000000000000){ if(l & 0xff00000000000000){ return(i+bits[l>>56]+56); }else{ return(i+bits[l>>48]+48); } }else{ if(l & 0x0000ff0000000000){ return(i+bits[l>>40]+40); }else{ return(i+bits[l>>32]+32); } } }else #endif { #if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) if(l & 0xffff0000L){ if(l & 0xff000000L){ return (i+bits[l>>24L]+24); }else{ return (i+bits[l>>16L]+16); } }else #endif { if(l & 0xff00L){ return (i+bits[l>>8]+8); }else{ return (i+bits[l]); } } } } /**************************************************************************/ // ignores negative static int BN_bn2bin(BIGNUM *a, unsigned char *to) { int n,i; BN_ULONG l; n=i=BN_num_bytes(a); while (i-- > 0){ l=a->d[i/BN_BYTES]; *(to++)=(unsigned char)(l>>(8*(i%BN_BYTES)))&0xff; } return(n); } /**************************************************************************/ static void BN_free(BIGNUM *a) { if(!a){ return; } if(a->d){ free(a->d); } free(a); } /**************************************************************************/ static BIGNUM *BN_new() { BIGNUM *ret; BN_ULONG *p; ret=(BIGNUM *)malloc(sizeof(BIGNUM)); if(ret == NULL){ return NULL; } ret->top=0; ret->neg=0; ret->max=(BN_DEFAULT_BITS/BN_BITS2); p=(BN_ULONG *)malloc(sizeof(BN_ULONG)*(ret->max+1)); if(p == NULL){ return NULL; } ret->d=p; memset(p,0,(ret->max+1)*sizeof(p[0])); return(ret); } /**************************************************************************/ static void BN_clear(BIGNUM *a) { memset(a->d,0,a->max*sizeof(a->d[0])); a->top=0; a->neg=0; } /**************************************************************************/ static void BN_clear_free(BIGNUM *a) { if(!a){ return; } if(a->d){ memset(a->d,0,a->max*sizeof(a->d[0])); free(a->d); } memset(a,0,sizeof(BIGNUM)); free(a); } /**************************************************************************/ static void BN_CTX_free(BN_CTX *c) { int i; for (i=0; i<BN_CTX_NUM; i++){ BN_clear_free(c->bn[i]); } free(c); } /**************************************************************************/ static BN_CTX *BN_CTX_new() { BN_CTX *ret; BIGNUM *n; int i, j; ret=(BN_CTX *)malloc(sizeof(BN_CTX)); if(!ret){ return NULL; } for (i=0; i<BN_CTX_NUM; i++){ n=BN_new(); if(!n){ for (j=0; j<i; j++) BN_free(ret->bn[j]); free(ret); return NULL; } ret->bn[i]=n; } ret->tos=0; return ret; } /**************************************************************************/ static BIGNUM *bn_expand2(BIGNUM *b, int bits) { BN_ULONG *p; register int n; while (bits > b->max*BN_BITS2){ n=((bits+BN_BITS2-1)/BN_BITS2)*2; p=b->d=(BN_ULONG *)realloc(b->d,sizeof(BN_ULONG)*(n+1)); if(!p){ return NULL; } memset(&(p[b->max]),0,((n+1)-b->max)*sizeof(BN_ULONG)); b->max=n; } return b; } /**************************************************************************/ // ignores negative static BIGNUM *BN_bin2bn(unsigned char *s, int len, BIGNUM *ret) { unsigned int i,m; unsigned int n; BN_ULONG l; if(!ret){ ret=BN_new(); } if(!ret){ return NULL; } l=0; n=len; if(n==0){ ret->top=0; return ret; } if(bn_expand(ret,(int)(n+2)*8) == NULL){ return NULL; } i=((n-1)/BN_BYTES)+1; m=((n-1)%(BN_BYTES)); ret->top=i; while (n-- > 0){ l=(l<<8)| *(s++); if(m-- == 0){ ret->d[--i]=l; l=0; m=BN_BYTES-1; } } // need to call this due to clear byte at top if avoiding // having the top bit set (-ve number) bn_fix_top(ret); // macro return(ret); } /**************************************************************************/ static int BN_set_word(BIGNUM *a,unsigned long w) { if(bn_expand(a,(int)sizeof(unsigned long)*8) == NULL){ return 0; } a->d[0]=w; a->top=(w == 0)?0:1; a->neg=0; return 1; } /**************************************************************************/ static BIGNUM *BN_copy(BIGNUM *a, BIGNUM *b) { if(bn_expand(a,b->top*BN_BITS2) == NULL){ return NULL; } memcpy(a->d,b->d,sizeof(b->d[0])*b->top); memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top)); a->top=b->top; a->neg=b->neg; return(a); } /**************************************************************************/ static int BN_is_bit_set(BIGNUM *a, int n) { int i,j; i=n/BN_BITS2; j=n%BN_BITS2; if(a->top <= i){ return 0; } return ((a->d[i]&(1L<<j))?1:0); } /**************************************************************************/ static int BN_rshift(BIGNUM *r, BIGNUM *a, int n) { int i,nw,lb,rb; BN_ULONG *t,*f; BN_ULONG l; r->neg=a->neg; nw=n/BN_BITS2; rb=n%BN_BITS2; lb=BN_BITS2-rb; if(nw > a->top){ BN_zero(r); return 1; } if(bn_expand(r,(a->top-nw+1)*BN_BITS2) == NULL){ return 0; } f=a->d; t=r->d; if(rb == 0){ for (i=nw; i<a->top; i++){ t[i-nw]=f[i]; } }else{ l=f[nw]; for (i=nw; i<a->top; i++){ t[i-nw] =(l>>rb)&BN_MASK2; l=f[i+1]; t[i-nw]|=(l<<lb)&BN_MASK2; } } r->top=a->top-nw; t[r->top]=0; bn_fix_top(r); return 1; } /**************************************************************************/ static int BN_lshift(BIGNUM *r, BIGNUM *a, int n) { int i,nw,lb,rb; BN_ULONG *t,*f; BN_ULONG l; r->neg=a->neg; if(bn_expand(r,(a->top*BN_BITS2)+n) == NULL) return(0); nw=n/BN_BITS2; lb=n%BN_BITS2; rb=BN_BITS2-lb; f=a->d; t=r->d; t[a->top+nw]=0; if(lb == 0) for (i=a->top-1; i>=0; i--) t[nw+i]=f[i]; else for (i=a->top-1; i>=0; i--) { l=f[i]; t[nw+i+1]|=(l>>rb)&BN_MASK2; t[nw+i]=(l<<lb)&BN_MASK2; } memset(t,0,nw*sizeof(t[0])); r->top=a->top+nw+1; bn_fix_top(r); return(1); } /**************************************************************************/ static int BN_ucmp(BIGNUM *a, BIGNUM *b) { int i; BN_ULONG t1,t2,*ap,*bp; i=a->top-b->top; if(i != 0) return(i); ap=a->d; bp=b->d; for(i=a->top-1; i>=0; i--){ t1=ap[i]; t2=bp[i]; if(t1 > t2) return(1); if(t1 < t2) return(-1); } return 0; } /**************************************************************************/ static int BN_cmp(BIGNUM *a, BIGNUM *b) { int i; int gt,lt; BN_ULONG t1,t2; if(a->neg != b->neg){ if(a->neg){ return(-1); }else{ return(1);} } if(a->neg == 0){ gt=1; lt=-1; }else{ gt=-1; lt=1; } if(a->top > b->top) return(gt); if(a->top < b->top) return(lt); for (i=a->top-1; i>=0; i--){ t1=a->d[i]; t2=b->d[i]; if(t1 > t2) return(gt); if(t1 < t2) return(lt); } return(0); } /**************************************************************************/ static void bn_SUB(BIGNUM *r, BIGNUM *a, BIGNUM *b) { int max,min; register BN_ULONG t1,t2,*ap,*bp,*rp; int i,carry; #if defined(IRIX_CC_BUG) && !defined(LINT) int dummy; #endif max=a->top; min=b->top; ap=a->d; bp=b->d; rp=r->d; carry=0; for (i=0; i<min; i++){ t1= *(ap++); t2= *(bp++); if(carry){ carry=(t1 <= t2); t1=(t1-t2-1); }else{ carry=(t1 < t2); t1=(t1-t2); } #if defined(IRIX_CC_BUG) && !defined(LINT) dummy=t1; #endif *(rp++)=t1&BN_MASK2; } if(carry){ // subtracted while (i < max){ i++; t1= *(ap++); t2=(t1-1)&BN_MASK2; *(rp++)=t2; if(t1 > t2) break; } } memcpy(rp,ap,sizeof(*rp)*(max-i)); r->top=max; bn_fix_top(r); } /**************************************************************************/ static int BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b) { register int i; int max,min; BN_ULONG *ap,*bp,*rp,carry,t1,t2; BIGNUM *tmp; // a + b a+b // a + -b a-b // -a + b b-a // -a + -b -(a+b) if(a->neg ^ b->neg){ if(a->neg){ a->neg=0; i=BN_sub(r,b,a); if(a != r) a->neg=1; }else{ b->neg=0; i=BN_sub(r,a,b); if(b != r) b->neg=1; } return(i); } if(a->neg){ // both are neg a->neg=0; b->neg=0; i=BN_add(r,a,b); if(a != r) a->neg=1; if(b != r) b->neg=1; return(i); } if(a->top < b->top){ tmp=a; a=b; b=tmp; } max=a->top; min=b->top; if(bn_expand(r,(max+1)*BN_BITS2) == NULL) return(0); r->top=max; r->neg=0; ap=a->d; bp=b->d; rp=r->d; carry=0; for(i=0; i<min; i++){ t1= *(ap++); t2= *(bp++); if(carry){ carry=(t2 >= ((~t1)&BN_MASK2)); t2=(t1+t2+1)&BN_MASK2; }else{ t2=(t1+t2)&BN_MASK2; carry=(t2 < t1); } *(rp++)=t2; } if(carry){ while (i < max){ t1= *(ap++); t2=(t1+1)&BN_MASK2; *(rp++)=t2; carry=(t2 < t1); i++; if(!carry) break; } if((i >= max) && carry){ *(rp++)=1; r->top++; } } for (; i<max; i++){ *(rp++)= *(ap++); } memcpy(rp,ap,sizeof(*ap)*(max-i)); return(1); } /**************************************************************************/ static int BN_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b) { int max,i; /* a - b a-b * a - -b a+b * -a - b -(a+b) * -a - -b b-a */ if(a->neg){ if(b->neg){ a->neg=b->neg=0; i=BN_sub(r,b,a); if(a != r) a->neg=1; if(b != r) b->neg=1; }else{ a->neg=0; i=BN_add(r,a,b); r->neg=a->neg=1; } return(i); }else{ if(b->neg){ b->neg=0; i=BN_add(r,a,b); if(r != b) b->neg=1; return(i); } } max=(a->top > b->top)?a->top:b->top; if(BN_cmp(a,b) < 0){ if(bn_expand(r,max*BN_BITS2) == NULL) return(0); bn_SUB(r,b,a); r->neg=1; }else{ if(bn_expand(r,max*BN_BITS2) == NULL) return(0); bn_SUB(r,a,b); r->neg=0; } return(1); } /**************************************************************************/ static int BN_rshift1(BIGNUM *r, BIGNUM *a) { BN_ULONG *ap,*rp,t,c; int i; if(BN_is_zero(a)){ BN_zero(r); return(1); } if(a!=r){ if(bn_expand(r,a->top*BN_BITS2) == NULL){ return 0; } r->top=a->top; r->neg=a->neg; } ap=a->d; rp=r->d; c=0; for (i=a->top-1; i>=0; i--){ t=ap[i]; rp[i]=((t>>1)&BN_MASK2)|c; c=(t&1)?BN_TBIT:0; } bn_fix_top(r); return 1; } /**************************************************************************/ static int BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx) { int i,nm,nd; BIGNUM *dv; if(BN_ucmp(m,d) < 0){ return((BN_copy(rem,m) == NULL)?0:1); } dv=ctx->bn[ctx->tos]; if(!BN_copy(rem,m)) { return 0; } nm=BN_num_bits(rem); nd=BN_num_bits(d); if(!BN_lshift(dv,d,nm-nd)){ return 0; } for(i=nm-nd; i>=0; i--) { if(BN_cmp(rem,dv) >= 0){ if(!BN_sub(rem,rem,dv)){ return 0; } } if(!BN_rshift1(dv,dv)){ return 0; } } return 1; } /**************************************************************************/ static int BN_lshift1(BIGNUM *r, BIGNUM *a) { register BN_ULONG *ap,*rp,t,c; int i; if (r != a){ r->neg=a->neg; if (bn_expand(r,(a->top+1)*BN_BITS2) == NULL) return(0); r->top=a->top; }else{ if (bn_expand(r,(a->top+1)*BN_BITS2) == NULL) return(0); } ap=a->d; rp=r->d; c=0; for (i=0; i<a->top; i++){ t= *(ap++); *(rp++)=((t<<1)|c)&BN_MASK2; c=(t & BN_TBIT)?1:0; } if(c){ *rp=1; r->top++; } return(1); } /**************************************************************************/ static int BN_div(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx) { int i,nm,nd; BIGNUM *D; if(BN_cmp(m,d) < 0){ if(rem != NULL){ if(BN_copy(rem,m) == NULL){ return(0); } } if(dv != NULL){ BN_zero(dv); } return(1); } D=ctx->bn[ctx->tos]; if(dv == NULL) dv=ctx->bn[ctx->tos+1]; if(rem == NULL) rem=ctx->bn[ctx->tos+2]; nd=BN_num_bits(d); nm=BN_num_bits(m); if(BN_copy(D,d) == NULL) return(0); if(BN_copy(rem,m) == NULL) return(0); // The next 2 are needed so we can do a dv->d[0]|=1 later // since BN_lshift1 will only work once there is a value :-) BN_zero(dv); dv->top=1; if(!BN_lshift(D,D,nm-nd)){ return(0); } for (i=nm-nd; i>=0; i--){ if(!BN_lshift1(dv,dv)) return(0); if(BN_cmp(rem,D) >= 0){ dv->d[0]|=1; if(!BN_sub(rem,rem,D)){ return(0); } } if(!BN_rshift1(D,D)) return(0); } dv->neg=m->neg^d->neg; return(1); } /**************************************************************************/ static int BN_reciprocal(BIGNUM *r, BIGNUM *m, BN_CTX *ctx) { int nm,ret=-1; BIGNUM *t; t=ctx->bn[ctx->tos++]; nm=BN_num_bits(m); if(!BN_lshift(t,BN_value_one,nm*2)) goto err; if(!BN_div(r,NULL,t,m,ctx)) goto err; ret=(nm+1); err: ctx->tos--; return(ret); } /**************************************************************************/ static void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n) { for (;;){ sqr64(r[0],r[1],a[0]); if (--n == 0) break; sqr64(r[2],r[3],a[1]); if (--n == 0) break; sqr64(r[4],r[5],a[2]); if (--n == 0) break; sqr64(r[6],r[7],a[3]); if (--n == 0) break; a+=4; r+=8; } } /**************************************************************************/ // r must not be a static int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx) { int i,j,max,al; BIGNUM *tmp; BN_ULONG *ap,*rp; tmp=ctx->bn[ctx->tos]; al=a->top; if (al == 0){ r->top=0; return(1); } max=(al*2+1); BN_clear(r); BN_clear(tmp); if (bn_expand(r,(max+1)*BN_BITS2) == NULL) return(0); if (bn_expand(tmp,(max+1)*BN_BITS2) == NULL) return(0); r->top=max; r->neg=a->neg; ap=a->d; rp=r->d; rp++; j=al; for (i=1; i<al; i++){ BN_ULONG r; j--; r= *(ap++); rp[j]+=bn_mul_add_word(rp,ap,j,r); rp+=2; } bn_fix_top(r); if (!BN_lshift1(r,r)) return(0); bn_sqr_words(tmp->d,a->d,a->top); tmp->top=al*2+1; bn_fix_top(tmp); if (!BN_add(r,r,tmp)) return(0); return(1); } /**************************************************************************/ // r must be different to a and b static int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b) { int i; int max,al,bl; BN_ULONG *ap,*bp,*rp; al=a->top; bl=b->top; if ((al == 0) || (bl == 0)){ r->top=0; return(1); } max=(al+bl+1); BN_clear(r); if (bn_expand(r,(max+1)*BN_BITS2) == NULL) return(0); r->top=max; r->neg=a->neg^b->neg; ap=a->d; bp=b->d; rp=r->d; for (i=0; i<bl; i++){ rp[al]=bn_mul_add_word(rp,ap,al,*(bp++)); rp++; } bn_fix_top(r); return(1); } /**************************************************************************/ static BN_ULONG bn_mul_add_word(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) { BN_ULONG c=0; BN_ULONG bl,bh; bl=LBITS(w); bh=HBITS(w); for (;;){ mul_add(rp[0],ap[0],bl,bh,c); if (--num == 0) break; mul_add(rp[1],ap[1],bl,bh,c); if (--num == 0) break; mul_add(rp[2],ap[2],bl,bh,c); if (--num == 0) break; mul_add(rp[3],ap[3],bl,bh,c); if (--num == 0) break; ap+=4; rp+=4; } return(c); } /**************************************************************************/ static int mg_crypt_text(int flen, unsigned char *from, unsigned char *to, BIGNUM *e, BIGNUM *n) { BIGNUM *f=NULL,*ret=NULL; int i,j,k,num=0,r=-1; unsigned char *p; unsigned char *buf=NULL; BN_CTX *ctx; ctx=BN_CTX_new(); if(!ctx){ goto err; } num=BN_num_bytes(n); // macro if(flen > (num-11)){ goto err; } buf=(unsigned char *)malloc(num); if(!buf){ goto err; } p=(unsigned char *)buf; *(p++)=0; *(p++)=2; // pad out with non-zero random data j=num-3-flen; RAND_bytes(p,j); for(i=0; i<j; i++){ if (*p == '\0'){ do{ RAND_bytes(p,1); } while (*p == '\0'); } p++; } *(p++)='\0'; memcpy(p,from,(unsigned int)flen); f=BN_new(); ret=BN_new(); if( !f || !ret ){ goto err; } if(BN_bin2bn(buf,num,f) == NULL) goto err; if(!BN_mod_exp(ret,f,e,n,ctx)) goto err; // put in leading 0 bytes if the number is less than the // length of the modulus j=BN_num_bytes(ret); i=BN_bn2bin(ret,&(to[num-j])); for (k=0; k<(num-i); k++) to[k]=0; r=num; err: if (ctx != NULL) BN_CTX_free(ctx); if (f != NULL) BN_free(f); if (ret != NULL) BN_free(ret); if (buf != NULL) { memset(buf,0,num); free(buf); } return(r); } /**************************************************************************/ int mg_crypt_msg(char *input, char *encoded) { int len; BIGNUM *e=BN_bin2bn((unsigned char *)eh, eKEYSIZE, NULL); BIGNUM *n=BN_bin2bn((unsigned char *)nh, nKEYSIZE, NULL); len=mg_crypt_text(str_len(input), (unsigned char *)input, (unsigned char *)encoded, e, n); BN_free(e); BN_free(n); return len; } /**************************************************************************/ static int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, BIGNUM *m, BIGNUM *i, int nb, BN_CTX *ctx) { int ret=0,j; BIGNUM *a,*b,*c,*d; a=ctx->bn[ctx->tos++]; b=ctx->bn[ctx->tos++]; c=ctx->bn[ctx->tos++]; d=ctx->bn[ctx->tos++]; if(x==y){ if(!BN_sqr(a,x,ctx)){ goto err; } }else{ if(!BN_mul(a,x,y)){ goto err; } } if(!BN_rshift(d,a,nb-1)) goto err; if(!BN_mul(b,d,i)) goto err; if(!BN_rshift(c,b,nb-1)) goto err; if(!BN_mul(b,m,c)) goto err; if(!BN_sub(r,a,b)) goto err; j=0; while (BN_cmp(r,m) >= 0){ if(j++ > 2){ goto err; } if(!BN_sub(r,r,m)){ goto err; } } ret=1; err: ctx->tos-=4; return(ret); } /**************************************************************************/ static int BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m, BN_CTX *ctx) { int nb,i,j=0,bits,ret=0; BIGNUM *v,*tmp,*d,*pc[8]; BN_CTX *c2=NULL; v=ctx->bn[ctx->tos]; tmp=ctx->bn[ctx->tos+1]; d=ctx->bn[ctx->tos+2]; ctx->tos+=3; if(!BN_mod(v,a,m,ctx)){ goto err; } bits=BN_num_bits(p); if(!BN_one(r)){ goto err; } nb=BN_reciprocal(d,m,ctx); if(nb == -1){ goto err; } if((c2=BN_CTX_new()) == NULL){ goto err; } for (i=0; i<8; i++){ pc[i]=c2->bn[i]; } c2->tos+=7; if(!BN_copy(pc[1],v)) goto err; if(!BN_mod_mul_reciprocal(pc[2],pc[1],pc[1],m,d,nb,ctx)) goto err; if(!BN_mod_mul_reciprocal(pc[3],pc[2],pc[1],m,d,nb,ctx)) goto err; if(!BN_mod_mul_reciprocal(pc[4],pc[2],pc[2],m,d,nb,ctx)) goto err; if(!BN_mod_mul_reciprocal(pc[5],pc[4],pc[1],m,d,nb,ctx)) goto err; if(!BN_mod_mul_reciprocal(pc[6],pc[3],pc[3],m,d,nb,ctx)) goto err; if(!BN_mod_mul_reciprocal(pc[7],pc[6],pc[1],m,d,nb,ctx)) goto err; bits=((bits-1)/3)*3; // for 4 bits, start at 2 for (i=bits; i>=0; i-=3){ if(!BN_mod_mul_reciprocal(r,r,r,m,d,nb,ctx)) goto err; if(!BN_mod_mul_reciprocal(r,r,r,m,d,nb,ctx)) goto err; if(!BN_mod_mul_reciprocal(r,r,r,m,d,nb,ctx)) goto err; j= BN_is_bit_set(p,i)+ (BN_is_bit_set(p,i+1)<<1)+ (BN_is_bit_set(p,i+2)<<2); if(j && !BN_mod_mul_reciprocal(r,r,pc[j],m,d,nb,ctx)){ goto err; } #ifdef BN_FIXED_TIME else{ if(!BN_mod_mul_reciprocal(pc[0],r,pc[5],m,d,nb,ctx)){ goto err; } } #endif } ret=1; err: if(c2){ BN_CTX_free(c2); } ctx->tos-=3; return(ret); } /**************************************************************************/