1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-12-28 15:53:20 +02:00

add the 'ead' package (emergency access daemon),

which can provide remote access to your device, even if the ip
and firewall settings are broken

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13738 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
nbd 2008-12-24 10:42:12 +00:00
parent 2b020ab721
commit 85f89d5d09
69 changed files with 17597 additions and 0 deletions

53
package/ead/Makefile Normal file
View File

@ -0,0 +1,53 @@
#
# Copyright (C) 2006-2008 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# $Id$
include $(TOPDIR)/rules.mk
PKG_NAME:=ead
PKG_RELEASE:=1
PKG_BUILD_DEPENDS:=pcap
include $(INCLUDE_DIR)/package.mk
define Package/ead
SECTION:=net
CATEGORY:=Base system
TITLE:=Emergency Access Daemon
URL:=http://bridge.sourceforge.net/
endef
define Package/ead/description
Provides remote access to your device even if IP and firewall
configuration settings are defunct
endef
CONFIGURE_PATH = tinysrp
TARGET_CFLAGS += \
-I$(PKG_BUILD_DIR) \
-I$(PKG_BUILD_DIR)/tinysrp \
-I$(STAGING_DIR)/usr/include
MAKE_FLAGS += \
CONFIGURE_ARGS="$(CONFIGURE_ARGS)" \
LIBS="$(PKG_BUILD_DIR)/tinysrp/libtinysrp.a" \
LIBS_EAD="$(PKG_BUILD_DIR)/tinysrp/libtinysrp.a $(STAGING_DIR)/usr/lib/libpcap.a" \
CFLAGS="$(TARGET_CFLAGS)"
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Package/ead/install
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ead $(1)/sbin/
endef
$(eval $(call BuildPackage,ead))

33
package/ead/src/Makefile Normal file
View File

@ -0,0 +1,33 @@
CC = gcc
CPPFLAGS = -I. -Itinysrp
CFLAGS = -Os -Wall
LDFLAGS =
LIBS = tinysrp/libtinysrp.a
LIBS_EAD = $(LIBS) -lpcap
CONFIGURE_ARGS =
all: ead ead-client
obj = ead-crypt.o
tinysrp/Makefile:
cd tinysrp; ./configure $(CONFIGURE_ARGS)
tinysrp/libtinysrp.a: tinysrp/Makefile
-$(MAKE) -C tinysrp CFLAGS="$(CFLAGS)"
%.o: %.c $(wildcard *.h) tinysrp/libtinysrp.a
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
ead.o: filter.c
ead-crypt.o: aes.c sha1.c
ead: ead.o $(obj) tinysrp/libtinysrp.a
$(CC) -o $@ $< $(obj) $(LDFLAGS) $(LIBS_EAD)
ead-client: ead-client.o $(obj)
$(CC) -o $@ $< $(obj) $(LDFLAGS) $(LIBS)
clean:
rm -f *.o ead ead-client
if [ -f tinysrp/Makefile ]; then $(MAKE) -C tinysrp distclean; fi

1061
package/ead/src/aes.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,405 @@
/*
* Client for the Emergency Access Daemon
* Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* 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.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <t_pwd.h>
#include <t_read.h>
#include <t_sha.h>
#include <t_defines.h>
#include <t_client.h>
#include "ead.h"
#include "ead-crypt.h"
#include "pw_encrypt_md5.c"
#define EAD_TIMEOUT 400
#define EAD_TIMEOUT_LONG 2000
static char msgbuf[1500];
static struct ead_msg *msg = (struct ead_msg *) msgbuf;
static uint16_t nid = 0xffff;
struct sockaddr_in local, remote;
static int s = 0;
static int sockflags;
static unsigned char *skey = NULL;
static unsigned char bbuf[MAXPARAMLEN];
static unsigned char saltbuf[MAXSALTLEN];
static char *username = NULL;
static char password[MAXPARAMLEN] = "";
static char pw_md5[MD5_OUT_BUFSIZE];
static char pw_salt[MAXSALTLEN];
static struct t_client *tc = NULL;
static struct t_num salt = { .data = saltbuf };
static struct t_num *A, B;
static struct t_preconf *tcp;
static int auth_type = EAD_AUTH_DEFAULT;
static int timeout = EAD_TIMEOUT;
static void
set_nonblock(int enable)
{
if (enable == !!(sockflags & O_NONBLOCK));
return;
sockflags ^= O_NONBLOCK;
fcntl(s, F_SETFL, sockflags);
}
static int
send_packet(int type, bool (*handler)(void), unsigned int max)
{
struct timeval tv;
fd_set fds;
int nfds;
int len;
int res = 0;
type = htonl(type);
set_nonblock(0);
sendto(s, msgbuf, sizeof(struct ead_msg) + ntohl(msg->len), 0, (struct sockaddr *) &remote, sizeof(remote));
set_nonblock(1);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds);
do {
FD_SET(s, &fds);
nfds = select(s + 1, &fds, NULL, NULL, &tv);
if (nfds <= 0)
break;
if (!FD_ISSET(s, &fds))
break;
len = read(s, msgbuf, sizeof(msgbuf));
if (len < 0)
break;
if (len < sizeof(struct ead_msg))
continue;
if (len < sizeof(struct ead_msg) + ntohl(msg->len))
continue;
if (msg->magic != htonl(EAD_MAGIC))
continue;
if ((nid != 0xffff) && (ntohs(msg->nid) != nid))
continue;
if (msg->type != type)
continue;
if (handler())
res++;
if ((max > 0) && (res >= max))
break;
} while (1);
return res;
}
static void
prepare_password(void)
{
switch(auth_type) {
case EAD_AUTH_DEFAULT:
break;
case EAD_AUTH_MD5:
md5_crypt(pw_md5, (unsigned char *) password, (unsigned char *) pw_salt);
strncpy(password, pw_md5, sizeof(password));
break;
}
}
static bool
handle_pong(void)
{
struct ead_msg_pong *pong = EAD_DATA(msg, pong);
int len = msg->len - sizeof(struct ead_msg_pong);
pong->name[len] = 0;
auth_type = ntohs(pong->auth_type);
if (nid == 0xffff)
printf("%04x: %s\n", ntohs(msg->nid), pong->name);
return true;
}
static bool
handle_prime(void)
{
struct ead_msg_salt *sb = EAD_DATA(msg, salt);
salt.len = sb->len;
memcpy(salt.data, sb->salt, salt.len);
if (auth_type == EAD_AUTH_MD5) {
memcpy(pw_salt, sb->ext_salt, MAXSALTLEN);
pw_salt[MAXSALTLEN - 1] = 0;
}
tcp = t_getpreparam(sb->prime);
tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &salt);
if (!tc) {
fprintf(stderr, "Client open failed\n");
return false;
}
return true;
}
static bool
handle_b(void)
{
struct ead_msg_number *num = EAD_DATA(msg, number);
int len = ntohl(msg->len) - sizeof(struct ead_msg_number);
B.data = bbuf;
B.len = len;
memcpy(bbuf, num->data, len);
return true;
}
static bool
handle_none(void)
{
return true;
}
static bool
handle_done_auth(void)
{
struct ead_msg_auth *auth = EAD_DATA(msg, auth);
if (t_clientverify(tc, auth->data) != 0) {
fprintf(stderr, "Client auth verify failed\n");
return false;
}
return true;
}
static bool
handle_cmd_data(void)
{
struct ead_msg_cmd_data *cmd = EAD_ENC_DATA(msg, cmd_data);
int datalen = ead_decrypt_message(msg) - sizeof(struct ead_msg_cmd_data);
if (datalen < 0)
return false;
if (datalen > 0) {
write(1, cmd->data, datalen);
}
return !!cmd->done;
}
static int
send_ping(void)
{
msg->type = htonl(EAD_TYPE_PING);
msg->len = 0;
return send_packet(EAD_TYPE_PONG, handle_pong, (nid == 0xffff ? 0 : 1));
}
static int
send_username(void)
{
msg->type = htonl(EAD_TYPE_SET_USERNAME);
msg->len = htonl(sizeof(struct ead_msg_user));
strcpy(EAD_DATA(msg, user)->username, username);
return send_packet(EAD_TYPE_ACK_USERNAME, handle_none, 1);
}
static int
get_prime(void)
{
msg->type = htonl(EAD_TYPE_GET_PRIME);
msg->len = 0;
return send_packet(EAD_TYPE_PRIME, handle_prime, 1);
}
static int
send_a(void)
{
struct ead_msg_number *num = EAD_DATA(msg, number);
A = t_clientgenexp(tc);
msg->type = htonl(EAD_TYPE_SEND_A);
msg->len = htonl(sizeof(struct ead_msg_number) + A->len);
memcpy(num->data, A->data, A->len);
return send_packet(EAD_TYPE_SEND_B, handle_b, 1);
}
static int
send_auth(void)
{
struct ead_msg_auth *auth = EAD_DATA(msg, auth);
prepare_password();
t_clientpasswd(tc, password);
skey = t_clientgetkey(tc, &B);
if (!skey)
return 0;
ead_set_key(skey);
msg->type = htonl(EAD_TYPE_SEND_AUTH);
msg->len = htonl(sizeof(struct ead_msg_auth));
memcpy(auth->data, t_clientresponse(tc), sizeof(auth->data));
return send_packet(EAD_TYPE_DONE_AUTH, handle_done_auth, 1);
}
static int
send_command(const char *command)
{
struct ead_msg_cmd *cmd = EAD_ENC_DATA(msg, cmd);
msg->type = htonl(EAD_TYPE_SEND_CMD);
cmd->type = htons(EAD_CMD_NORMAL);
cmd->timeout = htons(10);
strncpy((char *)cmd->data, command, 1024);
ead_encrypt_message(msg, sizeof(struct ead_msg_cmd) + strlen(command) + 1);
return send_packet(EAD_TYPE_RESULT_CMD, handle_cmd_data, 1);
}
static int
usage(const char *prog)
{
fprintf(stderr, "Usage: %s <node> <username>[:<password>]\n"
"\n"
"\n<node>: Node ID (4 digits hex)\n"
"\n<username>: Username to authenticate with\n"
"\n"
"\nPassing no arguments shows a list of active nodes on the network\n"
"\n", prog);
return -1;
}
int main(int argc, char **argv)
{
int val = 1;
char *st = NULL;
const char *command = NULL;
msg->magic = htonl(EAD_MAGIC);
msg->tid = 0;
memset(&local, 0, sizeof(local));
memset(&remote, 0, sizeof(remote));
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = 0xffffffff;
remote.sin_port = htons(EAD_PORT);
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = 0;
switch(argc) {
case 4:
command = argv[3];
/* fall through */
case 3:
username = argv[2];
st = strchr(username, ':');
if (st) {
*st = 0;
st++;
strncpy(password, st, sizeof(password));
password[sizeof(password) - 1] = 0;
/* hide command line password */
memset(st, 0, strlen(st));
}
/* fall through */
case 2:
nid = strtoul(argv[1], &st, 16);
if (st && st[0] != 0)
return usage(argv[0]);
/* fall through */
case 1:
break;
default:
return usage(argv[0]);
}
msg->nid = htons(nid);
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0) {
perror("socket");
return -1;
}
setsockopt(s, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0) {
perror("bind");
return -1;
}
sockflags = fcntl(s, F_GETFL);
if (!send_ping()) {
fprintf(stderr, "No devices found\n");
return 1;
}
if (nid == 0xffff)
return 0;
if (!username || !password[0])
return 0;
if (!send_username()) {
fprintf(stderr, "Device did not accept user name\n");
return 1;
}
if (!get_prime()) {
fprintf(stderr, "Failed to get user password info\n");
return 1;
}
timeout = EAD_TIMEOUT_LONG;
if (!send_a()) {
fprintf(stderr, "Failed to send local authentication data\n");
return 1;
}
if (!send_auth()) {
fprintf(stderr, "Authentication failed\n");
return 1;
}
if (!command) {
fprintf(stderr, "Authentication succesful\n");
return 0;
}
if (!send_command(command)) {
fprintf(stderr, "Command failed\n");
return 1;
}
return 0;
}

179
package/ead/src/ead-crypt.c Normal file
View File

@ -0,0 +1,179 @@
/*
* Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* 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.
*/
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include "ead.h"
#include "sha1.c"
#include "aes.c"
#if EAD_DEBUGLEVEL >= 1
#define DEBUG(n, format, ...) do { \
if (EAD_DEBUGLEVEL >= n) \
fprintf(stderr, format, ##__VA_ARGS__); \
} while (0);
#else
#define DEBUG(n, format, ...) do {} while(0)
#endif
static uint32_t aes_enc_ctx[AES_PRIV_SIZE];
static uint32_t aes_dec_ctx[AES_PRIV_SIZE];
static uint32_t ead_rx_iv;
static uint32_t ead_tx_iv;
static uint32_t ivofs_vec;
static unsigned int ivofs_idx = 0;
static uint32_t W[80]; /* work space for sha1 */
#define EAD_ENC_PAD 64
void
ead_set_key(unsigned char *skey)
{
uint32_t *ivp = (uint32_t *)skey;
memset(aes_enc_ctx, 0, sizeof(aes_enc_ctx));
memset(aes_dec_ctx, 0, sizeof(aes_dec_ctx));
/* first 32 bytes of skey are used as aes key for
* encryption and decryption */
rijndaelKeySetupEnc(aes_enc_ctx, skey);
rijndaelKeySetupDec(aes_dec_ctx, skey);
/* the following bytes are used as initialization vector for messages
* (highest byte cleared to avoid overflow) */
ivp += 8;
ead_rx_iv = ntohl(*ivp) & 0x00ffffff;
ead_tx_iv = ead_rx_iv;
/* the last bytes are used to feed the random iv increment */
ivp++;
ivofs_vec = *ivp;
}
static bool
ead_check_rx_iv(uint32_t iv)
{
if (iv <= ead_rx_iv)
return false;
if (iv > ead_rx_iv + EAD_MAX_IV_INCR)
return false;
ead_rx_iv = iv;
return true;
}
static uint32_t
ead_get_tx_iv(void)
{
unsigned int ofs;
ofs = 1 + ((ivofs_vec >> 2 * ivofs_idx) & 0x3);
ivofs_idx = (ivofs_idx + 1) % 16;
ead_tx_iv += ofs;
return ead_tx_iv;
}
static void
ead_hash_message(struct ead_msg_encrypted *enc, uint32_t *hash, int len)
{
unsigned char *data = (unsigned char *) enc;
/* hash the packet with the stored hash part initialized to zero */
sha_init(hash);
memset(enc->hash, 0, sizeof(enc->hash));
while (len > 0) {
sha_transform(hash, data, W);
len -= 64;
data += 64;
}
}
void
ead_encrypt_message(struct ead_msg *msg, unsigned int len)
{
struct ead_msg_encrypted *enc = EAD_DATA(msg, enc);
unsigned char *data = (unsigned char *) enc;
uint32_t hash[5];
int enclen, i;
len += sizeof(struct ead_msg_encrypted);
enc->pad = (EAD_ENC_PAD - (len % EAD_ENC_PAD)) % EAD_ENC_PAD;
enclen = len + enc->pad;
msg->len = htonl(enclen);
enc->iv = htonl(ead_get_tx_iv());
ead_hash_message(enc, hash, enclen);
for (i = 0; i < 5; i++)
enc->hash[i] = htonl(hash[i]);
DEBUG(2, "SHA1 generate (0x%08x), len=%d\n", enc->hash[0], enclen);
while (enclen > 0) {
rijndaelEncrypt(aes_enc_ctx, data, data);
data += 16;
enclen -= 16;
}
}
int
ead_decrypt_message(struct ead_msg *msg)
{
struct ead_msg_encrypted *enc = EAD_DATA(msg, enc);
unsigned char *data = (unsigned char *) enc;
uint32_t hash_old[5], hash_new[5];
int len = ntohl(msg->len);
int i, enclen = len;
if (!len || (len % EAD_ENC_PAD > 0))
return 0;
while (len > 0) {
rijndaelDecrypt(aes_dec_ctx, data, data);
data += 16;
len -= 16;
}
data = (unsigned char *) enc;
if (enc->pad >= EAD_ENC_PAD) {
DEBUG(2, "Invalid padding length\n");
return 0;
}
if (!ead_check_rx_iv(ntohl(enc->iv))) {
DEBUG(2, "RX IV mismatch (0x%08x <> 0x%08x)\n", ead_rx_iv, ntohl(enc->iv));
return 0;
}
for (i = 0; i < 5; i++)
hash_old[i] = ntohl(enc->hash[i]);
ead_hash_message(enc, hash_new, enclen);
if (memcmp(hash_old, hash_new, sizeof(hash_old)) != 0) {
DEBUG(2, "SHA1 mismatch (0x%08x != 0x%08x), len=%d\n", hash_old[0], hash_new[0], enclen);
return 0;
}
enclen -= enc->pad + sizeof(struct ead_msg_encrypted);
return enclen;
}

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* 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 __EAD_CRYPT_H
#define __EAD_CRYPT_H
extern void ead_set_key(unsigned char *skey);
extern void ead_encrypt_message(struct ead_msg *msg, unsigned int len);
extern int ead_decrypt_message(struct ead_msg *msg);
#endif

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2001-2003, Adam Dunkels.
* 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. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 file was part of the uIP TCP/IP stack.
*
*/
#ifndef __EAD_PCAP_H
#define __EAD_PCAP_H
#include <net/ethernet.h>
#include <stdint.h>
#include "ead.h"
typedef uint8_t u8_t;
typedef uint16_t u16_t;
/* The UDP and IP headers. */
struct ead_packet {
struct ether_header eh;
/* IP header. */
u8_t vhl,
tos,
len[2],
ipid[2],
ipoffset[2],
ttl,
proto;
u16_t ipchksum;
u16_t srcipaddr[2],
destipaddr[2];
/* UDP header. */
u16_t srcport,
destport;
u16_t udplen;
u16_t udpchksum;
struct ead_msg msg;
} __attribute__((packed));
#define UIP_PROTO_UDP 17
#define UIP_IPH_LEN 20 /* Size of IP header */
#define UIP_UDPH_LEN 8 /* Size of UDP header */
#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN)
#endif

931
package/ead/src/ead.c Normal file
View File

@ -0,0 +1,931 @@
/*
* Emergency Access Daemon
* Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* 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.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <fcntl.h>
#include <signal.h>
#include <pcap.h>
#include <pcap-bpf.h>
#include <t_pwd.h>
#include <t_read.h>
#include <t_sha.h>
#include <t_defines.h>
#include <t_server.h>
#include "list.h"
#include "ead.h"
#include "ead-pcap.h"
#include "ead-crypt.h"
#include "filter.c"
#ifdef linux
#include "libbridge_init.c"
#endif
#define PASSWD_FILE "/etc/passwd"
#ifndef DEFAULT_IFNAME
#define DEFAULT_IFNAME "eth0"
#endif
#ifndef DEFAULT_DEVNAME
#define DEFAULT_DEVNAME "Unknown"
#endif
#define PCAP_MRU 1600
#define PCAP_TIMEOUT 200
#if EAD_DEBUGLEVEL >= 1
#define DEBUG(n, format, ...) do { \
if (EAD_DEBUGLEVEL >= n) \
fprintf(stderr, format, ##__VA_ARGS__); \
} while (0);
#else
#define DEBUG(n, format, ...) do {} while(0)
#endif
static char ethmac[6] = "\x00\x13\x37\x00\x00\x00"; /* last 3 bytes will be randomized */
static pcap_t *pcap_fp = NULL;
static pcap_t *pcap_fp_rx = NULL;
static const char *ifname = DEFAULT_IFNAME;
static char pktbuf_b[PCAP_MRU];
static struct ead_packet *pktbuf = (struct ead_packet *)pktbuf_b;
static u16_t nid = 0xffff; /* node id */
static char username[32] = "";
static int state = EAD_TYPE_SET_USERNAME;
static const char *passwd_file = PASSWD_FILE;
static const char password[MAXPARAMLEN];
static bool child_pending = false;
static unsigned char abuf[MAXPARAMLEN + 1];
static unsigned char pwbuf[MAXPARAMLEN];
static unsigned char saltbuf[MAXSALTLEN];
static unsigned char pw_saltbuf[MAXSALTLEN];
static struct list_head instances;
static const char *dev_name = DEFAULT_DEVNAME;
static bool nonfork = false;
#ifdef linux
static const char *brname = NULL;
#endif
struct ead_instance {
struct list_head list;
char name[16];
int pid;
#ifdef linux
char bridge[16];
bool br_check;
#endif
};
static struct t_pwent tpe = {
.name = username,
.index = 1,
.password.data = pwbuf,
.password.len = 0,
.salt.data = saltbuf,
.salt.len = 0,
};
struct t_confent *tce = NULL;
static struct t_server *ts = NULL;
static struct t_num A, *B = NULL;
unsigned char *skey;
static bool
prepare_password(void)
{
static char lbuf[1024];
unsigned char dig[SHA_DIGESTSIZE];
BigInteger x, v, n, g;
SHA1_CTX ctxt;
int ulen = strlen(username);
FILE *f;
lbuf[sizeof(lbuf) - 1] = 0;
f = fopen(passwd_file, "r");
if (!f)
return false;
while (fgets(lbuf, sizeof(lbuf) - 1, f) != NULL) {
char *str, *s2;
if (strncmp(lbuf, username, ulen) != 0)
continue;
if (lbuf[ulen] != ':')
continue;
str = &lbuf[ulen + 1];
if (strncmp(str, "$1$", 3) != 0)
continue;
s2 = strchr(str + 3, '$');
if (!s2)
continue;
if (s2 - str >= MAXSALTLEN)
continue;
strncpy((char *) pw_saltbuf, str, s2 - str);
pw_saltbuf[s2 - str] = 0;
s2 = strchr(s2, ':');
if (!s2)
continue;
*s2 = 0;
if (s2 - str >= MAXPARAMLEN)
continue;
strncpy((char *)password, str, MAXPARAMLEN);
fclose(f);
goto hash_password;
}
/* not found */
fclose(f);
return false;
hash_password:
tce = gettcid(tpe.index);
do {
t_random(tpe.password.data, SALTLEN);
} while (memcmp(saltbuf, (char *)dig, sizeof(saltbuf)) == 0);
if (saltbuf[0] == 0)
saltbuf[0] = 0xff;
n = BigIntegerFromBytes(tce->modulus.data, tce->modulus.len);
g = BigIntegerFromBytes(tce->generator.data, tce->generator.len);
v = BigIntegerFromInt(0);
SHA1Init(&ctxt);
SHA1Update(&ctxt, (unsigned char *) username, strlen(username));
SHA1Update(&ctxt, (unsigned char *) ":", 1);
SHA1Update(&ctxt, (unsigned char *) password, strlen(password));
SHA1Final(dig, &ctxt);
SHA1Init(&ctxt);
SHA1Update(&ctxt, saltbuf, tpe.salt.len);
SHA1Update(&ctxt, dig, sizeof(dig));
SHA1Final(dig, &ctxt);
/* x = H(s, H(u, ':', p)) */
x = BigIntegerFromBytes(dig, sizeof(dig));
BigIntegerModExp(v, g, x, n);
tpe.password.len = BigIntegerToBytes(v, (unsigned char *)pwbuf);
BigIntegerFree(v);
BigIntegerFree(x);
BigIntegerFree(g);
BigIntegerFree(n);
return true;
}
static u16_t
chksum(u16_t sum, const u8_t *data, u16_t len)
{
u16_t t;
const u8_t *dataptr;
const u8_t *last_byte;
dataptr = data;
last_byte = data + len - 1;
while(dataptr < last_byte) { /* At least two more bytes */
t = (dataptr[0] << 8) + dataptr[1];
sum += t;
if(sum < t) {
sum++; /* carry */
}
dataptr += 2;
}
if(dataptr == last_byte) {
t = (dataptr[0] << 8) + 0;
sum += t;
if(sum < t) {
sum++; /* carry */
}
}
/* Return sum in host byte order. */
return sum;
}
static void
ead_send_packet_clone(struct ead_packet *pkt)
{
u16_t len, sum;
memcpy(pktbuf, pkt, offsetof(struct ead_packet, msg));
memcpy(pktbuf->eh.ether_shost, ethmac, 6);
memcpy(pktbuf->eh.ether_dhost, pkt->eh.ether_shost, 6);
/* ip header */
len = sizeof(struct ead_packet) - sizeof(struct ether_header) + ntohl(pktbuf->msg.len);
pktbuf->len[0] = len >> 8;
pktbuf->len[1] = len & 0xff;
memcpy(pktbuf->srcipaddr, pkt->destipaddr, 4);
memcpy(pktbuf->destipaddr, pkt->srcipaddr, 4);
/* ip checksum */
pktbuf->ipchksum = 0;
sum = chksum(0, (void *) &pktbuf->vhl, UIP_IPH_LEN);
if (sum == 0)
sum = 0xffff;
pktbuf->ipchksum = htons(~sum);
/* udp header */
pktbuf->srcport = pkt->destport;
pktbuf->destport = pkt->srcport;
/* udp checksum */
len -= UIP_IPH_LEN;
pktbuf->udplen = htons(len);
pktbuf->udpchksum = 0;
sum = len + UIP_PROTO_UDP;
sum = chksum(sum, (void *) &pktbuf->srcipaddr[0], 8); /* src, dest ip */
sum = chksum(sum, (void *) &pktbuf->srcport, len);
if (sum == 0)
sum = 0xffff;
pktbuf->udpchksum = htons(~sum);
pcap_sendpacket(pcap_fp, (void *) pktbuf, sizeof(struct ead_packet) + ntohl(pktbuf->msg.len));
}
static void
set_state(int nstate)
{
if (state == nstate)
return;
if (nstate < state) {
if ((nstate < EAD_TYPE_GET_PRIME) &&
(state >= EAD_TYPE_GET_PRIME)) {
t_serverclose(ts);
ts = NULL;
}
goto done;
}
switch(state) {
case EAD_TYPE_SET_USERNAME:
if (!prepare_password())
goto error;
ts = t_serveropenraw(&tpe, tce);
if (!ts)
goto error;
break;
case EAD_TYPE_GET_PRIME:
B = t_servergenexp(ts);
break;
case EAD_TYPE_SEND_A:
skey = t_servergetkey(ts, &A);
if (!skey)
goto error;
ead_set_key(skey);
break;
}
done:
state = nstate;
error:
return;
}
static bool
handle_ping(struct ead_packet *pkt, int len, int *nstate)
{
struct ead_msg *msg = &pktbuf->msg;
struct ead_msg_pong *pong = EAD_DATA(msg, pong);
int slen;
slen = strlen(dev_name);
if (slen > 1024)
slen = 1024;
msg->len = htonl(sizeof(struct ead_msg_pong) + slen);
strncpy(pong->name, dev_name, slen);
pong->name[len] = 0;
pong->auth_type = htons(EAD_AUTH_MD5);
return true;
}
static bool
handle_set_username(struct ead_packet *pkt, int len, int *nstate)
{
struct ead_msg *msg = &pkt->msg;
struct ead_msg_user *user = EAD_DATA(msg, user);
set_state(EAD_TYPE_SET_USERNAME); /* clear old state */
strncpy(username, user->username, sizeof(username));
username[sizeof(username)] = 0;
msg = &pktbuf->msg;
msg->len = 0;
*nstate = EAD_TYPE_GET_PRIME;
return true;
}
static bool
handle_get_prime(struct ead_packet *pkt, int len, int *nstate)
{
struct ead_msg *msg = &pktbuf->msg;
struct ead_msg_salt *salt = EAD_DATA(msg, salt);
msg->len = htonl(sizeof(struct ead_msg_salt));
salt->prime = tce->index - 1;
salt->len = ts->s.len;
memcpy(salt->salt, ts->s.data, ts->s.len);
memcpy(salt->ext_salt, pw_saltbuf, MAXSALTLEN);
*nstate = EAD_TYPE_SEND_A;
return true;
}
static bool
handle_send_a(struct ead_packet *pkt, int len, int *nstate)
{
struct ead_msg *msg = &pkt->msg;
struct ead_msg_number *number = EAD_DATA(msg, number);
len = ntohl(msg->len) - sizeof(struct ead_msg_number);
if (len > MAXPARAMLEN + 1)
return false;
A.len = len;
A.data = abuf;
memcpy(A.data, number->data, len);
msg = &pktbuf->msg;
number = EAD_DATA(msg, number);
msg->len = htonl(sizeof(struct ead_msg_number) + B->len);
memcpy(number->data, B->data, B->len);
*nstate = EAD_TYPE_SEND_AUTH;
return true;
}
static bool
handle_send_auth(struct ead_packet *pkt, int len, int *nstate)
{
struct ead_msg *msg = &pkt->msg;
struct ead_msg_auth *auth = EAD_DATA(msg, auth);
if (t_serververify(ts, auth->data) != 0) {
DEBUG(2, "Client authentication failed\n");
*nstate = EAD_TYPE_SET_USERNAME;
return false;
}
msg = &pktbuf->msg;
auth = EAD_DATA(msg, auth);
msg->len = htonl(sizeof(struct ead_msg_auth));
DEBUG(2, "Client authentication successful\n");
memcpy(auth->data, t_serverresponse(ts), sizeof(auth->data));
*nstate = EAD_TYPE_SEND_CMD;
return true;
}
static bool
handle_send_cmd(struct ead_packet *pkt, int len, int *nstate)
{
struct ead_msg *msg = &pkt->msg;
struct ead_msg_cmd *cmd = EAD_ENC_DATA(msg, cmd);
struct ead_msg_cmd_data *cmddata;
struct timeval tv, to, tn;
int pfd[2], fd;
fd_set fds;
pid_t pid;
bool stream = false;
int timeout;
int type;
int datalen;
datalen = ead_decrypt_message(msg) - sizeof(struct ead_msg_cmd);
if (datalen <= 0)
return false;
type = ntohs(cmd->type);
timeout = ntohs(cmd->timeout);
FD_ZERO(&fds);
cmd->data[datalen] = 0;
switch(type) {
case EAD_CMD_NORMAL:
if (pipe(pfd) < 0)
return false;
fcntl(pfd[0], F_SETFL, O_NONBLOCK | fcntl(pfd[0], F_GETFL));
child_pending = true;
pid = fork();
if (pid == 0) {
close(pfd[0]);
fd = open("/dev/null", O_RDWR);
if (fd > 0) {
dup2(fd, 0);
dup2(pfd[1], 1);
dup2(pfd[1], 2);
}
system((char *)cmd->data);
exit(0);
} else if (pid > 0) {
close(pfd[1]);
if (!timeout)
timeout = EAD_CMD_TIMEOUT;
stream = true;
break;
}
return false;
case EAD_CMD_BACKGROUND:
pid = fork();
if (pid == 0) {
/* close stdin, stdout, stderr, replace with fd to /dev/null */
fd = open("/dev/null", O_RDWR);
if (fd > 0) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
}
system((char *)cmd->data);
exit(0);
} else if (pid > 0) {
break;
}
return false;
default:
return false;
}
msg = &pktbuf->msg;
cmddata = EAD_ENC_DATA(msg, cmd_data);
if (stream) {
int nfds, bytes;
/* send keepalive packets every 200 ms so that the client doesn't timeout */
gettimeofday(&to, NULL);
memcpy(&tn, &to, sizeof(tn));
tv.tv_usec = PCAP_TIMEOUT * 1000;
tv.tv_sec = 0;
do {
cmddata->done = 0;
FD_SET(pfd[0], &fds);
nfds = select(pfd[0] + 1, &fds, NULL, NULL, &tv);
bytes = 0;
if (nfds > 0) {
bytes = read(pfd[0], cmddata->data, 1024);
if (bytes < 0)
bytes = 0;
}
if (!bytes && !child_pending)
break;
DEBUG(3, "Sending %d bytes of console data, type=%d, timeout=%d\n", bytes, ntohl(msg->type), timeout);
ead_encrypt_message(msg, sizeof(struct ead_msg_cmd_data) + bytes);
ead_send_packet_clone(pkt);
gettimeofday(&tn, NULL);
} while (tn.tv_sec < to.tv_sec + timeout);
if (child_pending) {
kill(pid, SIGKILL);
return false;
}
}
cmddata->done = 1;
ead_encrypt_message(msg, sizeof(struct ead_msg_cmd_data));
return true;
}
static void
parse_message(struct ead_packet *pkt, int len)
{
bool (*handler)(struct ead_packet *pkt, int len, int *nstate);
int min_len = sizeof(struct ead_packet);
int nstate = state;
int type = ntohl(pkt->msg.type);
if ((type >= EAD_TYPE_GET_PRIME) &&
(state != type))
return;
switch(type) {
case EAD_TYPE_PING:
handler = handle_ping;
break;
case EAD_TYPE_SET_USERNAME:
handler = handle_set_username;
min_len += sizeof(struct ead_msg_user);
break;
case EAD_TYPE_GET_PRIME:
handler = handle_get_prime;
break;
case EAD_TYPE_SEND_A:
handler = handle_send_a;
min_len += sizeof(struct ead_msg_number);
break;
case EAD_TYPE_SEND_AUTH:
handler = handle_send_auth;
min_len += sizeof(struct ead_msg_auth);
break;
case EAD_TYPE_SEND_CMD:
handler = handle_send_cmd;
min_len += sizeof(struct ead_msg_cmd) + sizeof(struct ead_msg_encrypted);
break;
default:
return;
}
if (len < min_len) {
DEBUG(2, "discarding packet: message too small\n");
return;
}
pktbuf->msg.magic = htonl(EAD_MAGIC);
pktbuf->msg.type = htonl(type + 1);
pktbuf->msg.nid = htons(nid);
pktbuf->msg.len = 0;
if (handler(pkt, len, &nstate)) {
DEBUG(2, "sending response to packet type %d: %d\n", type + 1, ntohl(pktbuf->msg.len));
/* format response packet */
ead_send_packet_clone(pkt);
}
set_state(nstate);
}
static void
handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
struct ead_packet *pkt = (struct ead_packet *) bytes;
if (h->len < sizeof(struct ead_packet))
return;
if (pkt->eh.ether_type != htons(ETHERTYPE_IP))
return;
if (memcmp(pkt->eh.ether_dhost, "\xff\xff\xff\xff\xff\xff", 6) != 0)
return;
if (pkt->proto != UIP_PROTO_UDP)
return;
if (pkt->destport != htons(EAD_PORT))
return;
if (pkt->msg.magic != htonl(EAD_MAGIC))
return;
if (h->len < sizeof(struct ead_packet) + ntohl(pkt->msg.len))
return;
if ((pkt->msg.nid != 0xffff) &&
(pkt->msg.nid != htons(nid)))
return;
parse_message(pkt, h->len);
}
static void
ead_pcap_reopen(bool first)
{
static char errbuf[PCAP_ERRBUF_SIZE] = "";
if (pcap_fp_rx != pcap_fp)
pcap_close(pcap_fp_rx);
if (pcap_fp)
pcap_close(pcap_fp);
pcap_fp_rx = pcap_fp;
do {
pcap_fp = pcap_open_live(ifname, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
#ifdef linux
if (brname) {
pcap_fp_rx = pcap_open_live(brname, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
if (!pcap_fp_rx)
pcap_fp_rx = pcap_fp;
}
#endif
pcap_setfilter(pcap_fp_rx, &pktfilter);
if (first && !pcap_fp) {
DEBUG(1, "WARNING: unable to open interface '%s'\n", ifname);
first = false;
}
if (!pcap_fp)
sleep(1);
} while (!pcap_fp);
}
static void
ead_pktloop(void)
{
while (1) {
if (pcap_dispatch(pcap_fp_rx, 1, handle_packet, NULL) < 0) {
ead_pcap_reopen(false);
continue;
}
}
}
static int
usage(const char *prog)
{
fprintf(stderr, "Usage: %s [<options>]\n"
"Options:\n"
"\t-B Run in background mode\n"
"\t-d <device> Set the device to listen on\n"
"\t-D <name> Set the name of the device visible to clients\n"
"\t-p <file> Set the password file for authenticating\n"
"\t-P <file> Write a pidfile\n"
"\n", prog);
return -1;
}
static void
server_handle_sigchld(int sig)
{
struct ead_instance *in;
struct list_head *p;
int pid = 0;
wait(&pid);
list_for_each(p, &instances) {
in = list_entry(p, struct ead_instance, list);
if (pid != in->pid)
continue;
in->pid = 0;
break;
}
}
static void
instance_handle_sigchld(int sig)
{
int pid = 0;
wait(&pid);
child_pending = false;
}
static void
start_server(struct ead_instance *i)
{
if (!nonfork) {
i->pid = fork();
if (i->pid != 0) {
if (i->pid < 0)
i->pid = 0;
return;
}
}
signal(SIGCHLD, instance_handle_sigchld);
ifname = i->name;
#ifdef linux
if (i->bridge[0])
brname = i->bridge;
#endif
ead_pcap_reopen(true);
ead_pktloop();
pcap_close(pcap_fp);
if (pcap_fp_rx != pcap_fp)
pcap_close(pcap_fp_rx);
exit(0);
}
static void
start_servers(bool restart)
{
struct ead_instance *in;
struct list_head *p;
list_for_each(p, &instances) {
in = list_entry(p, struct ead_instance, list);
if (in->pid > 0)
continue;
sleep(1);
start_server(in);
}
}
static void
stop_server(struct ead_instance *in, bool do_free)
{
if (in->pid > 0)
kill(in->pid, SIGKILL);
in->pid = 0;
if (do_free) {
list_del(&in->list);
free(in);
}
}
static void
server_handle_sigint(int sig)
{
struct ead_instance *in;
struct list_head *p, *tmp;
list_for_each_safe(p, tmp, &instances) {
in = list_entry(p, struct ead_instance, list);
stop_server(in, true);
}
exit(1);
}
#ifdef linux
static int
check_bridge_port(const char *br, const char *port, void *arg)
{
struct ead_instance *in;
struct list_head *p, *tmp;
list_for_each(p, &instances) {
in = list_entry(p, struct ead_instance, list);
if (strcmp(in->name, port) != 0)
continue;
in->br_check = true;
if (strcmp(in->bridge, br) == 0)
break;
strncpy(in->bridge, br, sizeof(in->bridge));
DEBUG(2, "assigning port %s to bridge %s\n", in->name, in->bridge);
stop_server(in, false);
}
return 0;
}
static int
check_bridge(const char *name, void *arg)
{
br_foreach_port(name, check_bridge_port, arg);
return 0;
}
#endif
static void
check_all_interfaces(void)
{
#ifdef linux
struct ead_instance *in;
struct list_head *p, *tmp;
br_foreach_bridge(check_bridge, NULL);
/* look for interfaces that are no longer part of a bridge */
list_for_each(p, &instances) {
in = list_entry(p, struct ead_instance, list);
if (in->br_check) {
in->br_check = false;
} else if (in->bridge[0]) {
DEBUG(2, "removing port %s from bridge %s\n", in->name, in->bridge);
in->bridge[0] = 0;
stop_server(in, false);
}
}
#endif
}
int main(int argc, char **argv)
{
struct ead_instance *in;
struct timeval tv;
int fd, ch;
const char *pidfile = NULL;
bool background = false;
int n_iface = 0;
if (argc == 1)
return usage(argv[0]);
INIT_LIST_HEAD(&instances);
while ((ch = getopt(argc, argv, "Bd:D:fhp:P:")) != -1) {
switch(ch) {
case 'B':
background = true;
break;
case 'f':
nonfork = true;
break;
case 'h':
return usage(argv[0]);
case 'd':
in = malloc(sizeof(struct ead_instance));
memset(in, 0, sizeof(struct ead_instance));
INIT_LIST_HEAD(&in->list);
strncpy(in->name, optarg, sizeof(in->name) - 1);
list_add(&in->list, &instances);
n_iface++;
break;
case 'D':
dev_name = optarg;
break;
case 'p':
passwd_file = optarg;
break;
case 'P':
pidfile = optarg;
break;
}
}
signal(SIGCHLD, server_handle_sigchld);
signal(SIGINT, server_handle_sigint);
signal(SIGTERM, server_handle_sigint);
signal(SIGKILL, server_handle_sigint);
if (!n_iface) {
fprintf(stderr, "Error: ead needs at least one interface\n");
return -1;
}
if (background) {
if (fork() > 0)
exit(0);
fd = open("/dev/null", O_RDWR);
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
}
if (pidfile) {
char pid[8];
int len;
unlink(pidfile);
fd = open(pidfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
if (fd > 0) {
len = sprintf(pid, "%d\n", getpid());
write(fd, pid, len);
close(fd);
}
}
/* randomize the mac address */
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) {
perror("open");
exit(1);
}
read(fd, ethmac + 3, 3);
close(fd);
nid = *(((u16_t *) ethmac) + 2);
start_servers(false);
#ifdef linux
br_init();
#endif
tv.tv_sec = 1;
tv.tv_usec = 0;
while (1) {
check_all_interfaces();
start_servers(true);
sleep(1);
}
#ifdef linux
br_shutdown();
#endif
return 0;
}

134
package/ead/src/ead.h Normal file
View File

@ -0,0 +1,134 @@
/*
* Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* 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 __EAD_H
#define __EAD_H
#define EAD_DEBUGLEVEL 1
#include <stdint.h>
#include <stddef.h>
#ifndef MAXSALTLEN
#define MAXSALTLEN 32
#endif
#define EAD_PORT 56026UL
#define EAD_MAGIC 3671771902UL
#define EAD_CMD_TIMEOUT 10
#define EAD_MAX_IV_INCR 128
/* request/response types */
/* response id == request id + 1 */
enum ead_type {
EAD_TYPE_PING,
EAD_TYPE_PONG,
EAD_TYPE_SET_USERNAME,
EAD_TYPE_ACK_USERNAME,
EAD_TYPE_GET_PRIME,
EAD_TYPE_PRIME,
EAD_TYPE_SEND_A,
EAD_TYPE_SEND_B,
EAD_TYPE_SEND_AUTH,
EAD_TYPE_DONE_AUTH,
EAD_TYPE_SEND_CMD,
EAD_TYPE_RESULT_CMD,
EAD_TYPE_LAST
};
enum ead_auth_type {
EAD_AUTH_DEFAULT,
EAD_AUTH_MD5
};
enum ead_cmd_type {
EAD_CMD_NORMAL,
EAD_CMD_BACKGROUND,
EAD_CMD_LAST
};
struct ead_msg_pong {
uint16_t auth_type;
char name[];
} __attribute__((packed));
struct ead_msg_number {
uint8_t id;
unsigned char data[];
} __attribute__((packed));
struct ead_msg_salt {
uint8_t prime;
uint8_t len;
unsigned char salt[MAXSALTLEN];
unsigned char ext_salt[MAXSALTLEN];
} __attribute__((packed));
struct ead_msg_user {
char username[32];
} __attribute__((packed));
struct ead_msg_auth {
unsigned char data[20];
} __attribute__((packed));
struct ead_msg_cmd {
uint8_t type;
uint16_t timeout;
unsigned char data[];
} __attribute__((packed));
struct ead_msg_cmd_data {
uint8_t done;
unsigned char data[];
} __attribute__((packed));
struct ead_msg_encrypted {
uint32_t hash[5];
uint32_t iv;
uint8_t pad;
union {
struct ead_msg_cmd cmd;
struct ead_msg_cmd_data cmd_data;
} data[];
} __attribute__((packed));
#define EAD_DATA(_msg, _type) (&((_msg)->data[0]._type))
#define EAD_ENC_DATA(_msg, _type) (&((_msg)->data[0].enc.data[0]._type))
struct ead_msg {
uint32_t magic;
uint32_t len;
uint32_t type;
uint16_t nid; /* node id */
uint16_t tid; /* transaction id */
union {
struct ead_msg_pong pong;
struct ead_msg_user user;
struct ead_msg_number number;
struct ead_msg_auth auth;
struct ead_msg_salt salt;
struct ead_msg_encrypted enc;
} data[];
} __attribute__((packed));
#endif

23
package/ead/src/filter.c Normal file
View File

@ -0,0 +1,23 @@
/* precompiled expression: udp and dst host 255.255.255.255 and dst port 56026 */
static struct bpf_insn pktfilter_insns[] = {
{ .code = 0x0028, .jt = 0x00, .jf = 0x00, .k = 0x0000000c },
{ .code = 0x0015, .jt = 0x0b, .jf = 0x00, .k = 0x000086dd },
{ .code = 0x0015, .jt = 0x00, .jf = 0x0a, .k = 0x00000800 },
{ .code = 0x0030, .jt = 0x00, .jf = 0x00, .k = 0x00000017 },
{ .code = 0x0015, .jt = 0x00, .jf = 0x08, .k = 0x00000011 },
{ .code = 0x0020, .jt = 0x00, .jf = 0x00, .k = 0x0000001e },
{ .code = 0x0015, .jt = 0x00, .jf = 0x06, .k = 0xffffffff },
{ .code = 0x0028, .jt = 0x00, .jf = 0x00, .k = 0x00000014 },
{ .code = 0x0045, .jt = 0x04, .jf = 0x00, .k = 0x00001fff },
{ .code = 0x00b1, .jt = 0x00, .jf = 0x00, .k = 0x0000000e },
{ .code = 0x0048, .jt = 0x00, .jf = 0x00, .k = 0x00000010 },
{ .code = 0x0015, .jt = 0x00, .jf = 0x01, .k = 0x0000dada },
{ .code = 0x0006, .jt = 0x00, .jf = 0x00, .k = 0x000005dc },
{ .code = 0x0006, .jt = 0x00, .jf = 0x00, .k = 0x00000000 },
};
static struct bpf_program pktfilter = {
.bf_len = 14,
.bf_insns = pktfilter_insns,
};

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2000 Lennert Buytenhek
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _LIBBRIDGE_H
#define _LIBBRIDGE_H
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_bridge.h>
/* defined in net/if.h but that conflicts with linux/if.h... */
extern unsigned int if_nametoindex (const char *__ifname);
extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
struct bridge_id
{
unsigned char prio[2];
unsigned char addr[6];
};
struct bridge_info
{
struct bridge_id designated_root;
struct bridge_id bridge_id;
unsigned root_path_cost;
struct timeval max_age;
struct timeval hello_time;
struct timeval forward_delay;
struct timeval bridge_max_age;
struct timeval bridge_hello_time;
struct timeval bridge_forward_delay;
u_int16_t root_port;
unsigned char stp_enabled;
unsigned char topology_change;
unsigned char topology_change_detected;
struct timeval ageing_time;
struct timeval hello_timer_value;
struct timeval tcn_timer_value;
struct timeval topology_change_timer_value;
struct timeval gc_timer_value;
};
struct fdb_entry
{
u_int8_t mac_addr[6];
u_int16_t port_no;
unsigned char is_local;
struct timeval ageing_timer_value;
};
struct port_info
{
unsigned port_no;
struct bridge_id designated_root;
struct bridge_id designated_bridge;
u_int16_t port_id;
u_int16_t designated_port;
u_int8_t priority;
unsigned char top_change_ack;
unsigned char config_pending;
unsigned char state;
unsigned path_cost;
unsigned designated_cost;
struct timeval message_age_timer_value;
struct timeval forward_delay_timer_value;
struct timeval hold_timer_value;
};
#endif

View File

@ -0,0 +1,208 @@
/*
* Copyright (C) 2000 Lennert Buytenhek
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "libbridge.h"
#include "libbridge_private.h"
int br_socket_fd = -1;
static int br_init(void)
{
if ((br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
return errno;
return 0;
}
static void br_shutdown(void)
{
close(br_socket_fd);
br_socket_fd = -1;
}
/* If /sys/class/net/XXX/bridge exists then it must be a bridge */
static int isbridge(const struct dirent *entry)
{
char path[SYSFS_PATH_MAX];
struct stat st;
snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/bridge", entry->d_name);
return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
}
/*
* New interface uses sysfs to find bridges
*/
static int new_foreach_bridge(int (*iterator)(const char *name, void *),
void *arg)
{
struct dirent **namelist;
int i, count = 0;
count = scandir(SYSFS_CLASS_NET, &namelist, isbridge, alphasort);
if (count < 0)
return -1;
for (i = 0; i < count; i++) {
if (iterator(namelist[i]->d_name, arg))
break;
}
for (i = 0; i < count; i++)
free(namelist[i]);
free(namelist);
return count;
}
/*
* Old interface uses ioctl
*/
static int old_foreach_bridge(int (*iterator)(const char *, void *),
void *iarg)
{
int i, ret=0, num;
char ifname[IFNAMSIZ];
int ifindices[MAX_BRIDGES];
unsigned long args[3] = { BRCTL_GET_BRIDGES,
(unsigned long)ifindices, MAX_BRIDGES };
num = ioctl(br_socket_fd, SIOCGIFBR, args);
if (num < 0) {
dprintf("Get bridge indices failed: %s\n",
strerror(errno));
return -errno;
}
for (i = 0; i < num; i++) {
if (!if_indextoname(ifindices[i], ifname)) {
dprintf("get find name for ifindex %d\n",
ifindices[i]);
return -errno;
}
++ret;
if(iterator(ifname, iarg))
break;
}
return ret;
}
/*
* Go over all bridges and call iterator function.
* if iterator returns non-zero then stop.
*/
static int br_foreach_bridge(int (*iterator)(const char *, void *),
void *arg)
{
int ret;
ret = new_foreach_bridge(iterator, arg);
if (ret <= 0)
ret = old_foreach_bridge(iterator, arg);
return ret;
}
/*
* Only used if sysfs is not available.
*/
static int old_foreach_port(const char *brname,
int (*iterator)(const char *br, const char *port,
void *arg),
void *arg)
{
int i, err, count;
struct ifreq ifr;
char ifname[IFNAMSIZ];
int ifindices[MAX_PORTS];
unsigned long args[4] = { BRCTL_GET_PORT_LIST,
(unsigned long)ifindices, MAX_PORTS, 0 };
memset(ifindices, 0, sizeof(ifindices));
strncpy(ifr.ifr_name, brname, IFNAMSIZ);
ifr.ifr_data = (char *) &args;
err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
if (err < 0) {
dprintf("list ports for bridge:'%s' failed: %s\n",
brname, strerror(errno));
return -errno;
}
count = 0;
for (i = 0; i < MAX_PORTS; i++) {
if (!ifindices[i])
continue;
if (!if_indextoname(ifindices[i], ifname)) {
dprintf("can't find name for ifindex:%d\n",
ifindices[i]);
continue;
}
++count;
if (iterator(brname, ifname, arg))
break;
}
return count;
}
/*
* Iterate over all ports in bridge (using sysfs).
*/
static int br_foreach_port(const char *brname,
int (*iterator)(const char *br, const char *port, void *arg),
void *arg)
{
int i, count;
struct dirent **namelist;
char path[SYSFS_PATH_MAX];
snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brif", brname);
count = scandir(path, &namelist, 0, alphasort);
if (count < 0)
return old_foreach_port(brname, iterator, arg);
for (i = 0; i < count; i++) {
if (namelist[i]->d_name[0] == '.'
&& (namelist[i]->d_name[1] == '\0'
|| (namelist[i]->d_name[1] == '.'
&& namelist[i]->d_name[2] == '\0')))
continue;
if (iterator(brname, namelist[i]->d_name, arg))
break;
}
for (i = 0; i < count; i++)
free(namelist[i]);
free(namelist);
return count;
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2000 Lennert Buytenhek
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _LIBBRIDGE_PRIVATE_H
#define _LIBBRIDGE_PRIVATE_H
#include <linux/sockios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/if_bridge.h>
#define MAX_BRIDGES 1024
#define MAX_PORTS 1024
#define SYSFS_CLASS_NET "/sys/class/net/"
#define SYSFS_PATH_MAX 256
#define dprintf(fmt,arg...)
#endif

602
package/ead/src/list.h Normal file
View File

@ -0,0 +1,602 @@
/* GPL v2, adapted from the Linux kernel */
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
#include <stddef.h>
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#ifndef container_of
#define container_of(ptr, type, member) ( \
(type *)( (char *)ptr - offsetof(type,member) ))
#endif
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = NULL;
entry->prev = NULL;
}
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
static inline void __list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/**
* list_splice - join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)
/**
* __list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
* This variant differs from list_for_each() in that it's the
* simplest possible list iteration code, no prefetching is done.
* Use this for code that knows the list to be very short (empty
* or 1 entry) most of the time.
*/
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; \
pos != (head); \
pos = n, n = pos->prev)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member) \
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_continue
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_from
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_reverse
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = NULL;
n->pprev = NULL;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos; pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos; pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; pos && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; pos && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
#endif

3
package/ead/src/passwd Normal file
View File

@ -0,0 +1,3 @@
root:$1$MCGAgYw.$Ip1GcyeUliId3wzVcKR/e/:0:0:root:/root:/bin/ash
nobody:*:65534:65534:nobody:/var:/bin/false
daemon:*:65534:65534:daemon:/var:/bin/false

54
package/ead/src/pfc.c Normal file
View File

@ -0,0 +1,54 @@
/*
* Small pcap precompiler
* Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* 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.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <pcap.h>
int main (int argc, char ** argv)
{
struct bpf_program filter;
pcap_t *pc;
int i;
if (argc != 2)
{
printf ("Usage: %s <expression>\n", argv[0]);
return 1;
}
pc = pcap_open_dead(DLT_EN10MB, 1500);
if (pcap_compile(pc, &filter, argv[1], 1, 0) != 0) {
printf("error in active-filter expression: %s\n", pcap_geterr(pc));
return 1;
}
printf("/* precompiled expression: %s */\n\n"
"static struct bpf_insn pktfilter_insns[] = {\n",
argv[1]);
for (i = 0; i < filter.bf_len; i++) {
struct bpf_insn *in = &filter.bf_insns[i];
printf("\t{ .code = 0x%04x, .jt = 0x%02x, .jf = 0x%02x, .k = 0x%08x },\n", in->code, in->jt, in->jf, in->k);
}
printf("};\n\n"
"static struct bpf_program pktfilter = {\n"
"\t.bf_len = %d,\n"
"\t.bf_insns = pktfilter_insns,\n"
"};\n", filter.bf_len);
return 0;
}

View File

@ -0,0 +1,646 @@
/*
* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*
* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
* rights reserved.
*
* License to copy and use this software is granted provided that it
* is identified as the "RSA Data Security, Inc. MD5 Message-Digest
* Algorithm" in all material mentioning or referencing this software
* or this function.
*
* License is also granted to make and use derivative works provided
* that such works are identified as "derived from the RSA Data
* Security, Inc. MD5 Message-Digest Algorithm" in all material
* mentioning or referencing the derived work.
*
* RSA Data Security, Inc. makes no representations concerning either
* the merchantability of this software or the suitability of this
* software for any particular purpose. It is provided "as is"
* without express or implied warranty of any kind.
*
* These notices must be retained in any copies of any part of this
* documentation and/or software.
*
* $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $
*
* This code is the same as the code published by RSA Inc. It has been
* edited for clarity and style only.
*
* ----------------------------------------------------------------------------
* The md5_crypt() function was taken from freeBSD's libcrypt and contains
* this license:
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
*
* $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $
*
* ----------------------------------------------------------------------------
* On April 19th, 2001 md5_crypt() was modified to make it reentrant
* by Erik Andersen <andersen@uclibc.org>
*
*
* June 28, 2001 Manuel Novoa III
*
* "Un-inlined" code using loops and static const tables in order to
* reduce generated code size (on i386 from approx 4k to approx 2.5k).
*
* June 29, 2001 Manuel Novoa III
*
* Completely removed static PADDING array.
*
* Reintroduced the loop unrolling in MD5_Transform and added the
* MD5_SIZE_OVER_SPEED option for configurability. Define below as:
* 0 fully unrolled loops
* 1 partially unrolled (4 ops per loop)
* 2 no unrolling -- introduces the need to swap 4 variables (slow)
* 3 no unrolling and all 4 loops merged into one with switch
* in each loop (glacial)
* On i386, sizes are roughly (-Os -fno-builtin):
* 0: 3k 1: 2.5k 2: 2.2k 3: 2k
*
*
* Since SuSv3 does not require crypt_r, modified again August 7, 2002
* by Erik Andersen to remove reentrance stuff...
*/
static const uint8_t ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/*
* Valid values are 1 (fastest/largest) to 3 (smallest/slowest).
*/
#define MD5_SIZE_OVER_SPEED 3
/**********************************************************************/
/* MD5 context. */
struct MD5Context {
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
};
static void __md5_Init(struct MD5Context *);
static void __md5_Update(struct MD5Context *, const unsigned char *, unsigned int);
static void __md5_Pad(struct MD5Context *);
static void __md5_Final(unsigned char [16], struct MD5Context *);
static void __md5_Transform(uint32_t [4], const unsigned char [64]);
#define MD5_MAGIC_STR "$1$"
#define MD5_MAGIC_LEN (sizeof(MD5_MAGIC_STR) - 1)
static const unsigned char __md5__magic[] = MD5_MAGIC_STR;
#ifdef i386
#define __md5_Encode memcpy
#define __md5_Decode memcpy
#else /* i386 */
/*
* __md5_Encodes input (uint32_t) into output (unsigned char). Assumes len is
* a multiple of 4.
*/
static void
__md5_Encode(unsigned char *output, uint32_t *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = input[i];
output[j+1] = (input[i] >> 8);
output[j+2] = (input[i] >> 16);
output[j+3] = (input[i] >> 24);
}
}
/*
* __md5_Decodes input (unsigned char) into output (uint32_t). Assumes len is
* a multiple of 4.
*/
static void
__md5_Decode(uint32_t *output, const unsigned char *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
}
#endif /* i386 */
/* F, G, H and I are basic MD5 functions. */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/*
* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
* Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context. */
static void __md5_Init(struct MD5Context *context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants. */
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/*
* MD5 block update operation. Continues an MD5 message-digest
* operation, processing another message block, and updating the
* context.
*/
static void __md5_Update(struct MD5Context *context, const unsigned char *input, unsigned int inputLen)
{
unsigned int i, idx, partLen;
/* Compute number of bytes mod 64 */
idx = (context->count[0] >> 3) & 0x3F;
/* Update number of bits */
context->count[0] += (inputLen << 3);
if (context->count[0] < (inputLen << 3))
context->count[1]++;
context->count[1] += (inputLen >> 29);
partLen = 64 - idx;
/* Transform as many times as possible. */
if (inputLen >= partLen) {
memcpy(&context->buffer[idx], input, partLen);
__md5_Transform(context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
__md5_Transform(context->state, &input[i]);
idx = 0;
} else
i = 0;
/* Buffer remaining input */
memcpy(&context->buffer[idx], &input[i], inputLen - i);
}
/*
* MD5 padding. Adds padding followed by original length.
*/
static void __md5_Pad(struct MD5Context *context)
{
unsigned char bits[8];
unsigned int idx, padLen;
unsigned char PADDING[64];
memset(PADDING, 0, sizeof(PADDING));
PADDING[0] = 0x80;
/* Save number of bits */
__md5_Encode(bits, context->count, 8);
/* Pad out to 56 mod 64. */
idx = (context->count[0] >> 3) & 0x3f;
padLen = (idx < 56) ? (56 - idx) : (120 - idx);
__md5_Update(context, PADDING, padLen);
/* Append length (before padding) */
__md5_Update(context, bits, 8);
}
/*
* MD5 finalization. Ends an MD5 message-digest operation, writing the
* the message digest and zeroizing the context.
*/
static void __md5_Final(unsigned char digest[16], struct MD5Context *context)
{
/* Do padding. */
__md5_Pad(context);
/* Store state in digest */
__md5_Encode(digest, context->state, 16);
/* Zeroize sensitive information. */
memset(context, 0, sizeof(*context));
}
/* MD5 basic transformation. Transforms state based on block. */
static void __md5_Transform(uint32_t state[4], const unsigned char block[64])
{
uint32_t a, b, c, d, x[16];
#if MD5_SIZE_OVER_SPEED > 1
uint32_t temp;
const unsigned char *ps;
static const unsigned char S[] = {
7, 12, 17, 22,
5, 9, 14, 20,
4, 11, 16, 23,
6, 10, 15, 21
};
#endif /* MD5_SIZE_OVER_SPEED > 1 */
#if MD5_SIZE_OVER_SPEED > 0
const uint32_t *pc;
const unsigned char *pp;
int i;
static const uint32_t C[] = {
/* round 1 */
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
/* round 2 */
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
/* round 3 */
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
/* round 4 */
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
static const unsigned char P[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
};
#endif /* MD5_SIZE_OVER_SPEED > 0 */
__md5_Decode(x, block, 64);
a = state[0]; b = state[1]; c = state[2]; d = state[3];
#if MD5_SIZE_OVER_SPEED > 2
pc = C; pp = P; ps = S - 4;
for (i = 0; i < 64; i++) {
if ((i & 0x0f) == 0) ps += 4;
temp = a;
switch (i>>4) {
case 0:
temp += F(b, c, d);
break;
case 1:
temp += G(b, c, d);
break;
case 2:
temp += H(b, c, d);
break;
case 3:
temp += I(b, c, d);
break;
}
temp += x[*pp++] + *pc++;
temp = ROTATE_LEFT(temp, ps[i & 3]);
temp += b;
a = d; d = c; c = b; b = temp;
}
#elif MD5_SIZE_OVER_SPEED > 1
pc = C; pp = P; ps = S;
/* Round 1 */
for (i = 0; i < 16; i++) {
FF(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
temp = d; d = c; c = b; b = a; a = temp;
}
/* Round 2 */
ps += 4;
for (; i < 32; i++) {
GG(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
temp = d; d = c; c = b; b = a; a = temp;
}
/* Round 3 */
ps += 4;
for (; i < 48; i++) {
HH(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
temp = d; d = c; c = b; b = a; a = temp;
}
/* Round 4 */
ps += 4;
for (; i < 64; i++) {
II(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
temp = d; d = c; c = b; b = a; a = temp;
}
#elif MD5_SIZE_OVER_SPEED > 0
pc = C; pp = P;
/* Round 1 */
for (i = 0; i < 4; i++) {
FF(a, b, c, d, x[*pp], 7, *pc); pp++; pc++;
FF(d, a, b, c, x[*pp], 12, *pc); pp++; pc++;
FF(c, d, a, b, x[*pp], 17, *pc); pp++; pc++;
FF(b, c, d, a, x[*pp], 22, *pc); pp++; pc++;
}
/* Round 2 */
for (i = 0; i < 4; i++) {
GG(a, b, c, d, x[*pp], 5, *pc); pp++; pc++;
GG(d, a, b, c, x[*pp], 9, *pc); pp++; pc++;
GG(c, d, a, b, x[*pp], 14, *pc); pp++; pc++;
GG(b, c, d, a, x[*pp], 20, *pc); pp++; pc++;
}
/* Round 3 */
for (i = 0; i < 4; i++) {
HH(a, b, c, d, x[*pp], 4, *pc); pp++; pc++;
HH(d, a, b, c, x[*pp], 11, *pc); pp++; pc++;
HH(c, d, a, b, x[*pp], 16, *pc); pp++; pc++;
HH(b, c, d, a, x[*pp], 23, *pc); pp++; pc++;
}
/* Round 4 */
for (i = 0; i < 4; i++) {
II(a, b, c, d, x[*pp], 6, *pc); pp++; pc++;
II(d, a, b, c, x[*pp], 10, *pc); pp++; pc++;
II(c, d, a, b, x[*pp], 15, *pc); pp++; pc++;
II(b, c, d, a, x[*pp], 21, *pc); pp++; pc++;
}
#else
/* Round 1 */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
#define S21 5
#define S22 9
#define S23 14
#define S24 20
GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
#define S31 4
#define S32 11
#define S33 16
#define S34 23
HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
#define S41 6
#define S42 10
#define S43 15
#define S44 21
II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
#endif
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
memset(x, 0, sizeof(x));
}
static char*
__md5_to64(char *s, unsigned v, int n)
{
while (--n >= 0) {
*s++ = ascii64[v & 0x3f];
v >>= 6;
}
return s;
}
/*
* UNIX password
*
* Use MD5 for what it is best at...
*/
#define MD5_OUT_BUFSIZE 36
static char *
md5_crypt(char passwd[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned char *salt)
{
const unsigned char *sp, *ep;
char *p;
unsigned char final[17]; /* final[16] exists only to aid in looping */
int sl, pl, i, pw_len;
struct MD5Context ctx, ctx1;
/* Refine the Salt first */
sp = salt;
sp += MD5_MAGIC_LEN;
/* It stops at the first '$', max 8 chars */
for (ep = sp; *ep && *ep != '$' && ep < (sp+8); ep++)
continue;
/* get the length of the true salt */
sl = ep - sp;
__md5_Init(&ctx);
/* The password first, since that is what is most unknown */
pw_len = strlen((char*)pw);
__md5_Update(&ctx, pw, pw_len);
/* Then our magic string */
__md5_Update(&ctx, __md5__magic, MD5_MAGIC_LEN);
/* Then the raw salt */
__md5_Update(&ctx, sp, sl);
/* Then just as many characters of the MD5(pw, salt, pw) */
__md5_Init(&ctx1);
__md5_Update(&ctx1, pw, pw_len);
__md5_Update(&ctx1, sp, sl);
__md5_Update(&ctx1, pw, pw_len);
__md5_Final(final, &ctx1);
for (pl = pw_len; pl > 0; pl -= 16)
__md5_Update(&ctx, final, pl > 16 ? 16 : pl);
/* Don't leave anything around in vm they could use. */
//TODO: the above comment seems to be wrong. final is used later.
memset(final, 0, sizeof(final));
/* Then something really weird... */
for (i = pw_len; i; i >>= 1) {
__md5_Update(&ctx, ((i & 1) ? final : (const unsigned char *) pw), 1);
}
/* Now make the output string */
passwd[0] = '$';
passwd[1] = '1';
passwd[2] = '$';
strncpy(passwd + 3, (char*)sp, sl);
passwd[sl + 3] = '$';
__md5_Final(final, &ctx);
/*
* and now, just to make sure things don't run too fast
* On a 60 Mhz Pentium this takes 34 msec, so you would
* need 30 seconds to build a 1000 entry dictionary...
*/
for (i = 0; i < 1000; i++) {
__md5_Init(&ctx1);
if (i & 1)
__md5_Update(&ctx1, pw, pw_len);
else
__md5_Update(&ctx1, final, 16);
if (i % 3)
__md5_Update(&ctx1, sp, sl);
if (i % 7)
__md5_Update(&ctx1, pw, pw_len);
if (i & 1)
__md5_Update(&ctx1, final, 16);
else
__md5_Update(&ctx1, pw, pw_len);
__md5_Final(final, &ctx1);
}
p = passwd + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */
/* Add 5*4+2 = 22 bytes of hash, + NUL byte. */
final[16] = final[5];
for (i = 0; i < 5; i++) {
unsigned l = (final[i] << 16) | (final[i+6] << 8) | final[i+12];
p = __md5_to64(p, l, 4);
}
p = __md5_to64(p, final[11], 2);
*p = '\0';
/* Don't leave anything around in vm they could use. */
memset(final, 0, sizeof(final));
return passwd;
}
#undef MD5_SIZE_OVER_SPEED
#undef MD5_MAGIC_STR
#undef MD5_MAGIC_LEN
#undef __md5_Encode
#undef __md5_Decode
#undef F
#undef G
#undef H
#undef I
#undef ROTATE_LEFT
#undef FF
#undef GG
#undef HH
#undef II
#undef S11
#undef S12
#undef S13
#undef S14
#undef S21
#undef S22
#undef S23
#undef S24
#undef S31
#undef S32
#undef S33
#undef S34
#undef S41
#undef S42
#undef S43
#undef S44

104
package/ead/src/sha1.c Normal file
View File

@ -0,0 +1,104 @@
/*
* SHA transform algorithm, originally taken from code written by
* Peter Gutmann, and placed in the public domain.
*/
static uint32_t
rol32(uint32_t word, int shift)
{
return (word << shift) | (word >> (32 - shift));
}
/* The SHA f()-functions. */
#define f1(x,y,z) (z ^ (x & (y ^ z))) /* x ? y : z */
#define f2(x,y,z) (x ^ y ^ z) /* XOR */
#define f3(x,y,z) ((x & y) + (z & (x ^ y))) /* majority */
/* The SHA Mysterious Constants */
#define K1 0x5A827999L /* Rounds 0-19: sqrt(2) * 2^30 */
#define K2 0x6ED9EBA1L /* Rounds 20-39: sqrt(3) * 2^30 */
#define K3 0x8F1BBCDCL /* Rounds 40-59: sqrt(5) * 2^30 */
#define K4 0xCA62C1D6L /* Rounds 60-79: sqrt(10) * 2^30 */
/**
* sha_transform - single block SHA1 transform
*
* @digest: 160 bit digest to update
* @data: 512 bits of data to hash
* @W: 80 words of workspace (see note)
*
* This function generates a SHA1 digest for a single 512-bit block.
* Be warned, it does not handle padding and message digest, do not
* confuse it with the full FIPS 180-1 digest algorithm for variable
* length messages.
*
* Note: If the hash is security sensitive, the caller should be sure
* to clear the workspace. This is left to the caller to avoid
* unnecessary clears between chained hashing operations.
*/
static void sha_transform(uint32_t *digest, const unsigned char *in, uint32_t *W)
{
uint32_t a, b, c, d, e, t, i;
for (i = 0; i < 16; i++) {
int ofs = 4 * i;
/* word load/store may be unaligned here, so use bytes instead */
W[i] =
(in[ofs+0] << 24) |
(in[ofs+1] << 16) |
(in[ofs+2] << 8) |
in[ofs+3];
}
for (i = 0; i < 64; i++)
W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
a = digest[0];
b = digest[1];
c = digest[2];
d = digest[3];
e = digest[4];
for (i = 0; i < 20; i++) {
t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i];
e = d; d = c; c = rol32(b, 30); b = a; a = t;
}
for (; i < 40; i ++) {
t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i];
e = d; d = c; c = rol32(b, 30); b = a; a = t;
}
for (; i < 60; i ++) {
t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i];
e = d; d = c; c = rol32(b, 30); b = a; a = t;
}
for (; i < 80; i ++) {
t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i];
e = d; d = c; c = rol32(b, 30); b = a; a = t;
}
digest[0] += a;
digest[1] += b;
digest[2] += c;
digest[3] += d;
digest[4] += e;
}
/**
* sha_init - initialize the vectors for a SHA1 digest
* @buf: vector to initialize
*/
static void sha_init(uint32_t *buf)
{
buf[0] = 0x67452301;
buf[1] = 0xefcdab89;
buf[2] = 0x98badcfe;
buf[3] = 0x10325476;
buf[4] = 0xc3d2e1f0;
}

View File

@ -0,0 +1,28 @@
AUTOMAKE_OPTIONS = foreign no-dependencies
noinst_HEADERS = t_client.h t_pwd.h t_server.h t_sha.h \
bn.h bn_lcl.h bn_prime.h t_defines.h t_read.h
include_HEADERS = tinysrp.h
lib_LIBRARIES = libtinysrp.a
CFLAGS = -O2 @signed@
libtinysrp_a_SOURCES = \
tinysrp.c t_client.c t_getconf.c t_conv.c t_getpass.c t_sha.c t_math.c \
t_misc.c t_pw.c t_read.c t_server.c t_truerand.c \
bn_add.c bn_ctx.c bn_div.c bn_exp.c bn_mul.c bn_word.c bn_asm.c bn_lib.c \
bn_shift.c bn_sqr.c
noinst_PROGRAMS = srvtest clitest
srvtest_SOURCES = srvtest.c
clitest_SOURCES = clitest.c
bin_PROGRAMS = tconf tphrase
tconf_SOURCES = tconf.c t_conf.c
tphrase_SOURCES = tphrase.c
LDADD = libtinysrp.a
EXTRA_DIST = tpasswd Notes

View File

@ -0,0 +1,481 @@
# Makefile.in generated automatically by automake 1.4a from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_FLAG =
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
LN_S = @LN_S@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
signed = @signed@
AUTOMAKE_OPTIONS = foreign no-dependencies
noinst_HEADERS = t_client.h t_pwd.h t_server.h t_sha.h bn.h bn_lcl.h bn_prime.h t_defines.h t_read.h
include_HEADERS = tinysrp.h
lib_LIBRARIES = libtinysrp.a
CFLAGS = -O2 @signed@
libtinysrp_a_SOURCES = tinysrp.c t_client.c t_getconf.c t_conv.c t_getpass.c t_sha.c t_math.c t_misc.c t_pw.c t_read.c t_server.c t_truerand.c bn_add.c bn_ctx.c bn_div.c bn_exp.c bn_mul.c bn_word.c bn_asm.c bn_lib.c bn_shift.c bn_sqr.c
noinst_PROGRAMS = srvtest clitest
srvtest_SOURCES = srvtest.c
clitest_SOURCES = clitest.c
bin_PROGRAMS = tconf tphrase
tconf_SOURCES = tconf.c t_conf.c
tphrase_SOURCES = tphrase.c
LDADD = libtinysrp.a
EXTRA_DIST = tpasswd Notes
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(lib_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir) -I.
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libtinysrp_a_LIBADD =
libtinysrp_a_OBJECTS = tinysrp.o t_client.o t_getconf.o t_conv.o \
t_getpass.o t_sha.o t_math.o t_misc.o t_pw.o t_read.o t_server.o \
t_truerand.o bn_add.o bn_ctx.o bn_div.o bn_exp.o bn_mul.o bn_word.o \
bn_asm.o bn_lib.o bn_shift.o bn_sqr.o
AR = ar
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
tconf_OBJECTS = tconf.o t_conf.o
tconf_LDADD = $(LDADD)
tconf_DEPENDENCIES = libtinysrp.a
tconf_LDFLAGS =
tphrase_OBJECTS = tphrase.o
tphrase_LDADD = $(LDADD)
tphrase_DEPENDENCIES = libtinysrp.a
tphrase_LDFLAGS =
srvtest_OBJECTS = srvtest.o
srvtest_LDADD = $(LDADD)
srvtest_DEPENDENCIES = libtinysrp.a
srvtest_LDFLAGS =
clitest_OBJECTS = clitest.o
clitest_LDADD = $(LDADD)
clitest_DEPENDENCIES = libtinysrp.a
clitest_LDFLAGS =
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
HEADERS = $(include_HEADERS) $(noinst_HEADERS)
DIST_COMMON = ./stamp-h.in Makefile.am Makefile.in acconfig.h \
acinclude.m4 aclocal.m4 config.h.in configure configure.in install-sh \
missing mkinstalldirs
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
GZIP_ENV = --best
SOURCES = $(libtinysrp_a_SOURCES) $(tconf_SOURCES) $(tphrase_SOURCES) $(srvtest_SOURCES) $(clitest_SOURCES)
OBJECTS = $(libtinysrp_a_OBJECTS) $(tconf_OBJECTS) $(tphrase_OBJECTS) $(srvtest_OBJECTS) $(clitest_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): configure.in acinclude.m4
cd $(srcdir) && $(ACLOCAL)
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
config.h: stamp-h
@if test ! -f $@; then \
rm -f stamp-h; \
$(MAKE) stamp-h; \
else :; fi
stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES= CONFIG_HEADERS=config.h \
$(SHELL) ./config.status
@echo timestamp > stamp-h 2> /dev/null
$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
@if test ! -f $@; then \
rm -f $(srcdir)/stamp-h.in; \
$(MAKE) $(srcdir)/stamp-h.in; \
else :; fi
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
cd $(top_srcdir) && $(AUTOHEADER)
@echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
mostlyclean-hdr:
clean-hdr:
distclean-hdr:
-rm -f config.h
maintainer-clean-hdr:
mostlyclean-libLIBRARIES:
clean-libLIBRARIES:
-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
distclean-libLIBRARIES:
maintainer-clean-libLIBRARIES:
install-libLIBRARIES: $(lib_LIBRARIES)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(libdir)
@list='$(lib_LIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \
$(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \
else :; fi; \
done
@$(POST_INSTALL)
@list='$(lib_LIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(RANLIB) $(DESTDIR)$(libdir)/$$p"; \
$(RANLIB) $(DESTDIR)$(libdir)/$$p; \
else :; fi; \
done
uninstall-libLIBRARIES:
@$(NORMAL_UNINSTALL)
list='$(lib_LIBRARIES)'; for p in $$list; do \
rm -f $(DESTDIR)$(libdir)/$$p; \
done
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
libtinysrp.a: $(libtinysrp_a_OBJECTS) $(libtinysrp_a_DEPENDENCIES)
-rm -f libtinysrp.a
$(AR) cru libtinysrp.a $(libtinysrp_a_OBJECTS) $(libtinysrp_a_LIBADD)
$(RANLIB) libtinysrp.a
mostlyclean-binPROGRAMS:
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
distclean-binPROGRAMS:
maintainer-clean-binPROGRAMS:
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
$(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
list='$(bin_PROGRAMS)'; for p in $$list; do \
rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
done
mostlyclean-noinstPROGRAMS:
clean-noinstPROGRAMS:
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
distclean-noinstPROGRAMS:
maintainer-clean-noinstPROGRAMS:
tconf: $(tconf_OBJECTS) $(tconf_DEPENDENCIES)
@rm -f tconf
$(LINK) $(tconf_LDFLAGS) $(tconf_OBJECTS) $(tconf_LDADD) $(LIBS)
tphrase: $(tphrase_OBJECTS) $(tphrase_DEPENDENCIES)
@rm -f tphrase
$(LINK) $(tphrase_LDFLAGS) $(tphrase_OBJECTS) $(tphrase_LDADD) $(LIBS)
srvtest: $(srvtest_OBJECTS) $(srvtest_DEPENDENCIES)
@rm -f srvtest
$(LINK) $(srvtest_LDFLAGS) $(srvtest_OBJECTS) $(srvtest_LDADD) $(LIBS)
clitest: $(clitest_OBJECTS) $(clitest_DEPENDENCIES)
@rm -f clitest
$(LINK) $(clitest_LDFLAGS) $(clitest_OBJECTS) $(clitest_LDADD) $(LIBS)
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(includedir)
@list='$(include_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p"; \
$(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
list='$(include_HEADERS)'; for p in $$list; do \
rm -f $(DESTDIR)$(includedir)/$$p; \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) dist
-rm -rf $(distdir)
@banner="$(distdir).tar.gz is ready for distribution"; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
all-recursive-am: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
install-exec-am: install-libLIBRARIES install-binPROGRAMS
install-exec: install-exec-am
install-data-am: install-includeHEADERS
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am: uninstall-libLIBRARIES uninstall-binPROGRAMS \
uninstall-includeHEADERS
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS) config.h
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
installdirs:
$(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir) \
$(DESTDIR)$(includedir)
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-hdr mostlyclean-libLIBRARIES \
mostlyclean-compile mostlyclean-binPROGRAMS \
mostlyclean-noinstPROGRAMS mostlyclean-tags \
mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-hdr clean-libLIBRARIES clean-compile clean-binPROGRAMS \
clean-noinstPROGRAMS clean-tags clean-generic \
mostlyclean-am
clean: clean-am
distclean-am: distclean-hdr distclean-libLIBRARIES distclean-compile \
distclean-binPROGRAMS distclean-noinstPROGRAMS \
distclean-tags distclean-generic clean-am
distclean: distclean-am
-rm -f config.status
maintainer-clean-am: maintainer-clean-hdr maintainer-clean-libLIBRARIES \
maintainer-clean-compile maintainer-clean-binPROGRAMS \
maintainer-clean-noinstPROGRAMS maintainer-clean-tags \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
-rm -f config.status
.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
mostlyclean-libLIBRARIES distclean-libLIBRARIES clean-libLIBRARIES \
maintainer-clean-libLIBRARIES uninstall-libLIBRARIES \
install-libLIBRARIES mostlyclean-compile distclean-compile \
clean-compile maintainer-clean-compile mostlyclean-binPROGRAMS \
distclean-binPROGRAMS clean-binPROGRAMS maintainer-clean-binPROGRAMS \
uninstall-binPROGRAMS install-binPROGRAMS mostlyclean-noinstPROGRAMS \
distclean-noinstPROGRAMS clean-noinstPROGRAMS \
maintainer-clean-noinstPROGRAMS uninstall-includeHEADERS \
install-includeHEADERS tags mostlyclean-tags distclean-tags clean-tags \
maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \
installcheck-am installcheck all-recursive-am install-exec-am \
install-exec install-data-am install-data install-am install \
uninstall-am uninstall all-redirect all-am all installdirs \
mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,110 @@
t_* stuff is from the srp 1.7.1 dist
bn_* stuff is from openssl 0.9.6
(The 7 in libtinysrp's version number reflects the srp version.)
Licensing and copyright for srp and openssl are as indicated in the relevant
source files. Everything else here is GPL, including the tinysrp protocol.
Changelog since initial release:
0.7.4 more robust terminal modes in t_getpass
a potential buffer overflow in tinysrp
0.7.5 uninitialized pointer bug in tconf
Changes from the base srp and openssl distributions:
I've removed everything that's not needed for client/server operations, and
all the bn_* stuff that's only used for prime generation has been moved to
t_conf.c, which isn't part of the library anymore. Also, all the routines
used for passphrase file maintenance have been moved to tphrase.c.
The library has been optimized (a bit) for space instead of speed. Since
authentication is usually only done once, this isn't a big problem. Modern
CPUs are plenty fast for this task, and even 100 MHz CPUs are fine. If you
really need the speed, get the regular distributions.
Note that if the server sends the client a prime that the client doesn't
know about, the client MUST test for primality. Since this is pretty
expensive, and takes 30 seconds on a 100 MHz machine, and uses lots of code,
I've removed that ability from the client. So only KNOWN primes can be
used. You can still generate new ones with tconf, but you have to install
them in the table of known primes (pre_params) in t_getconf.c that's common
to the client and server, and recompile. The configuration file is gone.
The default prime (the last entry in the table) is 1024 bits; there are
others with more bits but they will be correspondingly slower.
The default tpasswd file (which is an ascii file that may be editted with a
regular text editor) contains two users: moo (passphrase "glub glub") and
"new user" (passphrase "this is a test"). Passphrases may be added or
changed with tphrase; you can also change the user's prime. To delete a
user, edit the tpasswd file and remove that line. The tpasswd file's
default name is DEFAULT_PASSWD in t_pwd.h. Note that you can't change a
user's username by editting the file: the username is encoded in the
verifier. If you change a username you must set a new passphrase with
tphrase.
Here is an example session, using the supplied srvtest and clitest. First,
start both programs in different windows, and enter the user names. Normally,
the client would send the username to the server. Server lines are marked
with S>, client lines with C>.
S> % srvtest
S> Enter username: moo
S> index (to client): 5
S> salt (to client): 19AI0Hc9jEkdFc
C> % clitest
C> Enter username: moo
C> Enter index (from server): 5
C> Enter salt (from server): 19AI0Hc9jEkdFc
The server reports the index and salt values used for that user. They
are sent over the network to the client. (Simulate this by cutting and
pasting from one window to the other.)
C> A (to server): 5wCDXRxLIv/zLazYfKupV/OY3BlhTZuJ71wVgI0HcL1kSJEpkMuWF.xEz/BV2wlJl7vk5Eoz9KMS1ccnaatsVP5D6CBm7UA.yVB59EQFN0dNBirvX29NAFdtdMsMppo5tHRy987XjJWrWSLpeibq6emr.gP8nYyX75GQqSiMY1j
C> Enter password:
S> Enter A (from client): 5wCDXRxLIv/zLazYfKupV/OY3BlhTZuJ71wVgI0HcL1kSJEpkMuWF.xEz/BV2wlJl7vk5Eoz9KMS1ccnaatsVP5D6CBm7UA.yVB59EQFN0dNBirvX29NAFdtdMsMppo5tHRy987XjJWrWSLpeibq6emr.gP8nYyX75GQqSiMY1j
Now the client calculates A and sends it to the server, and while the
server is munching on that, the client gets the password from the user.
S> B (to client): 9dcCpulxQAbaDXI0NHWY6B.QH6B9fsoXs/x/5SCNBNJm/6H6bYfbVrwNmdquhLZjYMvpcgGc2mBYqL77RNfw1kVQo17//GfsByECBIjRnrAn02ffX9Y/llJcfscAQiii0hyZhJf9PT5wE7pC7WUjIgSqckIZ0JLNDbSr7fJcrgw
S> Session key: ebbcf3a45c968defdcfff6e144ad8d4f5412167c9716e79cbf7cacfe18257947ad46fa5d6418a1fd
The server now calculates B and sends it to the client. The session key
is not sent -- it is a shared secret that can be used for encryption.
C> Enter B (from server): 9dcCpulxQAbaDXI0NHWY6B.QH6B9fsoXs/x/5SCNBNJm/6H6bYfbVrwNmdquhLZjYMvpcgGc2mBYqL77RNfw1kVQo17//GfsByECBIjRnrAn02ffX9Y/llJcfscAQiii0hyZhJf9PT5wE7pC7WUjIgSqckIZ0JLNDbSr7fJcrgw
C> Session key: ebbcf3a45c968defdcfff6e144ad8d4f5412167c9716e79cbf7cacfe18257947ad46fa5d6418a1fd
C> Response (to server): b9ea99094a176c4be28eb469982066cc7146d180
The client uses the B value to calculate its own copy of the shared secret
session key, and sends a response to the server proving that it does know
the correct key.
S> Enter response (from client): b9ea99094a176c4be28eb469982066cc7146d180
S> Authentication successful.
S> Response (to client): cd46c839ccad2d0c76f3ca1905ae8ceda8d1c1dc
The server authenticates the client. (You're in!)
C> Enter server response: cd46c839ccad2d0c76f3ca1905ae8ceda8d1c1dc
C> Server authentication successful.
The client authenticates the server (prevents server spoofing in the case
where the session key isn't used to encrypt the channel -- a spoofed server
might just respond with random values and _pretend_ to authenticate the
client; but the spoofed server won't know the session key and this check
catches that).
Final note:
Remember that many breaches of security involve buggy software, such as
servers susceptible to buffer overflow exploits that totally bypass any
passphrase, secure or not. If an attacker roots your client, or the server,
no form of authentication will work. Consider MAC-based schemes if this
worries you.

View File

@ -0,0 +1,9 @@
#undef SHA1HANDSOFF
#undef POSIX_TERMIOS
#undef POSIX_SIGTYPE
#undef VERSION
#undef volatile

View File

@ -0,0 +1,26 @@
dnl
dnl check for signal type
dnl
dnl AC_RETSIGTYPE isn't quite right, but almost.
dnl
define(TYPE_SIGNAL,[
AC_MSG_CHECKING([POSIX signal handlers])
AC_CACHE_VAL(cv_has_posix_signals,
[AC_TRY_COMPILE(
[#include <sys/types.h>
#include <signal.h>
#ifdef signal
#undef signal
#endif
extern void (*signal ()) ();], [],
cv_has_posix_signals=yes, cv_has_posix_signals=no)])
AC_MSG_RESULT($cv_has_posix_signals)
if test $cv_has_posix_signals = yes; then
AC_DEFINE(RETSIGTYPE, void) AC_DEFINE(POSIX_SIGTYPE)
else
if test $ac_cv_type_signal = void; then
AC_DEFINE(RETSIGTYPE, void)
else
AC_DEFINE(RETSIGTYPE, int)
fi
fi])dnl

156
package/ead/src/tinysrp/aclocal.m4 vendored Normal file
View File

@ -0,0 +1,156 @@
dnl aclocal.m4 generated automatically by aclocal 1.4a
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
dnl
dnl check for signal type
dnl
dnl AC_RETSIGTYPE isn't quite right, but almost.
dnl
define(TYPE_SIGNAL,[
AC_MSG_CHECKING([POSIX signal handlers])
AC_CACHE_VAL(cv_has_posix_signals,
[AC_TRY_COMPILE(
[#include <sys/types.h>
#include <signal.h>
#ifdef signal
#undef signal
#endif
extern void (*signal ()) ();], [],
cv_has_posix_signals=yes, cv_has_posix_signals=no)])
AC_MSG_RESULT($cv_has_posix_signals)
if test $cv_has_posix_signals = yes; then
AC_DEFINE(RETSIGTYPE, void) AC_DEFINE(POSIX_SIGTYPE)
else
if test $ac_cv_type_signal = void; then
AC_DEFINE(RETSIGTYPE, void)
else
AC_DEFINE(RETSIGTYPE, int)
fi
fi])dnl
# Like AC_CONFIG_HEADER, but automatically create stamp file.
AC_DEFUN(AM_CONFIG_HEADER,
[AC_PREREQ([2.12])
AC_CONFIG_HEADER([$1])
dnl When config.status generates a header, we must update the stamp-h file.
dnl This file resides in the same directory as the config header
dnl that is generated. We must strip everything past the first ":",
dnl and everything past the last "/".
AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
<<am_indx=1
for am_file in <<$1>>; do
case " <<$>>CONFIG_HEADERS " in
*" <<$>>am_file "*<<)>>
echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
;;
esac
am_indx=`expr "<<$>>am_indx" + 1`
done<<>>dnl>>)
changequote([,]))])
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AC_PROG_INSTALL])
dnl We require 2.13 because we rely on SHELL being computed by configure.
AC_PREREQ([2.13])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])

View File

@ -0,0 +1,471 @@
/* crypto/bn/bn.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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.]
*/
#ifndef HEADER_BN_H
#define HEADER_BN_H
#include <stdio.h> /* FILE */
#include "config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef VMS
#undef BN_LLONG /* experimental, so far... */
#endif
#undef BN_MUL_COMBA
#undef BN_SQR_COMBA
#undef BN_RECURSION
#undef RECP_MUL_MOD
#undef MONT_MUL_MOD
#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == 8
# if SIZEOF_LONG == 4
# define THIRTY_TWO_BIT
# else
# define SIXTY_FOUR_BIT_LONG
# endif
#else
# if SIZEOF_LONG == 4
# define THIRTY_TWO_BIT
# endif
#endif
#undef BN_LLONG
/* assuming long is 64bit - this is the DEC Alpha
* unsigned long long is only 64 bits :-(, don't define
* BN_LLONG for the DEC Alpha */
#ifdef SIXTY_FOUR_BIT_LONG
#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_MASK (0xffffffffffffffffffffffffffffffffLL)
#define BN_MASK2 (0xffffffffffffffffL)
#define BN_MASK2l (0xffffffffL)
#define BN_MASK2h (0xffffffff00000000L)
#define BN_MASK2h1 (0xffffffff80000000L)
#define BN_TBIT (0x8000000000000000L)
#define BN_DEC_CONV (10000000000000000000UL)
#define BN_DEC_FMT1 "%lu"
#define BN_DEC_FMT2 "%019lu"
#define BN_DEC_NUM 19
#endif
/* This is where the long long data type is 64 bits, but long is 32.
* For machines where there are 64bit registers, this is the mode to use.
* IRIX, on R4000 and above should use this mode, along with the relevant
* assembler code :-). Do NOT define BN_LLONG.
*/
#ifdef SIXTY_FOUR_BIT
#undef BN_LLONG
#undef BN_ULLONG
#define BN_ULONG unsigned long long
#define BN_LONG long long
#define BN_BITS 128
#define BN_BYTES 8
#define BN_BITS2 64
#define BN_BITS4 32
#define BN_MASK2 (0xffffffffffffffffLL)
#define BN_MASK2l (0xffffffffL)
#define BN_MASK2h (0xffffffff00000000LL)
#define BN_MASK2h1 (0xffffffff80000000LL)
#define BN_TBIT (0x8000000000000000LL)
#define BN_DEC_CONV (10000000000000000000LL)
#define BN_DEC_FMT1 "%llu"
#define BN_DEC_FMT2 "%019llu"
#define BN_DEC_NUM 19
#endif
#ifdef THIRTY_TWO_BIT
#if defined(WIN32) && !defined(__GNUC__)
#define BN_ULLONG unsigned _int64
#else
#define BN_ULLONG unsigned long long
#endif
#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
#ifdef WIN32
/* VC++ doesn't like the LL suffix */
#define BN_MASK (0xffffffffffffffffL)
#else
#define BN_MASK (0xffffffffffffffffLL)
#endif
#define BN_MASK2 (0xffffffffL)
#define BN_MASK2l (0xffff)
#define BN_MASK2h1 (0xffff8000L)
#define BN_MASK2h (0xffff0000L)
#define BN_TBIT (0x80000000L)
#define BN_DEC_CONV (1000000000L)
#define BN_DEC_FMT1 "%lu"
#define BN_DEC_FMT2 "%09lu"
#define BN_DEC_NUM 9
#endif
#ifdef SIXTEEN_BIT
#ifndef BN_DIV2W
#define BN_DIV2W
#endif
#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_MASK (0xffffffff)
#define BN_MASK2 (0xffff)
#define BN_MASK2l (0xff)
#define BN_MASK2h1 (0xff80)
#define BN_MASK2h (0xff00)
#define BN_TBIT (0x8000)
#define BN_DEC_CONV (100000)
#define BN_DEC_FMT1 "%u"
#define BN_DEC_FMT2 "%05u"
#define BN_DEC_NUM 5
#endif
#ifdef EIGHT_BIT
#ifndef BN_DIV2W
#define BN_DIV2W
#endif
#define BN_ULLONG unsigned short
#define BN_ULONG unsigned char
#define BN_LONG char
#define BN_BITS 16
#define BN_BYTES 1
#define BN_BITS2 8
#define BN_BITS4 4
#define BN_MASK (0xffff)
#define BN_MASK2 (0xff)
#define BN_MASK2l (0xf)
#define BN_MASK2h1 (0xf8)
#define BN_MASK2h (0xf0)
#define BN_TBIT (0x80)
#define BN_DEC_CONV (100)
#define BN_DEC_FMT1 "%u"
#define BN_DEC_FMT2 "%02u"
#define BN_DEC_NUM 2
#endif
#define BN_DEFAULT_BITS 1280
#ifdef BIGNUM
#undef BIGNUM
#endif
#define BN_FLG_MALLOCED 0x01
#define BN_FLG_STATIC_DATA 0x02
#define BN_FLG_FREE 0x8000 /* used for debuging */
#define BN_set_flags(b,n) ((b)->flags|=(n))
#define BN_get_flags(b,n) ((b)->flags&(n))
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 dmax; /* Size of the d array. */
int neg; /* one if the number is negative */
int flags;
} BIGNUM;
/* Used for temp variables */
#define BN_CTX_NUM 12
#define BN_CTX_NUM_POS 12
typedef struct bignum_ctx
{
int tos;
BIGNUM bn[BN_CTX_NUM];
int flags;
int depth;
int pos[BN_CTX_NUM_POS];
int too_many;
} BN_CTX;
/* Used for montgomery multiplication */
typedef struct bn_mont_ctx_st
{
int ri; /* number of bits in R */
BIGNUM RR; /* used to convert to montgomery form */
BIGNUM N; /* The modulus */
BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1
* (Ni is only stored for bignum algorithm) */
BN_ULONG n0; /* least significant word of Ni */
int flags;
} BN_MONT_CTX;
/* Used for reciprocal division/mod functions
* It cannot be shared between threads
*/
typedef struct bn_recp_ctx_st
{
BIGNUM N; /* the divisor */
BIGNUM Nr; /* the reciprocal */
int num_bits;
int shift;
int flags;
} BN_RECP_CTX;
#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\
r,a,&((mont)->RR),(mont),ctx)
#define BN_prime_checks 0 /* default: select number of iterations
based on the size of the number */
/* number of Miller-Rabin iterations for an error rate of less than 2^-80
* for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook
* of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
* original paper: Damgaard, Landrock, Pomerance: Average case error estimates
* for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */
#define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \
(b) >= 850 ? 3 : \
(b) >= 650 ? 4 : \
(b) >= 550 ? 5 : \
(b) >= 450 ? 6 : \
(b) >= 400 ? 7 : \
(b) >= 350 ? 8 : \
(b) >= 300 ? 9 : \
(b) >= 250 ? 12 : \
(b) >= 200 ? 15 : \
(b) >= 150 ? 18 : \
/* b >= 100 */ 27)
#define BN_num_bytes(a) ((BN_num_bits(a)+7)/8)
#define BN_is_word(a,w) (((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w)))
#define BN_is_zero(a) (((a)->top == 0) || BN_is_word(a,0))
#define BN_is_one(a) (BN_is_word((a),1))
#define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1))
#define BN_one(a) (BN_set_word((a),1))
#define BN_zero(a) (BN_set_word((a),0))
BIGNUM *BN_value_one(void);
char * BN_options(void);
BN_CTX *BN_CTX_new(void);
void BN_CTX_init(BN_CTX *c);
void BN_CTX_free(BN_CTX *c);
void BN_CTX_start(BN_CTX *ctx);
BIGNUM *BN_CTX_get(BN_CTX *ctx);
void BN_CTX_end(BN_CTX *ctx);
int BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom);
int BN_num_bits(const BIGNUM *a);
int BN_num_bits_word(BN_ULONG);
BIGNUM *BN_new(void);
void BN_init(BIGNUM *);
void BN_clear_free(BIGNUM *a);
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
BIGNUM *BN_bin2bn(const unsigned char *s,int len,BIGNUM *ret);
int BN_bn2bin(const BIGNUM *a, unsigned char *to);
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
BN_CTX *ctx);
int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
int BN_sqr(BIGNUM *r, BIGNUM *a,BN_CTX *ctx);
BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
int BN_mul_word(BIGNUM *a, BN_ULONG w);
int BN_add_word(BIGNUM *a, BN_ULONG w);
int BN_sub_word(BIGNUM *a, BN_ULONG w);
int BN_set_word(BIGNUM *a, BN_ULONG w);
BN_ULONG BN_get_word(BIGNUM *a);
int BN_cmp(const BIGNUM *a, const BIGNUM *b);
void BN_free(BIGNUM *a);
int BN_is_bit_set(const BIGNUM *a, int n);
int BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
int BN_lshift1(BIGNUM *r, BIGNUM *a);
int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p,BN_CTX *ctx);
int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
const BIGNUM *m,BN_CTX *ctx);
int BN_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m,BN_CTX *ctx);
int BN_mask_bits(BIGNUM *a,int n);
int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
int BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx);
int BN_rshift(BIGNUM *r, BIGNUM *a, int n);
int BN_rshift1(BIGNUM *r, BIGNUM *a);
void BN_clear(BIGNUM *a);
BIGNUM *BN_dup(const BIGNUM *a);
int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
int BN_set_bit(BIGNUM *a, int n);
int BN_clear_bit(BIGNUM *a, int n);
int BN_gcd(BIGNUM *r,BIGNUM *in_a,BIGNUM *in_b,BN_CTX *ctx);
BIGNUM *BN_mod_inverse(BIGNUM *ret,BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,BIGNUM *add,
BIGNUM *rem,void (*callback)(int,int,void *),void *cb_arg);
int BN_is_prime(const BIGNUM *p,int nchecks,
void (*callback)(int,int,void *),
BN_CTX *ctx,void *cb_arg);
int BN_is_prime_fasttest(const BIGNUM *p,int nchecks,
void (*callback)(int,int,void *),BN_CTX *ctx,void *cb_arg,
int do_trial_division);
BN_MONT_CTX *BN_MONT_CTX_new(void );
void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
int BN_mod_mul_montgomery(BIGNUM *r,BIGNUM *a,BIGNUM *b,BN_MONT_CTX *mont,
BN_CTX *ctx);
int BN_from_montgomery(BIGNUM *r,BIGNUM *a,BN_MONT_CTX *mont,BN_CTX *ctx);
void BN_MONT_CTX_free(BN_MONT_CTX *mont);
int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *modulus,BN_CTX *ctx);
BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
void BN_set_params(int mul,int high,int low,int mont);
int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
void BN_RECP_CTX_init(BN_RECP_CTX *recp);
BN_RECP_CTX *BN_RECP_CTX_new(void);
void BN_RECP_CTX_free(BN_RECP_CTX *recp);
int BN_RECP_CTX_set(BN_RECP_CTX *recp,const BIGNUM *rdiv,BN_CTX *ctx);
int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y,
BN_RECP_CTX *recp,BN_CTX *ctx);
int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx);
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m,
BN_RECP_CTX *recp, BN_CTX *ctx);
/* library internal functions */
#define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\
(a):bn_expand2((a),(bits)/BN_BITS2+1))
#define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words)))
BIGNUM *bn_expand2(BIGNUM *a, int words);
#define bn_fix_top(a) \
{ \
BN_ULONG *ftl; \
if ((a)->top > 0) \
{ \
for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
if (*(ftl--)) break; \
} \
}
BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
void bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num);
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
BN_ULONG bn_add_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num);
BN_ULONG bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num);
#ifdef BN_DEBUG
void bn_dump1(FILE *o, const char *a, BN_ULONG *b,int n);
# define bn_print(a) {fprintf(stderr, #a "="); BN_print_fp(stderr,a); \
fprintf(stderr,"\n");}
# define bn_dump(a,n) bn_dump1(stderr,#a,a,n);
#else
# define bn_print(a)
# define bn_dump(a,b)
#endif
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
*/
/* Error codes for the BN functions. */
/* Function codes. */
#define BN_F_BN_CTX_GET 116
#define BN_F_BN_CTX_NEW 106
#define BN_F_BN_DIV 107
#define BN_F_BN_EXPAND2 108
#define BN_F_BN_MOD_EXP2_MONT 118
#define BN_F_BN_MOD_EXP_MONT 109
#define BN_F_BN_MOD_EXP_MONT_WORD 117
#define BN_F_BN_MOD_INVERSE 110
#define BN_F_BN_MOD_MUL_RECIPROCAL 111
#define BN_F_BN_MPI2BN 112
#define BN_F_BN_NEW 113
#define BN_F_BN_RAND 114
#define BN_F_BN_USUB 115
/* Reason codes. */
#define BN_R_ARG2_LT_ARG3 100
#define BN_R_BAD_RECIPROCAL 101
#define BN_R_CALLED_WITH_EVEN_MODULUS 102
#define BN_R_DIV_BY_ZERO 103
#define BN_R_ENCODING_ERROR 104
#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105
#define BN_R_INVALID_LENGTH 106
#define BN_R_NOT_INITIALIZED 107
#define BN_R_NO_INVERSE 108
#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,305 @@
/* crypto/bn/bn_add.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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 "bn_lcl.h"
/* r can == a or b */
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
const BIGNUM *tmp;
bn_check_top(a);
bn_check_top(b);
/* a + b a+b
* a + -b a-b
* -a + b b-a
* -a + -b -(a+b)
*/
if (a->neg ^ b->neg)
{
/* only one is negative */
if (a->neg)
{ tmp=a; a=b; b=tmp; }
/* we are now a - b */
if (BN_ucmp(a,b) < 0)
{
if (!BN_usub(r,b,a)) return(0);
r->neg=1;
}
else
{
if (!BN_usub(r,a,b)) return(0);
r->neg=0;
}
return(1);
}
if (a->neg) /* both are neg */
r->neg=1;
else
r->neg=0;
if (!BN_uadd(r,a,b)) return(0);
return(1);
}
/* unsigned add of b to a, r must be large enough */
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
register int i;
int max,min;
BN_ULONG *ap,*bp,*rp,carry,t1;
const BIGNUM *tmp;
bn_check_top(a);
bn_check_top(b);
if (a->top < b->top)
{ tmp=a; a=b; b=tmp; }
max=a->top;
min=b->top;
if (bn_wexpand(r,max+1) == NULL)
return(0);
r->top=max;
ap=a->d;
bp=b->d;
rp=r->d;
carry=0;
carry=bn_add_words(rp,ap,bp,min);
rp+=min;
ap+=min;
bp+=min;
i=min;
if (carry)
{
while (i < max)
{
i++;
t1= *(ap++);
if ((*(rp++)=(t1+1)&BN_MASK2) >= t1)
{
carry=0;
break;
}
}
if ((i >= max) && carry)
{
*(rp++)=1;
r->top++;
}
}
if (rp != ap)
{
for (; i<max; i++)
*(rp++)= *(ap++);
}
/* memcpy(rp,ap,sizeof(*ap)*(max-i));*/
return(1);
}
/* unsigned subtraction of b from a, a must be larger than b. */
int BN_usub(BIGNUM *r, const BIGNUM *a, const 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
bn_check_top(a);
bn_check_top(b);
if (a->top < b->top) /* hmm... should not be happening */
{
return(0);
}
max=a->top;
min=b->top;
if (bn_wexpand(r,max) == NULL) return(0);
ap=a->d;
bp=b->d;
rp=r->d;
#if 1
carry=0;
for (i=0; i<min; i++)
{
t1= *(ap++);
t2= *(bp++);
if (carry)
{
carry=(t1 <= t2);
t1=(t1-t2-1)&BN_MASK2;
}
else
{
carry=(t1 < t2);
t1=(t1-t2)&BN_MASK2;
}
#if defined(IRIX_CC_BUG) && !defined(LINT)
dummy=t1;
#endif
*(rp++)=t1&BN_MASK2;
}
#else
carry=bn_sub_words(rp,ap,bp,min);
ap+=min;
bp+=min;
rp+=min;
i=min;
#endif
if (carry) /* subtracted */
{
while (i < max)
{
i++;
t1= *(ap++);
t2=(t1-1)&BN_MASK2;
*(rp++)=t2;
if (t1 > t2) break;
}
}
#if 0
memcpy(rp,ap,sizeof(*rp)*(max-i));
#else
if (rp != ap)
{
for (;;)
{
if (i++ >= max) break;
rp[0]=ap[0];
if (i++ >= max) break;
rp[1]=ap[1];
if (i++ >= max) break;
rp[2]=ap[2];
if (i++ >= max) break;
rp[3]=ap[3];
rp+=4;
ap+=4;
}
}
#endif
r->top=max;
bn_fix_top(r);
return(1);
}
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
int max;
int add=0,neg=0;
const BIGNUM *tmp;
bn_check_top(a);
bn_check_top(b);
/* a - b a-b
* a - -b a+b
* -a - b -(a+b)
* -a - -b b-a
*/
if (a->neg)
{
if (b->neg)
{ tmp=a; a=b; b=tmp; }
else
{ add=1; neg=1; }
}
else
{
if (b->neg) { add=1; neg=0; }
}
if (add)
{
if (!BN_uadd(r,a,b)) return(0);
r->neg=neg;
return(1);
}
/* We are actually doing a - b :-) */
max=(a->top > b->top)?a->top:b->top;
if (bn_wexpand(r,max) == NULL) return(0);
if (BN_ucmp(a,b) < 0)
{
if (!BN_usub(r,b,a)) return(0);
r->neg=1;
}
else
{
if (!BN_usub(r,a,b)) return(0);
r->neg=0;
}
return(1);
}

View File

@ -0,0 +1,382 @@
/* crypto/bn/bn_asm.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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.]
*/
#ifndef BN_DEBUG
# undef NDEBUG /* avoid conflicting definitions */
# define NDEBUG
#endif
#include <stdio.h>
#include <assert.h>
#include "bn_lcl.h"
#if defined(BN_LLONG) || defined(BN_UMULT_HIGH)
BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
{
BN_ULONG c1=0;
assert(num >= 0);
if (num <= 0) return(c1);
while (num&~3)
{
mul_add(rp[0],ap[0],w,c1);
mul_add(rp[1],ap[1],w,c1);
mul_add(rp[2],ap[2],w,c1);
mul_add(rp[3],ap[3],w,c1);
ap+=4; rp+=4; num-=4;
}
if (num)
{
mul_add(rp[0],ap[0],w,c1); if (--num==0) return c1;
mul_add(rp[1],ap[1],w,c1); if (--num==0) return c1;
mul_add(rp[2],ap[2],w,c1); return c1;
}
return(c1);
}
BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
{
BN_ULONG c1=0;
assert(num >= 0);
if (num <= 0) return(c1);
while (num&~3)
{
mul(rp[0],ap[0],w,c1);
mul(rp[1],ap[1],w,c1);
mul(rp[2],ap[2],w,c1);
mul(rp[3],ap[3],w,c1);
ap+=4; rp+=4; num-=4;
}
if (num)
{
mul(rp[0],ap[0],w,c1); if (--num == 0) return c1;
mul(rp[1],ap[1],w,c1); if (--num == 0) return c1;
mul(rp[2],ap[2],w,c1);
}
return(c1);
}
void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n)
{
assert(n >= 0);
if (n <= 0) return;
while (n&~3)
{
sqr(r[0],r[1],a[0]);
sqr(r[2],r[3],a[1]);
sqr(r[4],r[5],a[2]);
sqr(r[6],r[7],a[3]);
a+=4; r+=8; n-=4;
}
if (n)
{
sqr(r[0],r[1],a[0]); if (--n == 0) return;
sqr(r[2],r[3],a[1]); if (--n == 0) return;
sqr(r[4],r[5],a[2]);
}
}
#else /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */
BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
{
BN_ULONG c=0;
BN_ULONG bl,bh;
assert(num >= 0);
if (num <= 0) return((BN_ULONG)0);
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);
}
BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
{
BN_ULONG carry=0;
BN_ULONG bl,bh;
assert(num >= 0);
if (num <= 0) return((BN_ULONG)0);
bl=LBITS(w);
bh=HBITS(w);
for (;;)
{
mul(rp[0],ap[0],bl,bh,carry);
if (--num == 0) break;
mul(rp[1],ap[1],bl,bh,carry);
if (--num == 0) break;
mul(rp[2],ap[2],bl,bh,carry);
if (--num == 0) break;
mul(rp[3],ap[3],bl,bh,carry);
if (--num == 0) break;
ap+=4;
rp+=4;
}
return(carry);
}
void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n)
{
assert(n >= 0);
if (n <= 0) return;
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;
}
}
#endif /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */
#if defined(BN_LLONG) && defined(BN_DIV2W)
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
{
return((BN_ULONG)(((((BN_ULLONG)h)<<BN_BITS2)|l)/(BN_ULLONG)d));
}
#else
/* Divide h,l by d and return the result. */
/* I need to test this some more :-( */
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
{
BN_ULONG dh,dl,q,ret=0,th,tl,t;
int i,count=2;
if (d == 0) return(BN_MASK2);
i=BN_num_bits_word(d);
assert((i == BN_BITS2) || (h > (BN_ULONG)1<<i));
i=BN_BITS2-i;
if (h >= d) h-=d;
if (i)
{
d<<=i;
h=(h<<i)|(l>>(BN_BITS2-i));
l<<=i;
}
dh=(d&BN_MASK2h)>>BN_BITS4;
dl=(d&BN_MASK2l);
for (;;)
{
if ((h>>BN_BITS4) == dh)
q=BN_MASK2l;
else
q=h/dh;
th=q*dh;
tl=dl*q;
for (;;)
{
t=h-th;
if ((t&BN_MASK2h) ||
((tl) <= (
(t<<BN_BITS4)|
((l&BN_MASK2h)>>BN_BITS4))))
break;
q--;
th-=dh;
tl-=dl;
}
t=(tl>>BN_BITS4);
tl=(tl<<BN_BITS4)&BN_MASK2h;
th+=t;
if (l < tl) th++;
l-=tl;
if (h < th)
{
h+=d;
q--;
}
h-=th;
if (--count == 0) break;
ret=q<<BN_BITS4;
h=((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2;
l=(l&BN_MASK2l)<<BN_BITS4;
}
ret|=q;
return(ret);
}
#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */
#ifdef BN_LLONG
BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
{
BN_ULLONG ll=0;
assert(n >= 0);
if (n <= 0) return((BN_ULONG)0);
for (;;)
{
ll+=(BN_ULLONG)a[0]+b[0];
r[0]=(BN_ULONG)ll&BN_MASK2;
ll>>=BN_BITS2;
if (--n <= 0) break;
ll+=(BN_ULLONG)a[1]+b[1];
r[1]=(BN_ULONG)ll&BN_MASK2;
ll>>=BN_BITS2;
if (--n <= 0) break;
ll+=(BN_ULLONG)a[2]+b[2];
r[2]=(BN_ULONG)ll&BN_MASK2;
ll>>=BN_BITS2;
if (--n <= 0) break;
ll+=(BN_ULLONG)a[3]+b[3];
r[3]=(BN_ULONG)ll&BN_MASK2;
ll>>=BN_BITS2;
if (--n <= 0) break;
a+=4;
b+=4;
r+=4;
}
return((BN_ULONG)ll);
}
#else /* !BN_LLONG */
BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
{
BN_ULONG c,l,t;
assert(n >= 0);
if (n <= 0) return((BN_ULONG)0);
c=0;
for (;;)
{
t=a[0];
t=(t+c)&BN_MASK2;
c=(t < c);
l=(t+b[0])&BN_MASK2;
c+=(l < t);
r[0]=l;
if (--n <= 0) break;
t=a[1];
t=(t+c)&BN_MASK2;
c=(t < c);
l=(t+b[1])&BN_MASK2;
c+=(l < t);
r[1]=l;
if (--n <= 0) break;
t=a[2];
t=(t+c)&BN_MASK2;
c=(t < c);
l=(t+b[2])&BN_MASK2;
c+=(l < t);
r[2]=l;
if (--n <= 0) break;
t=a[3];
t=(t+c)&BN_MASK2;
c=(t < c);
l=(t+b[3])&BN_MASK2;
c+=(l < t);
r[3]=l;
if (--n <= 0) break;
a+=4;
b+=4;
r+=4;
}
return((BN_ULONG)c);
}
#endif /* !BN_LLONG */

View File

@ -0,0 +1,142 @@
/* crypto/bn/bn_ctx.c */
/* Written by Ulf Moeller for the OpenSSL project. */
/* ====================================================================
* Copyright (c) 1998-2000 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
* openssl-core@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).
*
*/
#ifndef BN_CTX_DEBUG
# undef NDEBUG /* avoid conflicting definitions */
# define NDEBUG
#endif
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <bn.h>
BN_CTX *BN_CTX_new(void)
{
BN_CTX *ret;
ret=(BN_CTX *)malloc(sizeof(BN_CTX));
if (ret == NULL)
{
return(NULL);
}
BN_CTX_init(ret);
ret->flags=BN_FLG_MALLOCED;
return(ret);
}
void BN_CTX_init(BN_CTX *ctx)
{
int i;
ctx->tos = 0;
ctx->flags = 0;
ctx->depth = 0;
ctx->too_many = 0;
for (i = 0; i < BN_CTX_NUM; i++)
BN_init(&(ctx->bn[i]));
}
void BN_CTX_free(BN_CTX *ctx)
{
int i;
if (ctx == NULL) return;
assert(ctx->depth == 0);
for (i=0; i < BN_CTX_NUM; i++)
BN_clear_free(&(ctx->bn[i]));
if (ctx->flags & BN_FLG_MALLOCED)
free(ctx);
}
void BN_CTX_start(BN_CTX *ctx)
{
if (ctx->depth < BN_CTX_NUM_POS)
ctx->pos[ctx->depth] = ctx->tos;
ctx->depth++;
}
BIGNUM *BN_CTX_get(BN_CTX *ctx)
{
if (ctx->depth > BN_CTX_NUM_POS || ctx->tos >= BN_CTX_NUM)
{
if (!ctx->too_many)
{
/* disable error code until BN_CTX_end is called: */
ctx->too_many = 1;
}
return NULL;
}
return (&(ctx->bn[ctx->tos++]));
}
void BN_CTX_end(BN_CTX *ctx)
{
if (ctx == NULL) return;
assert(ctx->depth > 0);
if (ctx->depth == 0)
/* should never happen, but we can tolerate it if not in
* debug mode (could be a 'goto err' in the calling function
* before BN_CTX_start was reached) */
BN_CTX_start(ctx);
ctx->too_many = 0;
ctx->depth--;
if (ctx->depth < BN_CTX_NUM_POS)
ctx->tos = ctx->pos[ctx->depth];
}

View File

@ -0,0 +1,378 @@
/* crypto/bn/bn_div.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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 "bn_lcl.h"
#define NO_ASM
/* The old slow way */
#if 0
int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
BN_CTX *ctx)
{
int i,nm,nd;
int ret = 0;
BIGNUM *D;
bn_check_top(m);
bn_check_top(d);
if (BN_is_zero(d))
{
return(0);
}
if (BN_ucmp(m,d) < 0)
{
if (rem != NULL)
{ if (BN_copy(rem,m) == NULL) return(0); }
if (dv != NULL) BN_zero(dv);
return(1);
}
BN_CTX_start(ctx);
D = BN_CTX_get(ctx);
if (dv == NULL) dv = BN_CTX_get(ctx);
if (rem == NULL) rem = BN_CTX_get(ctx);
if (D == NULL || dv == NULL || rem == NULL)
goto end;
nd=BN_num_bits(d);
nm=BN_num_bits(m);
if (BN_copy(D,d) == NULL) goto end;
if (BN_copy(rem,m) == NULL) goto end;
/* 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);
bn_wexpand(dv,1);
dv->top=1;
if (!BN_lshift(D,D,nm-nd)) goto end;
for (i=nm-nd; i>=0; i--)
{
if (!BN_lshift1(dv,dv)) goto end;
if (BN_ucmp(rem,D) >= 0)
{
dv->d[0]|=1;
if (!BN_usub(rem,rem,D)) goto end;
}
/* CAN IMPROVE (and have now :=) */
if (!BN_rshift1(D,D)) goto end;
}
rem->neg=BN_is_zero(rem)?0:m->neg;
dv->neg=m->neg^d->neg;
ret = 1;
end:
BN_CTX_end(ctx);
return(ret);
}
#else
#if !defined(NO_ASM) && !defined(NO_INLINE_ASM) && !defined(PEDANTIC) && !defined(BN_DIV3W)
# if defined(__GNUC__) && __GNUC__>=2
# if defined(__i386)
/*
* There were two reasons for implementing this template:
* - GNU C generates a call to a function (__udivdi3 to be exact)
* in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
* understand why...);
* - divl doesn't only calculate quotient, but also leaves
* remainder in %edx which we can definitely use here:-)
*
* <appro@fy.chalmers.se>
*/
# define bn_div_words(n0,n1,d0) \
({ asm volatile ( \
"divl %4" \
: "=a"(q), "=d"(rem) \
: "a"(n1), "d"(n0), "g"(d0) \
: "cc"); \
q; \
})
# define REMAINDER_IS_ALREADY_CALCULATED
# endif /* __<cpu> */
# endif /* __GNUC__ */
#endif /* NO_ASM */
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
BN_CTX *ctx)
{
int norm_shift,i,j,loop;
BIGNUM *tmp,wnum,*snum,*sdiv,*res;
BN_ULONG *resp,*wnump;
BN_ULONG d0,d1;
int num_n,div_n;
bn_check_top(num);
bn_check_top(divisor);
if (BN_is_zero(divisor))
{
return(0);
}
if (BN_ucmp(num,divisor) < 0)
{
if (rm != NULL)
{ if (BN_copy(rm,num) == NULL) return(0); }
if (dv != NULL) BN_zero(dv);
return(1);
}
BN_CTX_start(ctx);
tmp=BN_CTX_get(ctx);
tmp->neg=0;
snum=BN_CTX_get(ctx);
sdiv=BN_CTX_get(ctx);
if (dv == NULL)
res=BN_CTX_get(ctx);
else res=dv;
if (res == NULL) goto err;
/* First we normalise the numbers */
norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2);
BN_lshift(sdiv,divisor,norm_shift);
sdiv->neg=0;
norm_shift+=BN_BITS2;
BN_lshift(snum,num,norm_shift);
snum->neg=0;
div_n=sdiv->top;
num_n=snum->top;
loop=num_n-div_n;
/* Lets setup a 'window' into snum
* This is the part that corresponds to the current
* 'area' being divided */
BN_init(&wnum);
wnum.d= &(snum->d[loop]);
wnum.top= div_n;
wnum.dmax= snum->dmax+1; /* a bit of a lie */
/* Get the top 2 words of sdiv */
/* i=sdiv->top; */
d0=sdiv->d[div_n-1];
d1=(div_n == 1)?0:sdiv->d[div_n-2];
/* pointer to the 'top' of snum */
wnump= &(snum->d[num_n-1]);
/* Setup to 'res' */
res->neg= (num->neg^divisor->neg);
if (!bn_wexpand(res,(loop+1))) goto err;
res->top=loop;
resp= &(res->d[loop-1]);
/* space for temp */
if (!bn_wexpand(tmp,(div_n+1))) goto err;
if (BN_ucmp(&wnum,sdiv) >= 0)
{
if (!BN_usub(&wnum,&wnum,sdiv)) goto err;
*resp=1;
res->d[res->top-1]=1;
}
else
res->top--;
resp--;
for (i=0; i<loop-1; i++)
{
BN_ULONG q,l0;
#ifdef BN_DIV3W
q=bn_div_3_words(wnump,d1,d0);
#else
BN_ULONG n0,n1,rem=0;
n0=wnump[0];
n1=wnump[-1];
if (n0 == d0)
q=BN_MASK2;
else /* n0 < d0 */
{
#ifdef BN_LLONG
BN_ULLONG t2;
#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0);
#else
q=bn_div_words(n0,n1,d0);
#endif
#ifndef REMAINDER_IS_ALREADY_CALCULATED
/*
* rem doesn't have to be BN_ULLONG. The least we
* know it's less that d0, isn't it?
*/
rem=(n1-q*d0)&BN_MASK2;
#endif
t2=(BN_ULLONG)d1*q;
for (;;)
{
if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2]))
break;
q--;
rem += d0;
if (rem < d0) break; /* don't let rem overflow */
t2 -= d1;
}
#else /* !BN_LLONG */
BN_ULONG t2l,t2h,ql,qh;
q=bn_div_words(n0,n1,d0);
#ifndef REMAINDER_IS_ALREADY_CALCULATED
rem=(n1-q*d0)&BN_MASK2;
#endif
#ifdef BN_UMULT_HIGH
t2l = d1 * q;
t2h = BN_UMULT_HIGH(d1,q);
#else
t2l=LBITS(d1); t2h=HBITS(d1);
ql =LBITS(q); qh =HBITS(q);
mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */
#endif
for (;;)
{
if ((t2h < rem) ||
((t2h == rem) && (t2l <= wnump[-2])))
break;
q--;
rem += d0;
if (rem < d0) break; /* don't let rem overflow */
if (t2l < d1) t2h--; t2l -= d1;
}
#endif /* !BN_LLONG */
}
#endif /* !BN_DIV3W */
l0=bn_mul_words(tmp->d,sdiv->d,div_n,q);
wnum.d--; wnum.top++;
tmp->d[div_n]=l0;
for (j=div_n+1; j>0; j--)
if (tmp->d[j-1]) break;
tmp->top=j;
j=wnum.top;
BN_sub(&wnum,&wnum,tmp);
snum->top=snum->top+wnum.top-j;
if (wnum.neg)
{
q--;
j=wnum.top;
BN_add(&wnum,&wnum,sdiv);
snum->top+=wnum.top-j;
}
*(resp--)=q;
wnump--;
}
if (rm != NULL)
{
BN_rshift(rm,snum,norm_shift);
rm->neg=num->neg;
}
BN_CTX_end(ctx);
return(1);
err:
BN_CTX_end(ctx);
return(0);
}
#endif
/* rem != m */
int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
{
#if 0 /* The old slow way */
int i,nm,nd;
BIGNUM *dv;
if (BN_ucmp(m,d) < 0)
return((BN_copy(rem,m) == NULL)?0:1);
BN_CTX_start(ctx);
dv=BN_CTX_get(ctx);
if (!BN_copy(rem,m)) goto err;
nm=BN_num_bits(rem);
nd=BN_num_bits(d);
if (!BN_lshift(dv,d,nm-nd)) goto err;
for (i=nm-nd; i>=0; i--)
{
if (BN_cmp(rem,dv) >= 0)
{
if (!BN_sub(rem,rem,dv)) goto err;
}
if (!BN_rshift1(dv,dv)) goto err;
}
BN_CTX_end(ctx);
return(1);
err:
BN_CTX_end(ctx);
return(0);
#else
return(BN_div(NULL,rem,m,d,ctx));
#endif
}

View File

@ -0,0 +1,395 @@
/* crypto/bn/bn_exp.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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.]
*/
/* ====================================================================
* Copyright (c) 1998-2000 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
* openssl-core@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).
*
*/
#include <stdio.h>
#include "bn_lcl.h"
#define TABLE_SIZE 32
/* slow but works */
int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
{
BIGNUM *t;
int r=0;
bn_check_top(a);
bn_check_top(b);
bn_check_top(m);
BN_CTX_start(ctx);
if ((t = BN_CTX_get(ctx)) == NULL) goto err;
if (a == b)
{ if (!BN_sqr(t,a,ctx)) goto err; }
else
{ if (!BN_mul(t,a,b,ctx)) goto err; }
if (!BN_mod(ret,t,m,ctx)) goto err;
r=1;
err:
BN_CTX_end(ctx);
return(r);
}
int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
BN_CTX *ctx)
{
int ret;
bn_check_top(a);
bn_check_top(p);
bn_check_top(m);
#ifdef MONT_MUL_MOD
/* I have finally been able to take out this pre-condition of
* the top bit being set. It was caused by an error in BN_div
* with negatives. There was also another problem when for a^b%m
* a >= m. eay 07-May-97 */
/* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */
if (BN_is_odd(m))
{
if (a->top == 1)
{
BN_ULONG A = a->d[0];
ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL);
}
else
ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL);
}
else
#endif
#ifdef RECP_MUL_MOD
{ ret=BN_mod_exp_recp(r,a,p,m,ctx); }
#else
{ ret=BN_mod_exp_simple(r,a,p,m,ctx); }
#endif
return(ret);
}
#ifdef RECP_MUL_MOD
int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx)
{
int i,j,bits,ret=0,wstart,wend,window,wvalue;
int start=1,ts=0;
BIGNUM *aa;
BIGNUM val[TABLE_SIZE];
BN_RECP_CTX recp;
bits=BN_num_bits(p);
if (bits == 0)
{
BN_one(r);
return(1);
}
BN_CTX_start(ctx);
if ((aa = BN_CTX_get(ctx)) == NULL) goto err;
BN_RECP_CTX_init(&recp);
if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
BN_init(&(val[0]));
ts=1;
if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */
window = BN_window_bits_for_exponent_size(bits);
if (window > 1)
{
if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx))
goto err; /* 2 */
j=1<<(window-1);
for (i=1; i<j; i++)
{
BN_init(&val[i]);
if (!BN_mod_mul_reciprocal(&(val[i]),&(val[i-1]),aa,&recp,ctx))
goto err;
}
ts=i;
}
start=1; /* This is used to avoid multiplication etc
* when there is only the value '1' in the
* buffer. */
wvalue=0; /* The 'value' of the window */
wstart=bits-1; /* The top bit of the window */
wend=0; /* The bottom bit of the window */
if (!BN_one(r)) goto err;
for (;;)
{
if (BN_is_bit_set(p,wstart) == 0)
{
if (!start)
if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
goto err;
if (wstart == 0) break;
wstart--;
continue;
}
/* We now have wstart on a 'set' bit, we now need to work out
* how bit a window to do. To do this we need to scan
* forward until the last set bit before the end of the
* window */
j=wstart;
wvalue=1;
wend=0;
for (i=1; i<window; i++)
{
if (wstart-i < 0) break;
if (BN_is_bit_set(p,wstart-i))
{
wvalue<<=(i-wend);
wvalue|=1;
wend=i;
}
}
/* wend is the size of the current window */
j=wend+1;
/* add the 'bytes above' */
if (!start)
for (i=0; i<j; i++)
{
if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
if (!BN_mod_mul_reciprocal(r,r,&(val[wvalue>>1]),&recp,ctx))
goto err;
/* move the 'window' down further */
wstart-=wend+1;
wvalue=0;
start=0;
if (wstart < 0) break;
}
ret=1;
err:
BN_CTX_end(ctx);
for (i=0; i<ts; i++)
BN_clear_free(&(val[i]));
BN_RECP_CTX_free(&recp);
return(ret);
}
#else
/* The old fallback, simple version :-) */
int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx)
{
int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0;
int start=1;
BIGNUM *d;
BIGNUM val[TABLE_SIZE];
bits=BN_num_bits(p);
if (bits == 0)
{
BN_one(r);
return(1);
}
BN_CTX_start(ctx);
if ((d = BN_CTX_get(ctx)) == NULL) goto err;
BN_init(&(val[0]));
ts=1;
if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */
window = BN_window_bits_for_exponent_size(bits);
if (window > 1)
{
if (!BN_mod_mul(d,&(val[0]),&(val[0]),m,ctx))
goto err; /* 2 */
j=1<<(window-1);
for (i=1; i<j; i++)
{
BN_init(&(val[i]));
if (!BN_mod_mul(&(val[i]),&(val[i-1]),d,m,ctx))
goto err;
}
ts=i;
}
start=1; /* This is used to avoid multiplication etc
* when there is only the value '1' in the
* buffer. */
wvalue=0; /* The 'value' of the window */
wstart=bits-1; /* The top bit of the window */
wend=0; /* The bottom bit of the window */
if (!BN_one(r)) goto err;
for (;;)
{
if (BN_is_bit_set(p,wstart) == 0)
{
if (!start)
if (!BN_mod_mul(r,r,r,m,ctx))
goto err;
if (wstart == 0) break;
wstart--;
continue;
}
/* We now have wstart on a 'set' bit, we now need to work out
* how bit a window to do. To do this we need to scan
* forward until the last set bit before the end of the
* window */
j=wstart;
wvalue=1;
wend=0;
for (i=1; i<window; i++)
{
if (wstart-i < 0) break;
if (BN_is_bit_set(p,wstart-i))
{
wvalue<<=(i-wend);
wvalue|=1;
wend=i;
}
}
/* wend is the size of the current window */
j=wend+1;
/* add the 'bytes above' */
if (!start)
for (i=0; i<j; i++)
{
if (!BN_mod_mul(r,r,r,m,ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
if (!BN_mod_mul(r,r,&(val[wvalue>>1]),m,ctx))
goto err;
/* move the 'window' down further */
wstart-=wend+1;
wvalue=0;
start=0;
if (wstart < 0) break;
}
ret=1;
err:
BN_CTX_end(ctx);
for (i=0; i<ts; i++)
BN_clear_free(&(val[i]));
return(ret);
}
#endif

View File

@ -0,0 +1,419 @@
/* crypto/bn/bn_lcl.h */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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.]
*/
/* ====================================================================
* Copyright (c) 1998-2000 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
* openssl-core@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).
*
*/
#ifndef HEADER_BN_LCL_H
#define HEADER_BN_LCL_H
#include <bn.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
*
*
* For window size 'w' (w >= 2) and a random 'b' bits exponent,
* the number of multiplications is a constant plus on average
*
* 2^(w-1) + (b-w)/(w+1);
*
* here 2^(w-1) is for precomputing the table (we actually need
* entries only for windows that have the lowest bit set), and
* (b-w)/(w+1) is an approximation for the expected number of
* w-bit windows, not counting the first one.
*
* Thus we should use
*
* w >= 6 if b > 671
* w = 5 if 671 > b > 239
* w = 4 if 239 > b > 79
* w = 3 if 79 > b > 23
* w <= 2 if 23 > b
*
* (with draws in between). Very small exponents are often selected
* with low Hamming weight, so we use w = 1 for b <= 23.
*/
#if 1
#define BN_window_bits_for_exponent_size(b) \
((b) > 671 ? 6 : \
(b) > 239 ? 5 : \
(b) > 79 ? 4 : \
(b) > 23 ? 3 : 1)
#else
/* Old SSLeay/OpenSSL table.
* Maximum window size was 5, so this table differs for b==1024;
* but it coincides for other interesting values (b==160, b==512).
*/
#define BN_window_bits_for_exponent_size(b) \
((b) > 255 ? 5 : \
(b) > 127 ? 4 : \
(b) > 17 ? 3 : 1)
#endif
/* Pentium pro 16,16,16,32,64 */
/* Alpha 16,16,16,16.64 */
#define BN_MULL_SIZE_NORMAL (16) /* 32 */
#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 less than */
#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */
#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */
#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */
#if !defined(NO_ASM) && !defined(NO_INLINE_ASM) && !defined(PEDANTIC)
/*
* BN_UMULT_HIGH section.
*
* No, I'm not trying to overwhelm you when stating that the
* product of N-bit numbers is 2*N bits wide:-) No, I don't expect
* you to be impressed when I say that if the compiler doesn't
* support 2*N integer type, then you have to replace every N*N
* multiplication with 4 (N/2)*(N/2) accompanied by some shifts
* and additions which unavoidably results in severe performance
* penalties. Of course provided that the hardware is capable of
* producing 2*N result... That's when you normally start
* considering assembler implementation. However! It should be
* pointed out that some CPUs (most notably Alpha, PowerPC and
* upcoming IA-64 family:-) provide *separate* instruction
* calculating the upper half of the product placing the result
* into a general purpose register. Now *if* the compiler supports
* inline assembler, then it's not impossible to implement the
* "bignum" routines (and have the compiler optimize 'em)
* exhibiting "native" performance in C. That's what BN_UMULT_HIGH
* macro is about:-)
*
* <appro@fy.chalmers.se>
*/
# if defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))
# if defined(__DECC)
# include <c_asm.h>
# define BN_UMULT_HIGH(a,b) (BN_ULONG)asm("umulh %a0,%a1,%v0",(a),(b))
# elif defined(__GNUC__)
# define BN_UMULT_HIGH(a,b) ({ \
register BN_ULONG ret; \
asm ("umulh %1,%2,%0" \
: "=r"(ret) \
: "r"(a), "r"(b)); \
ret; })
# endif /* compiler */
# elif defined(_ARCH_PPC) && defined(__64BIT__) && defined(SIXTY_FOUR_BIT_LONG)
# if defined(__GNUC__)
# define BN_UMULT_HIGH(a,b) ({ \
register BN_ULONG ret; \
asm ("mulhdu %0,%1,%2" \
: "=r"(ret) \
: "r"(a), "r"(b)); \
ret; })
# endif /* compiler */
# endif /* cpu */
#endif /* NO_ASM */
/*************************************************************
* Using the long long type
*/
#define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
/* This is used for internal error checking and is not normally used */
#ifdef BN_DEBUG
# include <assert.h>
# define bn_check_top(a) assert ((a)->top >= 0 && (a)->top <= (a)->dmax);
#else
# define bn_check_top(a)
#endif
/* This macro is to add extra stuff for development checking */
#ifdef BN_DEBUG
#define bn_set_max(r) ((r)->max=(r)->top,BN_set_flags((r),BN_FLG_STATIC_DATA))
#else
#define bn_set_max(r)
#endif
/* These macros are used to 'take' a section of a bignum for read only use */
#define bn_set_low(r,a,n) \
{ \
(r)->top=((a)->top > (n))?(n):(a)->top; \
(r)->d=(a)->d; \
(r)->neg=(a)->neg; \
(r)->flags|=BN_FLG_STATIC_DATA; \
bn_set_max(r); \
}
#define bn_set_high(r,a,n) \
{ \
if ((a)->top > (n)) \
{ \
(r)->top=(a)->top-n; \
(r)->d= &((a)->d[n]); \
} \
else \
(r)->top=0; \
(r)->neg=(a)->neg; \
(r)->flags|=BN_FLG_STATIC_DATA; \
bn_set_max(r); \
}
#ifdef BN_LLONG
#define mul_add(r,a,w,c) { \
BN_ULLONG t; \
t=(BN_ULLONG)w * (a) + (r) + (c); \
(r)= Lw(t); \
(c)= Hw(t); \
}
#define mul(r,a,w,c) { \
BN_ULLONG t; \
t=(BN_ULLONG)w * (a) + (c); \
(r)= Lw(t); \
(c)= Hw(t); \
}
#define sqr(r0,r1,a) { \
BN_ULLONG t; \
t=(BN_ULLONG)(a)*(a); \
(r0)=Lw(t); \
(r1)=Hw(t); \
}
#elif defined(BN_UMULT_HIGH)
#define mul_add(r,a,w,c) { \
BN_ULONG high,low,ret,tmp=(a); \
ret = (r); \
high= BN_UMULT_HIGH(w,tmp); \
ret += (c); \
low = (w) * tmp; \
(c) = (ret<(c))?1:0; \
(c) += high; \
ret += low; \
(c) += (ret<low)?1:0; \
(r) = ret; \
}
#define mul(r,a,w,c) { \
BN_ULONG high,low,ret,ta=(a); \
low = (w) * ta; \
high= BN_UMULT_HIGH(w,ta); \
ret = low + (c); \
(c) = high; \
(c) += (ret<low)?1:0; \
(r) = ret; \
}
#define sqr(r0,r1,a) { \
BN_ULONG tmp=(a); \
(r0) = tmp * tmp; \
(r1) = BN_UMULT_HIGH(tmp,tmp); \
}
#else
/*************************************************************
* No long long type
*/
#define LBITS(a) ((a)&BN_MASK2l)
#define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2l)
#define L2HBITS(a) ((BN_ULONG)((a)&BN_MASK2l)<<BN_BITS4)
#define LLBITS(a) ((a)&BN_MASKl)
#define LHBITS(a) (((a)>>BN_BITS2)&BN_MASKl)
#define LL2HBITS(a) ((BN_ULLONG)((a)&BN_MASKl)<<BN_BITS2)
#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=(m+m1)&BN_MASK2; if (m < m1) ht+=L2HBITS(1L); \
ht+=HBITS(m); \
m1=L2HBITS(m); \
lt=(lt+m1)&BN_MASK2; if (lt < m1) ht++; \
(l)=lt; \
(h)=ht; \
}
#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=(l+m)&BN_MASK2; if (l < 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=(l+(c))&BN_MASK2; if (l < (c)) h++; \
(c)=(r); \
l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
(c)=h&BN_MASK2; \
(r)=l; \
}
#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; \
}
#endif /* !BN_LLONG */
void bn_mul_normal(BN_ULONG *r,BN_ULONG *a,int na,BN_ULONG *b,int nb);
void bn_mul_comba8(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
void bn_mul_comba4(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp);
void bn_sqr_comba8(BN_ULONG *r,BN_ULONG *a);
void bn_sqr_comba4(BN_ULONG *r,BN_ULONG *a);
int bn_cmp_words(BN_ULONG *a,BN_ULONG *b,int n);
void bn_mul_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t);
void bn_mul_part_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,
int tn, int n,BN_ULONG *t);
void bn_sqr_recursive(BN_ULONG *r,BN_ULONG *a, int n2, BN_ULONG *t);
void bn_mul_low_normal(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b, int n);
void bn_mul_low_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,
BN_ULONG *t);
void bn_mul_high(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,BN_ULONG *l,int n2,
BN_ULONG *t);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,576 @@
/* crypto/bn/bn_lib.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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.]
*/
#ifndef BN_DEBUG
# undef NDEBUG /* avoid conflicting definitions */
# define NDEBUG
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bn_lcl.h"
const char *BN_version="Big Number";
/* For a 32 bit machine
* 2 - 4 == 128
* 3 - 8 == 256
* 4 - 16 == 512
* 5 - 32 == 1024
* 6 - 64 == 2048
* 7 - 128 == 4096
* 8 - 256 == 8192
*/
static int bn_limit_bits=0;
static int bn_limit_num=8; /* (1<<bn_limit_bits) */
static int bn_limit_bits_low=0;
static int bn_limit_num_low=8; /* (1<<bn_limit_bits_low) */
static int bn_limit_bits_high=0;
static int bn_limit_num_high=8; /* (1<<bn_limit_bits_high) */
static int bn_limit_bits_mont=0;
static int bn_limit_num_mont=8; /* (1<<bn_limit_bits_mont) */
int BN_num_bits_word(BN_ULONG l)
{
static const 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 defined(SIXTY_FOUR_BIT_LONG)
if (l & 0xffffffff00000000L)
{
if (l & 0xffff000000000000L)
{
if (l & 0xff00000000000000L)
{
return(bits[(int)(l>>56)]+56);
}
else return(bits[(int)(l>>48)]+48);
}
else
{
if (l & 0x0000ff0000000000L)
{
return(bits[(int)(l>>40)]+40);
}
else return(bits[(int)(l>>32)]+32);
}
}
else
#else
#ifdef SIXTY_FOUR_BIT
if (l & 0xffffffff00000000LL)
{
if (l & 0xffff000000000000LL)
{
if (l & 0xff00000000000000LL)
{
return(bits[(int)(l>>56)]+56);
}
else return(bits[(int)(l>>48)]+48);
}
else
{
if (l & 0x0000ff0000000000LL)
{
return(bits[(int)(l>>40)]+40);
}
else return(bits[(int)(l>>32)]+32);
}
}
else
#endif
#endif
{
#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
if (l & 0xffff0000L)
{
if (l & 0xff000000L)
return(bits[(int)(l>>24L)]+24);
else return(bits[(int)(l>>16L)]+16);
}
else
#endif
{
#if defined(SIXTEEN_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
if (l & 0xff00L)
return(bits[(int)(l>>8)]+8);
else
#endif
return(bits[(int)(l )] );
}
}
}
int BN_num_bits(const BIGNUM *a)
{
BN_ULONG l;
int i;
bn_check_top(a);
if (a->top == 0) return(0);
l=a->d[a->top-1];
assert(l != 0);
i=(a->top-1)*BN_BITS2;
return(i+BN_num_bits_word(l));
}
void BN_clear_free(BIGNUM *a)
{
int i;
if (a == NULL) return;
if (a->d != NULL)
{
memset(a->d,0,a->dmax*sizeof(a->d[0]));
if (!(BN_get_flags(a,BN_FLG_STATIC_DATA)))
free(a->d);
}
i=BN_get_flags(a,BN_FLG_MALLOCED);
memset(a,0,sizeof(BIGNUM));
if (i)
free(a);
}
void BN_free(BIGNUM *a)
{
if (a == NULL) return;
if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA)))
free(a->d);
a->flags|=BN_FLG_FREE; /* REMOVE? */
if (a->flags & BN_FLG_MALLOCED)
free(a);
}
void BN_init(BIGNUM *a)
{
memset(a,0,sizeof(BIGNUM));
}
BIGNUM *BN_new(void)
{
BIGNUM *ret;
if ((ret=(BIGNUM *)malloc(sizeof(BIGNUM))) == NULL)
{
return(NULL);
}
ret->flags=BN_FLG_MALLOCED;
ret->top=0;
ret->neg=0;
ret->dmax=0;
ret->d=NULL;
return(ret);
}
/* This is an internal function that should not be used in applications.
* It ensures that 'b' has enough room for a 'words' word number number.
* It is mostly used by the various BIGNUM routines. If there is an error,
* NULL is returned. If not, 'b' is returned. */
BIGNUM *bn_expand2(BIGNUM *b, int words)
{
BN_ULONG *A,*a;
const BN_ULONG *B;
int i;
bn_check_top(b);
if (words > b->dmax)
{
bn_check_top(b);
if (BN_get_flags(b,BN_FLG_STATIC_DATA))
{
return(NULL);
}
a=A=(BN_ULONG *)malloc(sizeof(BN_ULONG)*(words+1));
if (A == NULL)
{
return(NULL);
}
#if 1
B=b->d;
/* Check if the previous number needs to be copied */
if (B != NULL)
{
#if 0
/* This lot is an unrolled loop to copy b->top
* BN_ULONGs from B to A
*/
/*
* I have nothing against unrolling but it's usually done for
* several reasons, namely:
* - minimize percentage of decision making code, i.e. branches;
* - avoid cache trashing;
* - make it possible to schedule loads earlier;
* Now let's examine the code below. The cornerstone of C is
* "programmer is always right" and that's what we love it for:-)
* For this very reason C compilers have to be paranoid when it
* comes to data aliasing and assume the worst. Yeah, but what
* does it mean in real life? This means that loop body below will
* be compiled to sequence of loads immediately followed by stores
* as compiler assumes the worst, something in A==B+1 style. As a
* result CPU pipeline is going to starve for incoming data. Secondly
* if A and B happen to share same cache line such code is going to
* cause severe cache trashing. Both factors have severe impact on
* performance of modern CPUs and this is the reason why this
* particular piece of code is #ifdefed away and replaced by more
* "friendly" version found in #else section below. This comment
* also applies to BN_copy function.
*
* <appro@fy.chalmers.se>
*/
for (i=b->top&(~7); i>0; i-=8)
{
A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3];
A[4]=B[4]; A[5]=B[5]; A[6]=B[6]; A[7]=B[7];
A+=8;
B+=8;
}
switch (b->top&7)
{
case 7:
A[6]=B[6];
case 6:
A[5]=B[5];
case 5:
A[4]=B[4];
case 4:
A[3]=B[3];
case 3:
A[2]=B[2];
case 2:
A[1]=B[1];
case 1:
A[0]=B[0];
case 0:
/* I need the 'case 0' entry for utrix cc.
* If the optimizer is turned on, it does the
* switch table by doing
* a=top&7
* a--;
* goto jump_table[a];
* If top is 0, this makes us jump to 0xffffffc
* which is rather bad :-(.
* eric 23-Apr-1998
*/
;
}
#else
for (i=b->top>>2; i>0; i--,A+=4,B+=4)
{
/*
* The fact that the loop is unrolled
* 4-wise is a tribute to Intel. It's
* the one that doesn't have enough
* registers to accomodate more data.
* I'd unroll it 8-wise otherwise:-)
*
* <appro@fy.chalmers.se>
*/
BN_ULONG a0,a1,a2,a3;
a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3];
A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3;
}
switch (b->top&3)
{
case 3: A[2]=B[2];
case 2: A[1]=B[1];
case 1: A[0]=B[0];
case 0: ; /* ultrix cc workaround, see above */
}
#endif
free(b->d);
}
b->d=a;
b->dmax=words;
/* Now need to zero any data between b->top and b->max */
A= &(b->d[b->top]);
for (i=(b->dmax - b->top)>>3; i>0; i--,A+=8)
{
A[0]=0; A[1]=0; A[2]=0; A[3]=0;
A[4]=0; A[5]=0; A[6]=0; A[7]=0;
}
for (i=(b->dmax - b->top)&7; i>0; i--,A++)
A[0]=0;
#else
memset(A,0,sizeof(BN_ULONG)*(words+1));
memcpy(A,b->d,sizeof(b->d[0])*b->top);
b->d=a;
b->max=words;
#endif
/* memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); */
/* { int i; for (i=b->max; i<words+1; i++) p[i]=i;} */
}
return(b);
}
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
{
int i;
BN_ULONG *A;
const BN_ULONG *B;
bn_check_top(b);
if (a == b) return(a);
if (bn_wexpand(a,b->top) == NULL) return(NULL);
#if 1
A=a->d;
B=b->d;
for (i=b->top>>2; i>0; i--,A+=4,B+=4)
{
BN_ULONG a0,a1,a2,a3;
a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3];
A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3;
}
switch (b->top&3)
{
case 3: A[2]=B[2];
case 2: A[1]=B[1];
case 1: A[0]=B[0];
case 0: ; /* ultrix cc workaround, see comments in bn_expand2 */
}
#else
memcpy(a->d,b->d,sizeof(b->d[0])*b->top);
#endif
/* memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/
a->top=b->top;
if ((a->top == 0) && (a->d != NULL))
a->d[0]=0;
a->neg=b->neg;
return(a);
}
int BN_set_word(BIGNUM *a, BN_ULONG w)
{
int i,n;
if (bn_expand(a,sizeof(BN_ULONG)*8) == NULL) return(0);
n=sizeof(BN_ULONG)/BN_BYTES;
a->neg=0;
a->top=0;
a->d[0]=(BN_ULONG)w&BN_MASK2;
if (a->d[0] != 0) a->top=1;
for (i=1; i<n; i++)
{
/* the following is done instead of
* w>>=BN_BITS2 so compilers don't complain
* on builds where sizeof(long) == BN_TYPES */
#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */
w>>=BN_BITS4;
w>>=BN_BITS4;
#else
w=0;
#endif
a->d[i]=(BN_ULONG)w&BN_MASK2;
if (a->d[i] != 0) a->top=i+1;
}
return(1);
}
/* ignore negative */
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i,m;
unsigned int n;
BN_ULONG l;
if (ret == NULL) ret=BN_new();
if (ret == NULL) 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<<8L)| *(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);
return(ret);
}
/* ignore negative */
int BN_bn2bin(const 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);
}
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
BN_ULONG t1,t2,*ap,*bp;
bn_check_top(a);
bn_check_top(b);
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(t1 > t2?1:-1);
}
return(0);
}
int BN_cmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
int gt,lt;
BN_ULONG t1,t2;
if ((a == NULL) || (b == NULL))
{
if (a != NULL)
return(-1);
else if (b != NULL)
return(1);
else
return(0);
}
bn_check_top(a);
bn_check_top(b);
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);
}
int BN_is_bit_set(const BIGNUM *a, int n)
{
int i,j;
if (n < 0) return(0);
i=n/BN_BITS2;
j=n%BN_BITS2;
if (a->top <= i) return(0);
return((a->d[i]&(((BN_ULONG)1)<<j))?1:0);
}

View File

@ -0,0 +1,176 @@
/* crypto/bn/bn_mul.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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 <string.h>
#include "bn_lcl.h"
int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
{
int top,al,bl;
BIGNUM *rr;
int ret = 0;
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
int i;
#endif
#ifdef BN_RECURSION
BIGNUM *t;
int j,k;
#endif
#ifdef BN_COUNT
printf("BN_mul %d * %d\n",a->top,b->top);
#endif
bn_check_top(a);
bn_check_top(b);
bn_check_top(r);
al=a->top;
bl=b->top;
if ((al == 0) || (bl == 0))
{
BN_zero(r);
return(1);
}
top=al+bl;
BN_CTX_start(ctx);
if ((r == a) || (r == b))
{
if ((rr = BN_CTX_get(ctx)) == NULL) goto err;
}
else
rr = r;
rr->neg=a->neg^b->neg;
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
i = al-bl;
#endif
#ifdef BN_MUL_COMBA
if (i == 0)
{
# if 0
if (al == 4)
{
if (bn_wexpand(rr,8) == NULL) goto err;
rr->top=8;
bn_mul_comba4(rr->d,a->d,b->d);
goto end;
}
# endif
if (al == 8)
{
if (bn_wexpand(rr,16) == NULL) goto err;
rr->top=16;
bn_mul_comba8(rr->d,a->d,b->d);
goto end;
}
}
#endif /* BN_MUL_COMBA */
if (bn_wexpand(rr,top) == NULL) goto err;
rr->top=top;
bn_mul_normal(rr->d,a->d,al,b->d,bl);
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
end:
#endif
bn_fix_top(rr);
if (r != rr) BN_copy(r,rr);
ret=1;
err:
BN_CTX_end(ctx);
return(ret);
}
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
{
BN_ULONG *rr;
#ifdef BN_COUNT
printf(" bn_mul_normal %d * %d\n",na,nb);
#endif
if (na < nb)
{
int itmp;
BN_ULONG *ltmp;
itmp=na; na=nb; nb=itmp;
ltmp=a; a=b; b=ltmp;
}
rr= &(r[na]);
rr[0]=bn_mul_words(r,a,na,b[0]);
for (;;)
{
if (--nb <= 0) return;
rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
if (--nb <= 0) return;
rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
if (--nb <= 0) return;
rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
if (--nb <= 0) return;
rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
rr+=4;
r+=4;
b+=4;
}
}

View File

@ -0,0 +1,325 @@
/* Auto generated by bn_prime.pl */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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.]
*/
#ifndef EIGHT_BIT
#define NUMPRIMES 2048
#else
#define NUMPRIMES 54
#endif
static const unsigned int primes[NUMPRIMES]=
{
2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47, 53,
59, 61, 67, 71, 73, 79, 83, 89,
97, 101, 103, 107, 109, 113, 127, 131,
137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223,
227, 229, 233, 239, 241, 251,
#ifndef EIGHT_BIT
257, 263,
269, 271, 277, 281, 283, 293, 307, 311,
313, 317, 331, 337, 347, 349, 353, 359,
367, 373, 379, 383, 389, 397, 401, 409,
419, 421, 431, 433, 439, 443, 449, 457,
461, 463, 467, 479, 487, 491, 499, 503,
509, 521, 523, 541, 547, 557, 563, 569,
571, 577, 587, 593, 599, 601, 607, 613,
617, 619, 631, 641, 643, 647, 653, 659,
661, 673, 677, 683, 691, 701, 709, 719,
727, 733, 739, 743, 751, 757, 761, 769,
773, 787, 797, 809, 811, 821, 823, 827,
829, 839, 853, 857, 859, 863, 877, 881,
883, 887, 907, 911, 919, 929, 937, 941,
947, 953, 967, 971, 977, 983, 991, 997,
1009,1013,1019,1021,1031,1033,1039,1049,
1051,1061,1063,1069,1087,1091,1093,1097,
1103,1109,1117,1123,1129,1151,1153,1163,
1171,1181,1187,1193,1201,1213,1217,1223,
1229,1231,1237,1249,1259,1277,1279,1283,
1289,1291,1297,1301,1303,1307,1319,1321,
1327,1361,1367,1373,1381,1399,1409,1423,
1427,1429,1433,1439,1447,1451,1453,1459,
1471,1481,1483,1487,1489,1493,1499,1511,
1523,1531,1543,1549,1553,1559,1567,1571,
1579,1583,1597,1601,1607,1609,1613,1619,
1621,1627,1637,1657,1663,1667,1669,1693,
1697,1699,1709,1721,1723,1733,1741,1747,
1753,1759,1777,1783,1787,1789,1801,1811,
1823,1831,1847,1861,1867,1871,1873,1877,
1879,1889,1901,1907,1913,1931,1933,1949,
1951,1973,1979,1987,1993,1997,1999,2003,
2011,2017,2027,2029,2039,2053,2063,2069,
2081,2083,2087,2089,2099,2111,2113,2129,
2131,2137,2141,2143,2153,2161,2179,2203,
2207,2213,2221,2237,2239,2243,2251,2267,
2269,2273,2281,2287,2293,2297,2309,2311,
2333,2339,2341,2347,2351,2357,2371,2377,
2381,2383,2389,2393,2399,2411,2417,2423,
2437,2441,2447,2459,2467,2473,2477,2503,
2521,2531,2539,2543,2549,2551,2557,2579,
2591,2593,2609,2617,2621,2633,2647,2657,
2659,2663,2671,2677,2683,2687,2689,2693,
2699,2707,2711,2713,2719,2729,2731,2741,
2749,2753,2767,2777,2789,2791,2797,2801,
2803,2819,2833,2837,2843,2851,2857,2861,
2879,2887,2897,2903,2909,2917,2927,2939,
2953,2957,2963,2969,2971,2999,3001,3011,
3019,3023,3037,3041,3049,3061,3067,3079,
3083,3089,3109,3119,3121,3137,3163,3167,
3169,3181,3187,3191,3203,3209,3217,3221,
3229,3251,3253,3257,3259,3271,3299,3301,
3307,3313,3319,3323,3329,3331,3343,3347,
3359,3361,3371,3373,3389,3391,3407,3413,
3433,3449,3457,3461,3463,3467,3469,3491,
3499,3511,3517,3527,3529,3533,3539,3541,
3547,3557,3559,3571,3581,3583,3593,3607,
3613,3617,3623,3631,3637,3643,3659,3671,
3673,3677,3691,3697,3701,3709,3719,3727,
3733,3739,3761,3767,3769,3779,3793,3797,
3803,3821,3823,3833,3847,3851,3853,3863,
3877,3881,3889,3907,3911,3917,3919,3923,
3929,3931,3943,3947,3967,3989,4001,4003,
4007,4013,4019,4021,4027,4049,4051,4057,
4073,4079,4091,4093,4099,4111,4127,4129,
4133,4139,4153,4157,4159,4177,4201,4211,
4217,4219,4229,4231,4241,4243,4253,4259,
4261,4271,4273,4283,4289,4297,4327,4337,
4339,4349,4357,4363,4373,4391,4397,4409,
4421,4423,4441,4447,4451,4457,4463,4481,
4483,4493,4507,4513,4517,4519,4523,4547,
4549,4561,4567,4583,4591,4597,4603,4621,
4637,4639,4643,4649,4651,4657,4663,4673,
4679,4691,4703,4721,4723,4729,4733,4751,
4759,4783,4787,4789,4793,4799,4801,4813,
4817,4831,4861,4871,4877,4889,4903,4909,
4919,4931,4933,4937,4943,4951,4957,4967,
4969,4973,4987,4993,4999,5003,5009,5011,
5021,5023,5039,5051,5059,5077,5081,5087,
5099,5101,5107,5113,5119,5147,5153,5167,
5171,5179,5189,5197,5209,5227,5231,5233,
5237,5261,5273,5279,5281,5297,5303,5309,
5323,5333,5347,5351,5381,5387,5393,5399,
5407,5413,5417,5419,5431,5437,5441,5443,
5449,5471,5477,5479,5483,5501,5503,5507,
5519,5521,5527,5531,5557,5563,5569,5573,
5581,5591,5623,5639,5641,5647,5651,5653,
5657,5659,5669,5683,5689,5693,5701,5711,
5717,5737,5741,5743,5749,5779,5783,5791,
5801,5807,5813,5821,5827,5839,5843,5849,
5851,5857,5861,5867,5869,5879,5881,5897,
5903,5923,5927,5939,5953,5981,5987,6007,
6011,6029,6037,6043,6047,6053,6067,6073,
6079,6089,6091,6101,6113,6121,6131,6133,
6143,6151,6163,6173,6197,6199,6203,6211,
6217,6221,6229,6247,6257,6263,6269,6271,
6277,6287,6299,6301,6311,6317,6323,6329,
6337,6343,6353,6359,6361,6367,6373,6379,
6389,6397,6421,6427,6449,6451,6469,6473,
6481,6491,6521,6529,6547,6551,6553,6563,
6569,6571,6577,6581,6599,6607,6619,6637,
6653,6659,6661,6673,6679,6689,6691,6701,
6703,6709,6719,6733,6737,6761,6763,6779,
6781,6791,6793,6803,6823,6827,6829,6833,
6841,6857,6863,6869,6871,6883,6899,6907,
6911,6917,6947,6949,6959,6961,6967,6971,
6977,6983,6991,6997,7001,7013,7019,7027,
7039,7043,7057,7069,7079,7103,7109,7121,
7127,7129,7151,7159,7177,7187,7193,7207,
7211,7213,7219,7229,7237,7243,7247,7253,
7283,7297,7307,7309,7321,7331,7333,7349,
7351,7369,7393,7411,7417,7433,7451,7457,
7459,7477,7481,7487,7489,7499,7507,7517,
7523,7529,7537,7541,7547,7549,7559,7561,
7573,7577,7583,7589,7591,7603,7607,7621,
7639,7643,7649,7669,7673,7681,7687,7691,
7699,7703,7717,7723,7727,7741,7753,7757,
7759,7789,7793,7817,7823,7829,7841,7853,
7867,7873,7877,7879,7883,7901,7907,7919,
7927,7933,7937,7949,7951,7963,7993,8009,
8011,8017,8039,8053,8059,8069,8081,8087,
8089,8093,8101,8111,8117,8123,8147,8161,
8167,8171,8179,8191,8209,8219,8221,8231,
8233,8237,8243,8263,8269,8273,8287,8291,
8293,8297,8311,8317,8329,8353,8363,8369,
8377,8387,8389,8419,8423,8429,8431,8443,
8447,8461,8467,8501,8513,8521,8527,8537,
8539,8543,8563,8573,8581,8597,8599,8609,
8623,8627,8629,8641,8647,8663,8669,8677,
8681,8689,8693,8699,8707,8713,8719,8731,
8737,8741,8747,8753,8761,8779,8783,8803,
8807,8819,8821,8831,8837,8839,8849,8861,
8863,8867,8887,8893,8923,8929,8933,8941,
8951,8963,8969,8971,8999,9001,9007,9011,
9013,9029,9041,9043,9049,9059,9067,9091,
9103,9109,9127,9133,9137,9151,9157,9161,
9173,9181,9187,9199,9203,9209,9221,9227,
9239,9241,9257,9277,9281,9283,9293,9311,
9319,9323,9337,9341,9343,9349,9371,9377,
9391,9397,9403,9413,9419,9421,9431,9433,
9437,9439,9461,9463,9467,9473,9479,9491,
9497,9511,9521,9533,9539,9547,9551,9587,
9601,9613,9619,9623,9629,9631,9643,9649,
9661,9677,9679,9689,9697,9719,9721,9733,
9739,9743,9749,9767,9769,9781,9787,9791,
9803,9811,9817,9829,9833,9839,9851,9857,
9859,9871,9883,9887,9901,9907,9923,9929,
9931,9941,9949,9967,9973,10007,10009,10037,
10039,10061,10067,10069,10079,10091,10093,10099,
10103,10111,10133,10139,10141,10151,10159,10163,
10169,10177,10181,10193,10211,10223,10243,10247,
10253,10259,10267,10271,10273,10289,10301,10303,
10313,10321,10331,10333,10337,10343,10357,10369,
10391,10399,10427,10429,10433,10453,10457,10459,
10463,10477,10487,10499,10501,10513,10529,10531,
10559,10567,10589,10597,10601,10607,10613,10627,
10631,10639,10651,10657,10663,10667,10687,10691,
10709,10711,10723,10729,10733,10739,10753,10771,
10781,10789,10799,10831,10837,10847,10853,10859,
10861,10867,10883,10889,10891,10903,10909,10937,
10939,10949,10957,10973,10979,10987,10993,11003,
11027,11047,11057,11059,11069,11071,11083,11087,
11093,11113,11117,11119,11131,11149,11159,11161,
11171,11173,11177,11197,11213,11239,11243,11251,
11257,11261,11273,11279,11287,11299,11311,11317,
11321,11329,11351,11353,11369,11383,11393,11399,
11411,11423,11437,11443,11447,11467,11471,11483,
11489,11491,11497,11503,11519,11527,11549,11551,
11579,11587,11593,11597,11617,11621,11633,11657,
11677,11681,11689,11699,11701,11717,11719,11731,
11743,11777,11779,11783,11789,11801,11807,11813,
11821,11827,11831,11833,11839,11863,11867,11887,
11897,11903,11909,11923,11927,11933,11939,11941,
11953,11959,11969,11971,11981,11987,12007,12011,
12037,12041,12043,12049,12071,12073,12097,12101,
12107,12109,12113,12119,12143,12149,12157,12161,
12163,12197,12203,12211,12227,12239,12241,12251,
12253,12263,12269,12277,12281,12289,12301,12323,
12329,12343,12347,12373,12377,12379,12391,12401,
12409,12413,12421,12433,12437,12451,12457,12473,
12479,12487,12491,12497,12503,12511,12517,12527,
12539,12541,12547,12553,12569,12577,12583,12589,
12601,12611,12613,12619,12637,12641,12647,12653,
12659,12671,12689,12697,12703,12713,12721,12739,
12743,12757,12763,12781,12791,12799,12809,12821,
12823,12829,12841,12853,12889,12893,12899,12907,
12911,12917,12919,12923,12941,12953,12959,12967,
12973,12979,12983,13001,13003,13007,13009,13033,
13037,13043,13049,13063,13093,13099,13103,13109,
13121,13127,13147,13151,13159,13163,13171,13177,
13183,13187,13217,13219,13229,13241,13249,13259,
13267,13291,13297,13309,13313,13327,13331,13337,
13339,13367,13381,13397,13399,13411,13417,13421,
13441,13451,13457,13463,13469,13477,13487,13499,
13513,13523,13537,13553,13567,13577,13591,13597,
13613,13619,13627,13633,13649,13669,13679,13681,
13687,13691,13693,13697,13709,13711,13721,13723,
13729,13751,13757,13759,13763,13781,13789,13799,
13807,13829,13831,13841,13859,13873,13877,13879,
13883,13901,13903,13907,13913,13921,13931,13933,
13963,13967,13997,13999,14009,14011,14029,14033,
14051,14057,14071,14081,14083,14087,14107,14143,
14149,14153,14159,14173,14177,14197,14207,14221,
14243,14249,14251,14281,14293,14303,14321,14323,
14327,14341,14347,14369,14387,14389,14401,14407,
14411,14419,14423,14431,14437,14447,14449,14461,
14479,14489,14503,14519,14533,14537,14543,14549,
14551,14557,14561,14563,14591,14593,14621,14627,
14629,14633,14639,14653,14657,14669,14683,14699,
14713,14717,14723,14731,14737,14741,14747,14753,
14759,14767,14771,14779,14783,14797,14813,14821,
14827,14831,14843,14851,14867,14869,14879,14887,
14891,14897,14923,14929,14939,14947,14951,14957,
14969,14983,15013,15017,15031,15053,15061,15073,
15077,15083,15091,15101,15107,15121,15131,15137,
15139,15149,15161,15173,15187,15193,15199,15217,
15227,15233,15241,15259,15263,15269,15271,15277,
15287,15289,15299,15307,15313,15319,15329,15331,
15349,15359,15361,15373,15377,15383,15391,15401,
15413,15427,15439,15443,15451,15461,15467,15473,
15493,15497,15511,15527,15541,15551,15559,15569,
15581,15583,15601,15607,15619,15629,15641,15643,
15647,15649,15661,15667,15671,15679,15683,15727,
15731,15733,15737,15739,15749,15761,15767,15773,
15787,15791,15797,15803,15809,15817,15823,15859,
15877,15881,15887,15889,15901,15907,15913,15919,
15923,15937,15959,15971,15973,15991,16001,16007,
16033,16057,16061,16063,16067,16069,16073,16087,
16091,16097,16103,16111,16127,16139,16141,16183,
16187,16189,16193,16217,16223,16229,16231,16249,
16253,16267,16273,16301,16319,16333,16339,16349,
16361,16363,16369,16381,16411,16417,16421,16427,
16433,16447,16451,16453,16477,16481,16487,16493,
16519,16529,16547,16553,16561,16567,16573,16603,
16607,16619,16631,16633,16649,16651,16657,16661,
16673,16691,16693,16699,16703,16729,16741,16747,
16759,16763,16787,16811,16823,16829,16831,16843,
16871,16879,16883,16889,16901,16903,16921,16927,
16931,16937,16943,16963,16979,16981,16987,16993,
17011,17021,17027,17029,17033,17041,17047,17053,
17077,17093,17099,17107,17117,17123,17137,17159,
17167,17183,17189,17191,17203,17207,17209,17231,
17239,17257,17291,17293,17299,17317,17321,17327,
17333,17341,17351,17359,17377,17383,17387,17389,
17393,17401,17417,17419,17431,17443,17449,17467,
17471,17477,17483,17489,17491,17497,17509,17519,
17539,17551,17569,17573,17579,17581,17597,17599,
17609,17623,17627,17657,17659,17669,17681,17683,
17707,17713,17729,17737,17747,17749,17761,17783,
17789,17791,17807,17827,17837,17839,17851,17863,
#endif
};

View File

@ -0,0 +1,139 @@
/* crypto/bn/bn_shift.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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 <string.h>
#include "bn_lcl.h"
int BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
{
int i,nw,lb,rb;
BN_ULONG *t,*f;
BN_ULONG l;
r->neg=a->neg;
if (bn_wexpand(r,a->top+(n/BN_BITS2)+1) == 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]));
/* for (i=0; i<nw; i++)
t[i]=0;*/
r->top=a->top+nw+1;
bn_fix_top(r);
return(1);
}
int BN_rshift(BIGNUM *r, BIGNUM *a, int n)
{
int i,j,nw,lb,rb;
BN_ULONG *t,*f;
BN_ULONG l,tmp;
nw=n/BN_BITS2;
rb=n%BN_BITS2;
lb=BN_BITS2-rb;
if (nw > a->top || a->top == 0)
{
BN_zero(r);
return(1);
}
if (r != a)
{
r->neg=a->neg;
if (bn_wexpand(r,a->top-nw+1) == NULL) return(0);
}
f= &(a->d[nw]);
t=r->d;
j=a->top-nw;
r->top=j;
if (rb == 0)
{
for (i=j+1; i > 0; i--)
*(t++)= *(f++);
}
else
{
l= *(f++);
for (i=1; i<j; i++)
{
tmp =(l>>rb)&BN_MASK2;
l= *(f++);
*(t++) =(tmp|(l<<lb))&BN_MASK2;
}
*(t++) =(l>>rb)&BN_MASK2;
}
*t=0;
bn_fix_top(r);
return(1);
}

View File

@ -0,0 +1,160 @@
/* crypto/bn/bn_sqr.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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 <string.h>
#include "bn_lcl.h"
/* r must not be a */
/* I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96 */
int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx)
{
int max,al;
int ret = 0;
BIGNUM *tmp,*rr;
#ifdef BN_COUNT
printf("BN_sqr %d * %d\n",a->top,a->top);
#endif
bn_check_top(a);
al=a->top;
if (al <= 0)
{
r->top=0;
return(1);
}
BN_CTX_start(ctx);
rr=(a != r) ? r : BN_CTX_get(ctx);
tmp=BN_CTX_get(ctx);
if (tmp == NULL) goto err;
max=(al+al);
if (bn_wexpand(rr,max+1) == NULL) goto err;
r->neg=0;
if (al == 4)
{
#ifndef BN_SQR_COMBA
BN_ULONG t[8];
bn_sqr_normal(rr->d,a->d,4,t);
#else
bn_sqr_comba4(rr->d,a->d);
#endif
}
else if (al == 8)
{
#ifndef BN_SQR_COMBA
BN_ULONG t[16];
bn_sqr_normal(rr->d,a->d,8,t);
#else
bn_sqr_comba8(rr->d,a->d);
#endif
}
else
{
if (bn_wexpand(tmp,max) == NULL) goto err;
bn_sqr_normal(rr->d,a->d,al,tmp->d);
}
rr->top=max;
if ((max > 0) && (rr->d[max-1] == 0)) rr->top--;
if (rr != r) BN_copy(r,rr);
ret = 1;
err:
BN_CTX_end(ctx);
return(ret);
}
/* tmp must have 2*n words */
void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp)
{
int i,j,max;
BN_ULONG *ap,*rp;
max=n*2;
ap=a;
rp=r;
rp[0]=rp[max-1]=0;
rp++;
j=n;
if (--j > 0)
{
ap++;
rp[j]=bn_mul_words(rp,ap,j,ap[-1]);
rp+=2;
}
for (i=n-2; i>0; i--)
{
j--;
ap++;
rp[j]=bn_mul_add_words(rp,ap,j,ap[-1]);
rp+=2;
}
bn_add_words(r,r,r,max);
/* There will not be a carry */
bn_sqr_words(tmp,a,n);
bn_add_words(r,r,tmp,max);
}

View File

@ -0,0 +1,130 @@
/* crypto/bn/bn_word.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* 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 "bn_lcl.h"
int BN_add_word(BIGNUM *a, BN_ULONG w)
{
BN_ULONG l;
int i;
if (a->neg)
{
a->neg=0;
i=BN_sub_word(a,w);
if (!BN_is_zero(a))
a->neg=!(a->neg);
return(i);
}
w&=BN_MASK2;
if (bn_wexpand(a,a->top+1) == NULL) return(0);
i=0;
for (;;)
{
l=(a->d[i]+(BN_ULONG)w)&BN_MASK2;
a->d[i]=l;
if (w > l)
w=1;
else
break;
i++;
}
if (i >= a->top)
a->top++;
return(1);
}
int BN_sub_word(BIGNUM *a, BN_ULONG w)
{
int i;
if (BN_is_zero(a) || a->neg)
{
a->neg=0;
i=BN_add_word(a,w);
a->neg=1;
return(i);
}
w&=BN_MASK2;
if ((a->top == 1) && (a->d[0] < w))
{
a->d[0]=w-a->d[0];
a->neg=1;
return(1);
}
i=0;
for (;;)
{
if (a->d[i] >= w)
{
a->d[i]-=w;
break;
}
else
{
a->d[i]=(a->d[i]-w)&BN_MASK2;
i++;
w=1;
}
}
if ((a->d[i] == 0) && (i == (a->top-1)))
a->top--;
return(1);
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include <stdio.h>
#include "t_defines.h"
#include "t_pwd.h"
#include "t_client.h"
int
main()
{
int index;
struct t_client * tc;
struct t_preconf *tcp;
struct t_num n;
struct t_num g;
struct t_num s;
struct t_num B;
char username[MAXUSERLEN];
char hexbuf[MAXHEXPARAMLEN];
char buf1[MAXPARAMLEN], buf2[MAXPARAMLEN], buf3[MAXSALTLEN];
unsigned char cbuf[20];
struct t_num * A;
unsigned char * skey;
char pass[128];
printf("Enter username: ");
fgets(username, sizeof(username), stdin);
username[strlen(username) - 1] = '\0';
printf("Enter index (from server): ");
fgets(hexbuf, sizeof(hexbuf), stdin);
index = atoi(hexbuf);
tcp = t_getpreparam(index - 1);
printf("Enter salt (from server): ");
fgets(hexbuf, sizeof(hexbuf), stdin);
s.data = buf3;
s.len = t_fromb64(s.data, hexbuf);
tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &s);
if (tc == 0) {
printf("invalid n, g\n");
exit(1);
}
A = t_clientgenexp(tc);
printf("A (to server): %s\n", t_tob64(hexbuf, A->data, A->len));
t_getpass(pass, 128, "Enter password:");
t_clientpasswd(tc, pass);
printf("Enter B (from server): ");
fgets(hexbuf, sizeof(hexbuf), stdin);
B.data = buf1;
B.len = t_fromb64(B.data, hexbuf);
skey = t_clientgetkey(tc, &B);
printf("Session key: %s\n", t_tohex(hexbuf, skey, 40));
printf("Response (to server): %s\n",
t_tohex(hexbuf, t_clientresponse(tc), RESPONSE_LEN));
printf("Enter server response: ");
fgets(hexbuf, sizeof(hexbuf), stdin);
hexbuf[strlen(hexbuf) - 1] = '\0';
t_fromhex(cbuf, hexbuf);
if (t_clientverify(tc, cbuf) == 0)
printf("Server authentication successful.\n");
else
printf("Server authentication failed.\n");
t_clientclose(tc);
return 0;
}

View File

@ -0,0 +1,79 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if type char is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
#undef __CHAR_UNSIGNED__
#endif
/* Define to empty if the keyword does not work. */
#undef const
/* Define as __inline if that's what the C compiler calls it. */
#undef inline
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
#undef SHA1HANDSOFF
#undef POSIX_TERMIOS
#undef POSIX_SIGTYPE
#undef volatile
/* The number of bytes in a int. */
#undef SIZEOF_INT
/* The number of bytes in a long. */
#undef SIZEOF_LONG
/* The number of bytes in a long long. */
#undef SIZEOF_LONG_LONG
/* The number of bytes in a short. */
#undef SIZEOF_SHORT
/* Define if you have the memcpy function. */
#undef HAVE_MEMCPY
/* Define if you have the sigaction function. */
#undef HAVE_SIGACTION
/* Define if you have the strchr function. */
#undef HAVE_STRCHR
/* Define if you have the <sgtty.h> header file. */
#undef HAVE_SGTTY_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Name of package */
#undef PACKAGE
/* Version number of package */
#undef VERSION

2421
package/ead/src/tinysrp/configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(t_pwd.h)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(libtinysrp, 0.7.5)
test "$CFLAGS" = "" && CFLAGS="-O2"
dnl Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_RANLIB
AC_ARG_PROGRAM
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(sgtty.h sys/ioctl.h sys/time.h termio.h termios.h unistd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_HEADER_TIME
AC_C_BIGENDIAN
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(long long)
AC_TRY_COMPILE(, [volatile int i;], , AC_DEFINE(volatile, ))
AC_C_CHAR_UNSIGNED
AC_SUBST(signed)dnl
if test "$ac_cv_c_char_unsigned" = "yes"; then
signed=-signed
fi
dnl Checks for library functions.
AC_CHECK_FUNCS(sigaction strchr memcpy)
TYPE_SIGNAL
AC_HEADER_CHECK(termios.h,AC_FUNC_CHECK(cfsetispeed,AC_DEFINE(POSIX_TERMIOS)))
dnl User options
dnl Some defines for now.
AC_DEFINE(SHA1HANDSOFF)
AC_OUTPUT(Makefile)

View File

@ -0,0 +1,250 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

134
package/ead/src/tinysrp/missing Executable file
View File

@ -0,0 +1,134 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
# 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, or (at your option)
# any later version.
# 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.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
case "$1" in
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison touch file \`y.tab.c'
makeinfo touch the output file
yacc touch file \`y.tab.c'"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing - GNU libit 0.0"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`configure.in'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`configure.in'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`configure.in'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
touch config.h.in
;;
automake)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print \
| sed 's/^\(.*\).am$/touch \1.in/' \
| sh
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
touch y.tab.c
;;
makeinfo)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequirements for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,40 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp" 1>&2
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include <stdio.h>
#include "t_defines.h"
#include "t_pwd.h"
#include "t_server.h"
int
main(argc, argv)
int argc;
char * argv[];
{
struct t_server * ts;
struct t_pw * tpw;
struct t_conf * tcnf;
struct t_num * B;
char username[MAXUSERLEN];
char hexbuf[MAXHEXPARAMLEN];
char buf[MAXPARAMLEN];
struct t_num A;
unsigned char * skey;
unsigned char cbuf[20];
FILE * fp;
FILE * fp2;
char confname[256];
printf("Enter username: ");
fgets(username, sizeof(username), stdin);
username[strlen(username) - 1] = '\0';
ts = t_serveropen(username);
if(ts == NULL) {
fprintf(stderr, "User %s not found\n", username);
exit(1);
}
#if 0
printf("n: %s\n", t_tob64(hexbuf, ts->n.data, ts->n.len));
printf("g: %s\n", t_tob64(hexbuf, ts->g.data, ts->g.len));
#endif
printf("index (to client): %d\n", ts->index);
printf("salt (to client): %s\n", t_tob64(hexbuf, ts->s.data, ts->s.len));
B = t_servergenexp(ts);
printf("Enter A (from client): ");
fgets(hexbuf, sizeof(hexbuf), stdin);
A.data = buf;
A.len = t_fromb64(A.data, hexbuf);
printf("B (to client): %s\n", t_tob64(hexbuf, B->data, B->len));
skey = t_servergetkey(ts, &A);
printf("Session key: %s\n", t_tohex(hexbuf, skey, 40));
/* printf("[Expected response: %s]\n", t_tohex(hexbuf, cbuf, 16)); */
printf("Enter response (from client): ");
fgets(hexbuf, sizeof(hexbuf), stdin);
hexbuf[strlen(hexbuf) - 1] = '\0';
t_fromhex(cbuf, hexbuf);
if(t_serververify(ts, cbuf) == 0) {
printf("Authentication successful.\n");
printf("Response (to client): %s\n",
t_tohex(hexbuf, t_serverresponse(ts), RESPONSE_LEN));
} else
printf("Authentication failed.\n");
t_serverclose(ts);
return 0;
}

View File

@ -0,0 +1 @@
timestamp

View File

@ -0,0 +1,287 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include <stdio.h>
#include "t_defines.h"
#include "t_pwd.h"
#include "t_client.h"
#include "t_sha.h"
_TYPE( struct t_client * )
t_clientopen(u, n, g, s)
const char * u;
struct t_num * n;
struct t_num * g;
struct t_num * s;
{
struct t_client * tc;
unsigned char buf1[SHA_DIGESTSIZE], buf2[SHA_DIGESTSIZE];
SHA1_CTX ctxt;
int i, validated;
struct t_preconf * tpc;
BigInteger nn, gg, n12, r;
validated = 0;
if(n->len < MIN_MOD_BYTES)
return 0;
for(i = 0; i < t_getprecount(); ++i) {
tpc = t_getpreparam(i);
if(tpc->modulus.len == n->len && tpc->generator.len == g->len &&
memcmp(tpc->modulus.data, n->data, n->len) == 0 &&
memcmp(tpc->generator.data, g->data, g->len) == 0) {
validated = 1; /* Match found, done */
break;
}
}
if(validated == 0)
return 0;
if((tc = malloc(sizeof(struct t_client))) == 0)
return 0;
strncpy(tc->username, u, MAXUSERLEN);
SHA1Init(&tc->hash);
tc->n.len = n->len;
tc->n.data = tc->nbuf;
memcpy(tc->n.data, n->data, tc->n.len);
SHA1Init(&ctxt);
SHA1Update(&ctxt, tc->n.data, tc->n.len);
SHA1Final(buf1, &ctxt);
tc->g.len = g->len;
tc->g.data = tc->gbuf;
memcpy(tc->g.data, g->data, tc->g.len);
SHA1Init(&ctxt);
SHA1Update(&ctxt, tc->g.data, tc->g.len);
SHA1Final(buf2, &ctxt);
for(i = 0; i < sizeof(buf1); ++i)
buf1[i] ^= buf2[i];
SHA1Update(&tc->hash, buf1, sizeof(buf1));
SHA1Init(&ctxt);
SHA1Update(&ctxt, tc->username, strlen(tc->username));
SHA1Final(buf1, &ctxt);
SHA1Update(&tc->hash, buf1, sizeof(buf1));
tc->s.len = s->len;
tc->s.data = tc->sbuf;
memcpy(tc->s.data, s->data, tc->s.len);
SHA1Update(&tc->hash, tc->s.data, tc->s.len);
tc->a.data = tc->abuf;
tc->A.data = tc->Abuf;
tc->p.data = tc->pbuf;
tc->v.data = tc->vbuf;
SHA1Init(&tc->ckhash);
return tc;
}
_TYPE( struct t_num * )
t_clientgenexp(tc)
struct t_client * tc;
{
BigInteger a, A, n, g;
if(tc->n.len < ALEN)
tc->a.len = tc->n.len;
else
tc->a.len = ALEN;
t_random(tc->a.data, tc->a.len);
a = BigIntegerFromBytes(tc->a.data, tc->a.len);
n = BigIntegerFromBytes(tc->n.data, tc->n.len);
g = BigIntegerFromBytes(tc->g.data, tc->g.len);
A = BigIntegerFromInt(0);
BigIntegerModExp(A, g, a, n);
tc->A.len = BigIntegerToBytes(A, tc->A.data);
BigIntegerFree(A);
BigIntegerFree(a);
BigIntegerFree(g);
BigIntegerFree(n);
SHA1Update(&tc->hash, tc->A.data, tc->A.len);
SHA1Update(&tc->ckhash, tc->A.data, tc->A.len);
return &tc->A;
}
_TYPE( void )
t_clientpasswd(tc, password)
struct t_client * tc;
char * password;
{
BigInteger n, g, p, v;
SHA1_CTX ctxt;
unsigned char dig[SHA_DIGESTSIZE];
n = BigIntegerFromBytes(tc->n.data, tc->n.len);
g = BigIntegerFromBytes(tc->g.data, tc->g.len);
SHA1Init(&ctxt);
SHA1Update(&ctxt, tc->username, strlen(tc->username));
SHA1Update(&ctxt, ":", 1);
SHA1Update(&ctxt, password, strlen(password));
SHA1Final(dig, &ctxt);
SHA1Init(&ctxt);
SHA1Update(&ctxt, tc->s.data, tc->s.len);
SHA1Update(&ctxt, dig, sizeof(dig));
SHA1Final(dig, &ctxt);
p = BigIntegerFromBytes(dig, sizeof(dig));
v = BigIntegerFromInt(0);
BigIntegerModExp(v, g, p, n);
tc->p.len = BigIntegerToBytes(p, tc->p.data);
BigIntegerFree(p);
tc->v.len = BigIntegerToBytes(v, tc->v.data);
BigIntegerFree(v);
}
_TYPE( unsigned char * )
t_clientgetkey(tc, serverval)
struct t_client * tc;
struct t_num * serverval;
{
BigInteger n, B, v, p, a, sum, S;
unsigned char sbuf[MAXPARAMLEN];
unsigned char dig[SHA_DIGESTSIZE];
unsigned slen;
unsigned int u;
SHA1_CTX ctxt;
SHA1Init(&ctxt);
SHA1Update(&ctxt, serverval->data, serverval->len);
SHA1Final(dig, &ctxt);
u = (dig[0] << 24) | (dig[1] << 16) | (dig[2] << 8) | dig[3];
if(u == 0)
return NULL;
SHA1Update(&tc->hash, serverval->data, serverval->len);
B = BigIntegerFromBytes(serverval->data, serverval->len);
n = BigIntegerFromBytes(tc->n.data, tc->n.len);
if(BigIntegerCmp(B, n) >= 0 || BigIntegerCmpInt(B, 0) == 0) {
BigIntegerFree(B);
BigIntegerFree(n);
return NULL;
}
v = BigIntegerFromBytes(tc->v.data, tc->v.len);
if(BigIntegerCmp(B, v) < 0)
BigIntegerAdd(B, B, n);
BigIntegerSub(B, B, v);
BigIntegerFree(v);
a = BigIntegerFromBytes(tc->a.data, tc->a.len);
p = BigIntegerFromBytes(tc->p.data, tc->p.len);
sum = BigIntegerFromInt(0);
BigIntegerMulInt(sum, p, u);
BigIntegerAdd(sum, sum, a);
BigIntegerFree(p);
BigIntegerFree(a);
S = BigIntegerFromInt(0);
BigIntegerModExp(S, B, sum, n);
slen = BigIntegerToBytes(S, sbuf);
BigIntegerFree(S);
BigIntegerFree(sum);
BigIntegerFree(B);
BigIntegerFree(n);
t_sessionkey(tc->session_key, sbuf, slen);
memset(sbuf, 0, slen);
SHA1Update(&tc->hash, tc->session_key, sizeof(tc->session_key));
SHA1Final(tc->session_response, &tc->hash);
SHA1Update(&tc->ckhash, tc->session_response, sizeof(tc->session_response));
SHA1Update(&tc->ckhash, tc->session_key, sizeof(tc->session_key));
return tc->session_key;
}
_TYPE( int )
t_clientverify(tc, resp)
struct t_client * tc;
unsigned char * resp;
{
unsigned char expected[SHA_DIGESTSIZE];
SHA1Final(expected, &tc->ckhash);
return memcmp(expected, resp, sizeof(expected));
}
_TYPE( unsigned char * )
t_clientresponse(tc)
struct t_client * tc;
{
return tc->session_response;
}
_TYPE( void )
t_clientclose(tc)
struct t_client * tc;
{
memset(tc->abuf, 0, sizeof(tc->abuf));
memset(tc->pbuf, 0, sizeof(tc->pbuf));
memset(tc->vbuf, 0, sizeof(tc->vbuf));
memset(tc->session_key, 0, sizeof(tc->session_key));
free(tc);
}

View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#ifndef T_CLIENT_H
#define T_CLIENT_H
#include "t_sha.h"
#if !defined(P)
#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
#endif
#endif
/* For building dynamic link libraries under windows, windows NT
* using MSVC1.5 or MSVC2.0
*/
#ifndef _DLLDECL
#define _DLLDECL
#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
#define _MSVC15EXPORT _export
#define _MSVC20EXPORT
#define _DLLAPI _export _pascal
#define _TYPE(a) a _MSVC15EXPORT
#define DLLEXPORT 1
#elif MSVC20
#define _MSVC15EXPORT
#define _MSVC20EXPORT _declspec(dllexport)
#define _DLLAPI
#define _TYPE(a) _MSVC20EXPORT a
#define DLLEXPORT 1
#else /* Default, non-dll. Use this for Unix or DOS */
#define _MSVC15DEXPORT
#define _MSVC20EXPORT
#define _DLLAPI
#define _TYPE(a) a
#endif
#endif
#define ALEN 32
#define MIN_MOD_BYTES 64 /* 512 bits */
struct t_client {
struct t_num n;
struct t_num g;
struct t_num s;
struct t_num a;
struct t_num A;
struct t_num p;
struct t_num v;
SHA1_CTX hash, ckhash;
char username[MAXUSERLEN];
unsigned char session_key[SESSION_KEY_LEN];
unsigned char session_response[RESPONSE_LEN];
unsigned char nbuf[MAXPARAMLEN], gbuf[MAXPARAMLEN], sbuf[MAXSALTLEN];
unsigned char pbuf[MAXPARAMLEN], vbuf[MAXPARAMLEN];
unsigned char abuf[ALEN], Abuf[MAXPARAMLEN];
};
/*
* SRP client-side negotiation
*
* This code negotiates the client side of an SRP exchange.
* "t_clientopen" accepts a username, and N, g, and s parameters,
* which are usually sent by the server in the first round.
* The client should then call...
* "t_clientgenexp" will generate a random 256-bit exponent and
* raise g to that power, returning the result. This result
* should be sent to the server as w(p).
* "t_clientpasswd" accepts the user's password, which should be
* entered locally and updates the client's state.
* "t_clientgetkey" accepts the exponential y(p), which should
* be sent by the server in the next round and computes the
* 256-bit session key. This data should be saved before the
* session is closed.
* "t_clientresponse" computes the session key proof as SHA(y(p), K).
* "t_clientclose" closes the session and frees its memory.
*
* Note that authentication is not performed per se; it is up
* to either/both sides of the protocol to now verify securely
* that their session keys agree in order to establish authenticity.
* One possible way is through "oracle hashing"; one side sends
* r, the other replies with H(r,K), where H() is a hash function.
*
* t_clientresponse and t_clientverify now implement a version of
* the session-key verification described above.
*/
_TYPE( struct t_client * )
t_clientopen P((const char *, struct t_num *, struct t_num *,
struct t_num *));
_TYPE( struct t_num * ) t_clientgenexp P((struct t_client *));
_TYPE( void ) t_clientpasswd P((struct t_client *, char *));
_TYPE( unsigned char * )
t_clientgetkey P((struct t_client *, struct t_num *));
_TYPE( int ) t_clientverify P((struct t_client *, unsigned char *));
_TYPE( unsigned char * ) t_clientresponse P((struct t_client *));
_TYPE( void ) t_clientclose P((struct t_client *));
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
/*#define _POSIX_SOURCE*/
#include <stdio.h>
#include "t_defines.h"
static int
hexDigitToInt(c)
char c;
{
if(c >= '0' && c <= '9')
return c - '0';
else if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
else if(c >= 'A' && c <= 'F')
return c - 'A' + 10;
else
return 0;
}
/*
* Convert a hex string to a string of bytes; return size of dst
*/
_TYPE( int )
t_fromhex(dst, src)
register char *dst, *src;
{
register char *chp = dst;
register unsigned size = strlen(src);
/* FIXME: handle whitespace and non-hex digits by setting size and src
appropriately. */
if(size % 2 == 1) {
*chp++ = hexDigitToInt(*src++);
--size;
}
while(size > 0) {
*chp++ = (hexDigitToInt(*src) << 4) | hexDigitToInt(*(src + 1));
src += 2;
size -= 2;
}
return chp - dst;
}
/*
* Convert a string of bytes to their hex representation
*/
_TYPE( char * )
t_tohex(dst, src, size)
register char *dst, *src;
register unsigned size;
{
int notleading = 0;
register char *chp = dst;
if (size != 0) do {
if(notleading || *src != '\0') {
notleading = 1;
sprintf(chp, "%.2x", * (unsigned char *) src);
chp += 2;
}
++src;
} while (--size != 0);
return dst;
}
static char b64table[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
/*
* Convert a base64 string into raw byte array representation.
*/
_TYPE( int )
t_fromb64(dst, src)
register char *dst, *src;
{
unsigned char *a;
char *loc;
int i, j;
unsigned int size;
while(*src && (*src == ' ' || *src == '\t' || *src == '\n'))
++src;
size = strlen(src);
a = malloc((size + 1) * sizeof(unsigned char));
if(a == (unsigned char *) 0)
return -1;
i = 0;
while(i < size) {
loc = strchr(b64table, src[i]);
if(loc == (char *) 0)
break;
else
a[i] = loc - b64table;
++i;
}
size = i;
i = size - 1;
j = size;
while(1) {
a[j] = a[i];
if(--i < 0)
break;
a[j] |= (a[i] & 3) << 6;
--j;
a[j] = (unsigned char) ((a[i] & 0x3c) >> 2);
if(--i < 0)
break;
a[j] |= (a[i] & 0xf) << 4;
--j;
a[j] = (unsigned char) ((a[i] & 0x30) >> 4);
if(--i < 0)
break;
a[j] |= (a[i] << 2);
a[--j] = 0;
if(--i < 0)
break;
}
while(a[j] == 0 && j <= size)
++j;
memcpy(dst, a + j, size - j + 1);
free(a);
return size - j + 1;
}
/*
* Convert a raw byte string into a null-terminated base64 ASCII string.
*/
_TYPE( char * )
t_tob64(dst, src, size)
register char *dst, *src;
register unsigned size;
{
int c, pos = size % 3;
unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0;
char *olddst = dst;
switch(pos) {
case 1:
b2 = src[0];
break;
case 2:
b1 = src[0];
b2 = src[1];
break;
}
while(1) {
c = (b0 & 0xfc) >> 2;
if(notleading || c != 0) {
*dst++ = b64table[c];
notleading = 1;
}
c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4);
if(notleading || c != 0) {
*dst++ = b64table[c];
notleading = 1;
}
c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6);
if(notleading || c != 0) {
*dst++ = b64table[c];
notleading = 1;
}
c = b2 & 0x3f;
if(notleading || c != 0) {
*dst++ = b64table[c];
notleading = 1;
}
if(pos >= size)
break;
else {
b0 = src[pos++];
b1 = src[pos++];
b2 = src[pos++];
}
}
*dst++ = '\0';
return olddst;
}

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#ifndef T_DEFINES_H
#define T_DEFINES_H
#ifndef P
#if defined(__STDC__) || defined(__cplusplus)
#define P(x) x
#else
#define P(x) ()
#endif
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#ifndef _DLLDECL
#define _DLLDECL
#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
#define _MSVC15EXPORT _export
#define _MSVC20EXPORT
#define _DLLAPI _export _pascal
#define _TYPE(a) a _MSVC15EXPORT
#define DLLEXPORT 1
#elif MSVC20
#define _MSVC15EXPORT
#define _MSVC20EXPORT _declspec(dllexport)
#define _DLLAPI
#define _TYPE(a) _MSVC20EXPORT a
#define DLLEXPORT 1
#else /* Default, non-dll. Use this for Unix or DOS */
#define _MSVC15DEXPORT
#define _MSVC20EXPORT
#define _DLLAPI
#define _TYPE(a) a
#endif
#endif
#if STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#else /* not STDC_HEADERS */
#ifndef HAVE_STRCHR
#define strchr index
#define strrchr rindex
#endif
char *strchr(), *strrchr(), *strtok();
#ifndef HAVE_MEMCPY
#define memcpy(d, s, n) bcopy((s), (d), (n))
#endif
#endif /* not STDC_HEADERS */
#include <sys/types.h>
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else /* not TIME_WITH_SYS_TIME */
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif /* not TIME_WITH_SYS_TIME */
#if HAVE_TERMIOS_H
#include <termios.h>
#define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
#define GTTY(fd, termio) tcgetattr(fd, termio)
#define TERMIO struct termios
#define USE_TERMIOS
#elif HAVE_TERMIO_H
#include <sys/ioctl.h>
#include <termio.h>
#define STTY(fd, termio) ioctl(fd, TCSETA, termio)
#define GTTY(fd, termio) ioctl(fd, TCGETA, termio)
#define TEMRIO struct termio
#define USE_TERMIO
#elif HAVE_SGTTY_H
#include <sgtty.h>
#define STTY(fd, termio) stty(fd, termio)
#define GTTY(fd, termio) gtty(fd, termio)
#define TERMIO struct sgttyb
#define USE_SGTTY
#endif
#ifdef USE_FTIME
#include <sys/timeb.h>
#endif
#ifndef MATH_PRIV
typedef void * BigInteger;
#endif
_TYPE( BigInteger ) BigIntegerFromInt P((unsigned int number));
_TYPE( BigInteger ) BigIntegerFromBytes P((unsigned char * bytes, int length));
_TYPE( int ) BigIntegerToBytes P((BigInteger src, unsigned char * dest));
_TYPE( int ) BigIntegerBitLen P((BigInteger b));
_TYPE( int ) BigIntegerCmp P((BigInteger c1, BigInteger c2));
_TYPE( int ) BigIntegerCmpInt P((BigInteger c1, unsigned int c2));
_TYPE( void ) BigIntegerLShift P((BigInteger result, BigInteger x,
unsigned int bits));
_TYPE( void ) BigIntegerAdd P((BigInteger result, BigInteger a1, BigInteger a2));
_TYPE( void ) BigIntegerAddInt P((BigInteger result,
BigInteger a1, unsigned int a2));
_TYPE( void ) BigIntegerSub P((BigInteger result, BigInteger s1, BigInteger s2));
_TYPE( void ) BigIntegerSubInt P((BigInteger result,
BigInteger s1, unsigned int s2));
/* For BigIntegerMul{,Int}: result != m1, m2 */
_TYPE( void ) BigIntegerMul P((BigInteger result, BigInteger m1, BigInteger m2));
_TYPE( void ) BigIntegerMulInt P((BigInteger result,
BigInteger m1, unsigned int m2));
_TYPE( void ) BigIntegerDivInt P((BigInteger result,
BigInteger d, unsigned int m));
_TYPE( void ) BigIntegerMod P((BigInteger result, BigInteger d, BigInteger m));
_TYPE( unsigned int ) BigIntegerModInt P((BigInteger d, unsigned int m));
_TYPE( void ) BigIntegerModMul P((BigInteger result,
BigInteger m1, BigInteger m2, BigInteger m));
_TYPE( void ) BigIntegerModExp P((BigInteger result, BigInteger base,
BigInteger expt, BigInteger modulus));
_TYPE( void ) BigIntegerModExpInt P((BigInteger result, BigInteger base,
unsigned int expt, BigInteger modulus));
_TYPE( int ) BigIntegerCheckPrime P((BigInteger n));
_TYPE( void ) BigIntegerFree P((BigInteger b));
#endif

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include <stdio.h>
#include "t_defines.h"
#include "t_pwd.h"
#include "t_read.h"
/* Master builtin parameter storage object. The default that tphrase
uses is the last one. */
static struct pre_struct {
struct t_preconf preconf;
int state; /* 0 == uninitialized/first time */
unsigned char modbuf[MAXPARAMLEN];
unsigned char genbuf[MAXPARAMLEN];
} pre_params[] = {
{ { "2iQzj1CagQc/5ctbuJYLWlhtAsPHc7xWVyCPAKFRLWKADpASkqe9djWPFWTNTdeJtL8nAhImCn3Sr/IAdQ1FrGw0WvQUstPx3FO9KNcXOwisOQ1VlL.gheAHYfbYyBaxXL.NcJx9TUwgWDT0hRzFzqSrdGGTN3FgSTA1v4QnHtEygNj3eZ.u0MThqWUaDiP87nqha7XnT66bkTCkQ8.7T8L4KZjIImrNrUftedTTBi.WCi.zlrBxDuOM0da0JbUkQlXqvp0yvJAPpC11nxmmZOAbQOywZGmu9nhZNuwTlxjfIro0FOdthaDTuZRL9VL7MRPUDo/DQEyW.d4H.UIlzp",
"2",
NULL }, 0 },
{ { "dUyyhxav9tgnyIg65wHxkzkb7VIPh4o0lkwfOKiPp4rVJrzLRYVBtb76gKlaO7ef5LYGEw3G.4E0jbMxcYBetDy2YdpiP/3GWJInoBbvYHIRO9uBuxgsFKTKWu7RnR7yTau/IrFTdQ4LY/q.AvoCzMxV0PKvD9Odso/LFIItn8PbTov3VMn/ZEH2SqhtpBUkWtmcIkEflhX/YY/fkBKfBbe27/zUaKUUZEUYZ2H2nlCL60.JIPeZJSzsu/xHDVcx",
"2",
NULL }, 0 },
{ { "3NUKQ2Re4P5BEK0TLg2dX3gETNNNECPoe92h4OVMaDn3Xo/0QdjgG/EvM.hiVV1BdIGklSI14HA38Mpe5k04juR5/EXMU0r1WtsLhNXwKBlf2zEfoOh0zVmDvqInpU695f29Iy7sNW3U5RIogcs740oUp2Kdv5wuITwnIx84cnO.e467/IV1lPnvMCr0pd1dgS0a.RV5eBJr03Q65Xy61R",
"2",
NULL }, 0 },
{ { "F//////////oG/QeY5emZJ4ncABWDmSqIa2JWYAPynq0Wk.fZiJco9HIWXvZZG4tU.L6RFDEaCRC2iARV9V53TFuJLjRL72HUI5jNPYNdx6z4n2wQOtxMiB/rosz0QtxUuuQ/jQYP.bhfya4NnB7.P9A6PHxEPJWV//////////",
"5",
"oakley prime 2" }, 0 },
{ { "Ewl2hcjiutMd3Fu2lgFnUXWSc67TVyy2vwYCKoS9MLsrdJVT9RgWTCuEqWJrfB6uE3LsE9GkOlaZabS7M29sj5TnzUqOLJMjiwEzArfiLr9WbMRANlF68N5AVLcPWvNx6Zjl3m5Scp0BzJBz9TkgfhzKJZ.WtP3Mv/67I/0wmRZ",
"2",
NULL }, 0 },
};
_TYPE( int )
t_getprecount()
{
return (sizeof(pre_params) / sizeof(struct pre_struct));
}
static struct t_confent sysconf;
/* id is index origin 1 */
_TYPE( struct t_confent * )
gettcid
(id)
int id;
{
struct t_preconf *tcp;
if (id <= 0 || id > t_getprecount()) {
return NULL;
}
tcp = t_getpreparam(id - 1);
sysconf.index = id;
sysconf.modulus = tcp->modulus;
sysconf.generator = tcp->generator;
return &sysconf;
}
_TYPE( struct t_preconf * )
t_getpreparam(idx)
int idx;
{
if(pre_params[idx].state == 0) {
/* Wire up storage */
pre_params[idx].preconf.modulus.data = pre_params[idx].modbuf;
pre_params[idx].preconf.generator.data = pre_params[idx].genbuf;
/* Convert from b64 to t_num */
pre_params[idx].preconf.modulus.len = t_fromb64(pre_params[idx].preconf.modulus.data, pre_params[idx].preconf.mod_b64);
pre_params[idx].preconf.generator.len = t_fromb64(pre_params[idx].preconf.generator.data, pre_params[idx].preconf.gen_b64);
pre_params[idx].state = 1;
}
return &(pre_params[idx].preconf);
}

View File

@ -0,0 +1,191 @@
/*
* Copyright 1990 - 1995, Julianne Frances Haugh
* 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. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH 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.
*/
#include "t_defines.h"
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#endif /* _WIN32 */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <signal.h>
#include <stdio.h>
static int sig_caught;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
/*ARGSUSED*/
static RETSIGTYPE
sig_catch (sig)
int sig;
{
sig_caught = 1;
}
_TYPE( int )
t_getpass (buf, maxlen, prompt)
char *buf;
unsigned maxlen;
const char *prompt;
{
char *cp;
#ifdef _WIN32
HANDLE handle = (HANDLE) _get_osfhandle(_fileno(stdin));
DWORD mode;
GetConsoleMode( handle, &mode );
SetConsoleMode( handle, mode & ~ENABLE_ECHO_INPUT );
if(fputs(prompt, stdout) == EOF ||
fgets(buf, maxlen, stdin) == NULL) {
SetConsoleMode(handle,mode);
return -1;
}
cp = buf + strlen(buf) - 1;
if ( *cp == 0x0a )
*cp = '\0';
printf("\n");
SetConsoleMode(handle,mode);
#else
FILE *fp;
int tty_opened = 0;
#ifdef HAVE_SIGACTION
struct sigaction old_sigact;
#else
RETSIGTYPE (*old_signal)();
#endif
TERMIO new_modes;
TERMIO old_modes;
/*
* set a flag so the SIGINT signal can be re-sent if it
* is caught
*/
sig_caught = 0;
/*
* if /dev/tty can't be opened, getpass() needs to read
* from stdin instead.
*/
if ((fp = fopen ("/dev/tty", "r")) == 0) {
fp = stdin;
setbuf (fp, (char *) 0);
} else {
tty_opened = 1;
}
/*
* the current tty modes must be saved so they can be
* restored later on. echo will be turned off, except
* for the newline character (BSD has to punt on this)
*/
if (GTTY (fileno (fp), &new_modes))
return -1;
old_modes = new_modes;
#ifdef HAVE_SIGACTION
sigact.sa_handler = sig_catch;
(void) sigaction (SIGINT, &sigact, &old_sigact);
#else
old_signal = signal (SIGINT, sig_catch);
#endif
#ifdef USE_SGTTY
new_modes.sg_flags &= ~ECHO;
#else
new_modes.c_iflag &= ~IGNCR;
new_modes.c_iflag |= ICRNL;
new_modes.c_oflag |= OPOST|ONLCR;
new_modes.c_lflag &= ~(ECHO|ECHOE|ECHOK);
new_modes.c_lflag |= ICANON|ECHONL;
#endif
if (STTY (fileno (fp), &new_modes))
goto out;
/*
* the prompt is output, and the response read without
* echoing. the trailing newline must be removed. if
* the fgets() returns an error, a NULL pointer is
* returned.
*/
if (fputs (prompt, stdout) == EOF)
goto out;
(void) fflush (stdout);
if (fgets (buf, maxlen, fp) == buf) {
if ((cp = strchr (buf, '\n')))
*cp = '\0';
else
buf[maxlen - 1] = '\0';
#ifdef USE_SGTTY
putc ('\n', stdout);
#endif
}
else buf[0] = '\0';
out:
/*
* the old SIGINT handler is restored after the tty
* modes. then /dev/tty is closed if it was opened in
* the beginning. finally, if a signal was caught it
* is sent to this process for normal processing.
*/
if (STTY (fileno (fp), &old_modes))
{ memset (buf, 0, maxlen); return -1; }
#ifdef HAVE_SIGACTION
(void) sigaction (SIGINT, &old_sigact, NULL);
#else
(void) signal (SIGINT, old_signal);
#endif
if (tty_opened)
(void) fclose (fp);
if (sig_caught) {
kill (getpid (), SIGINT);
memset (buf, 0, maxlen);
return -1;
}
#endif
return 0;
}

View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include <stdio.h>
#include <sys/types.h>
#include "config.h"
#include "bn.h"
typedef BIGNUM * BigInteger;
#define MATH_PRIV
#include "t_defines.h"
#include "t_pwd.h"
/* Math library interface stubs */
BigInteger
BigIntegerFromInt(n)
unsigned int n;
{
BIGNUM * a = BN_new();
BN_set_word(a, n);
return a;
}
BigInteger
BigIntegerFromBytes(bytes, length)
unsigned char * bytes;
int length;
{
BIGNUM * a = BN_new();
BN_bin2bn(bytes, length, a);
return a;
}
int
BigIntegerToBytes(src, dest)
BigInteger src;
unsigned char * dest;
{
return BN_bn2bin(src, dest);
}
int
BigIntegerCmp(c1, c2)
BigInteger c1, c2;
{
return BN_cmp(c1, c2);
}
int
BigIntegerCmpInt(c1, c2)
BigInteger c1;
unsigned int c2;
{
BIGNUM * a = BN_new();
int rv;
BN_set_word(a, c2);
rv = BN_cmp(c1, a);
BN_free(a);
return rv;
}
void
BigIntegerAdd(result, a1, a2)
BigInteger result, a1, a2;
{
BN_add(result, a1, a2);
}
void
BigIntegerAddInt(result, a1, a2)
BigInteger result, a1;
unsigned int a2;
{
BIGNUM * a = BN_new();
BN_set_word(a, a2);
BN_add(result, a1, a);
BN_free(a);
}
void
BigIntegerSub(result, s1, s2)
BigInteger result, s1, s2;
{
BN_sub(result, s1, s2);
}
void
BigIntegerMulInt(result, m1, m2)
BigInteger result, m1;
unsigned int m2;
{
BN_CTX * ctx = BN_CTX_new();
BIGNUM * m = BN_new();
BN_set_word(m, m2);
BN_mul(result, m1, m, ctx);
BN_CTX_free(ctx);
}
void
BigIntegerModMul(r, m1, m2, modulus)
BigInteger r, m1, m2, modulus;
{
BN_CTX * ctx = BN_CTX_new();
BN_mod_mul(r, m1, m2, modulus, ctx);
BN_CTX_free(ctx);
}
void
BigIntegerModExp(r, b, e, m)
BigInteger r, b, e, m;
{
BN_CTX * ctx = BN_CTX_new();
BN_mod_exp(r, b, e, m, ctx);
BN_CTX_free(ctx);
}
void
BigIntegerModExpInt(r, b, e, m)
BigInteger r, b;
unsigned int e;
BigInteger m;
{
BN_CTX * ctx = BN_CTX_new();
BIGNUM * p = BN_new();
BN_set_word(p, e);
BN_mod_exp(r, b, p, m, ctx);
BN_free(p);
BN_CTX_free(ctx);
}
void
BigIntegerFree(b)
BigInteger b;
{
BN_free(b);
}

View File

@ -0,0 +1,338 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include "t_defines.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "t_sha.h"
#ifndef NULL
#define NULL 0
#endif
static unsigned char randpool[SHA_DIGESTSIZE], randout[SHA_DIGESTSIZE];
static unsigned long randcnt = 0;
static unsigned int outpos = 0;
SHA1_CTX randctxt;
/*
* t_envhash - Generate a 160-bit SHA hash of the environment
*
* This routine performs an SHA hash of all the "name=value" pairs
* in the environment concatenated together and dumps them in the
* output. While it is true that anyone on the system can see
* your environment, someone not on the system will have a very
* difficult time guessing it, especially since some systems play
* tricks with variable ordering and sometimes define quirky
* environment variables like $WINDOWID or $_.
*/
extern char ** environ;
static void
t_envhash(out)
unsigned char * out;
{
char ** ptr;
char ebuf[256];
SHA1_CTX ctxt;
SHA1Init(&ctxt);
for(ptr = environ; *ptr; ++ptr) {
strncpy(ebuf, *ptr, 255);
ebuf[255] = '\0';
SHA1Update(&ctxt, ebuf, strlen(ebuf));
}
SHA1Final(out, &ctxt);
}
/*
* t_fshash - Generate a 160-bit SHA hash from the file system
*
* This routine climbs up the directory tree from the current
* directory, running stat() on each directory until it hits the
* root directory. This information is sensitive to the last
* access/modification times of all the directories above you,
* so someone who lists one of those directories injects some
* entropy into the system. Obviously, this hash is very sensitive
* to your current directory when the program is run.
*
* For good measure, it also performs an fstat on the standard input,
* usually your tty, throws that into the buffer, creates a file in
* /tmp (the inode is unpredictable on a busy system), and runs stat()
* on that before deleting it.
*
* The entire buffer is run once through SHA to obtain the final result.
*/
static void
t_fshash(out)
unsigned char * out;
{
char dotpath[128];
struct stat st;
SHA1_CTX ctxt;
int i, pinode;
dev_t pdev;
SHA1Init(&ctxt);
if(stat(".", &st) >= 0) {
SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
pinode = st.st_ino;
pdev = st.st_dev;
strcpy(dotpath, "..");
for(i = 0; i < 40; ++i) {
if(stat(dotpath, &st) < 0)
break;
if(st.st_ino == pinode && st.st_dev == pdev)
break;
SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
pinode = st.st_ino;
pdev = st.st_dev;
strcat(dotpath, "/..");
}
}
if(fstat(0, &st) >= 0)
SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
sprintf(dotpath, "/tmp/rnd.%d", getpid());
if(creat(dotpath, 0600) >= 0 && stat(dotpath, &st) >= 0)
SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
unlink(dotpath);
SHA1Final(out, &ctxt);
}
/*
* Generate a high-entropy seed for the strong random number generator.
* This uses a wide variety of quickly gathered and somewhat unpredictable
* system information. The 'preseed' structure is assembled from:
*
* The system time in seconds
* The system time in microseconds
* The current process ID
* The parent process ID
* A hash of the user's environment
* A hash gathered from the file system
* Input from a random device, if available
* Timings of system interrupts
*
* The entire structure (60 bytes on most systems) is fed to SHA to produce
* a 160-bit seed for the strong random number generator. It is believed
* that in the worst case (on a quiet system with no random device versus
* an attacker who has access to the system already), the seed contains at
* least about 80 bits of entropy. Versus an attacker who does not have
* access to the system, the entropy should be slightly over 128 bits.
*/
static char initialized = 0;
static struct {
unsigned int trand1;
time_t sec;
time_t usec;
short pid;
short ppid;
unsigned char envh[SHA_DIGESTSIZE];
unsigned char fsh[SHA_DIGESTSIZE];
unsigned char devrand[20];
unsigned int trand2;
} preseed;
unsigned long raw_truerand();
void
t_initrand()
{
SHA1_CTX ctxt;
#ifdef USE_FTIME
struct timeb t;
#else
struct timeval t;
#endif
int i, r=0;
if(initialized)
return;
initialized = 1;
i = open("/dev/urandom", O_RDONLY);
if(i > 0) {
r += read(i, preseed.devrand, sizeof(preseed.devrand));
close(i);
}
/* Resort to truerand only if desperate for some Real entropy */
if(r == 0)
preseed.trand1 = raw_truerand();
#ifdef USE_FTIME
ftime(&t);
#else
gettimeofday(&t, NULL);
#endif
#ifdef USE_FTIME
preseed.sec = t.time;
preseed.usec = t.millitm;
#else
preseed.sec = t.tv_sec;
preseed.usec = t.tv_usec;
#endif
preseed.pid = getpid();
preseed.ppid = getppid();
t_envhash(preseed.envh);
t_fshash(preseed.fsh);
if(r == 0)
preseed.trand2 = raw_truerand();
SHA1Init(&ctxt);
SHA1Update(&ctxt, (unsigned char *) &preseed, sizeof(preseed));
SHA1Final(randpool, &ctxt);
outpos = 0;
memset((unsigned char *) &preseed, 0, sizeof(preseed));
memset((unsigned char *) &ctxt, 0, sizeof(ctxt));
}
#define NUM_RANDOMS 12
/*
* The strong random number generator. This uses a 160-bit seed
* and uses SHA-1 in a feedback configuration to generate successive
* outputs. If S[0] is set to the initial seed, then:
*
* S[i+1] = SHA-1(i || S[i])
* A[i] = SHA-1(S[i])
*
* where the A[i] are the output blocks starting with i=0.
* Each cycle generates 20 bytes of new output.
*/
_TYPE( void )
t_random(data, size)
unsigned char * data;
unsigned size;
{
if(!initialized)
t_initrand();
if(size <= 0) /* t_random(NULL, 0) forces seed initialization */
return;
while(size > outpos) {
if(outpos > 0) {
memcpy(data, randout + (sizeof(randout) - outpos), outpos);
data += outpos;
size -= outpos;
}
/* Recycle */
SHA1Init(&randctxt);
SHA1Update(&randctxt, randpool, sizeof(randpool));
SHA1Final(randout, &randctxt);
SHA1Init(&randctxt);
SHA1Update(&randctxt, (unsigned char *) &randcnt, sizeof(randcnt));
SHA1Update(&randctxt, randpool, sizeof(randpool));
SHA1Final(randpool, &randctxt);
++randcnt;
outpos = sizeof(randout);
}
if(size > 0) {
memcpy(data, randout + (sizeof(randout) - outpos), size);
outpos -= size;
}
}
/*
* The interleaved session-key hash. This separates the even and the odd
* bytes of the input (ignoring the first byte if the input length is odd),
* hashes them separately, and re-interleaves the two outputs to form a
* single 320-bit value.
*/
_TYPE( unsigned char * )
t_sessionkey(key, sk, sklen)
unsigned char * key;
unsigned char * sk;
unsigned sklen;
{
unsigned i, klen;
unsigned char * hbuf;
unsigned char hout[SHA_DIGESTSIZE];
SHA1_CTX ctxt;
while(sklen > 0 && *sk == 0) { /* Skip leading 0's */
--sklen;
++sk;
}
klen = sklen / 2;
if((hbuf = malloc(klen * sizeof(char))) == 0)
return 0;
for(i = 0; i < klen; ++i)
hbuf[i] = sk[sklen - 2 * i - 1];
SHA1Init(&ctxt);
SHA1Update(&ctxt, hbuf, klen);
SHA1Final(hout, &ctxt);
for(i = 0; i < sizeof(hout); ++i)
key[2 * i] = hout[i];
for(i = 0; i < klen; ++i)
hbuf[i] = sk[sklen - 2 * i - 2];
SHA1Init(&ctxt);
SHA1Update(&ctxt, hbuf, klen);
SHA1Final(hout, &ctxt);
for(i = 0; i < sizeof(hout); ++i)
key[2 * i + 1] = hout[i];
memset(hout, 0, sizeof(hout));
memset(hbuf, 0, klen);
free(hbuf);
return key;
}

View File

@ -0,0 +1,262 @@
/*
* Copyright (c) 1997-2000 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include "t_defines.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef USE_HOMEDIR
#include <pwd.h>
#endif
#ifdef WIN32
#include <io.h>
#endif
#include "t_pwd.h"
#include "t_read.h"
#include "t_sha.h"
#include "t_server.h"
static struct t_pw * syspw = NULL;
static struct t_passwd tpass;
_TYPE( struct t_server * )
t_serveropen(username)
const char * username;
{
struct t_passwd * p;
p = gettpnam(username);
if(p == NULL) {
return NULL;
} else {
return t_serveropenraw(&p->tp, &p->tc);
}
}
/* t_openpw(NULL) is deprecated - use settpent()/gettpnam() instead */
_TYPE( struct t_pw * )
t_openpw(fp)
FILE * fp;
{
struct t_pw * tpw;
char close_flag = 0;
if(fp == NULL) { /* Deprecated */
if((fp = fopen(DEFAULT_PASSWD, "r")) == NULL)
return NULL;
close_flag = 1;
}
else
close_flag = 0;
if((tpw = malloc(sizeof(struct t_pw))) == NULL)
return NULL;
tpw->instream = fp;
tpw->close_on_exit = close_flag;
tpw->state = FILE_ONLY;
return tpw;
}
_TYPE( struct t_pw * )
t_openpwbyname(pwname)
const char * pwname;
{
FILE * fp;
struct t_pw * t;
if(pwname == NULL) /* Deprecated */
return t_openpw(NULL);
if((fp = fopen(pwname, "r")) == NULL)
return NULL;
t = t_openpw(fp);
t->close_on_exit = 1;
return t;
}
_TYPE( void )
t_closepw(tpw)
struct t_pw * tpw;
{
if(tpw->close_on_exit)
fclose(tpw->instream);
free(tpw);
}
_TYPE( void )
t_rewindpw(tpw)
struct t_pw * tpw;
{
#ifdef ENABLE_YP
if(tpw->state == IN_NIS)
tpw->state = FILE_NIS;
#endif
rewind(tpw->instream);
}
#ifdef ENABLE_YP
static void
savepwent(tpw, pwent)
struct t_pw * tpw;
struct t_pwent *pwent;
{
tpw->pebuf.name = tpw->userbuf;
tpw->pebuf.password.data = tpw->pwbuf;
tpw->pebuf.salt.data = tpw->saltbuf;
strcpy(tpw->pebuf.name, pwent->name);
tpw->pebuf.password.len = pwent->password.len;
memcpy(tpw->pebuf.password.data, pwent->password.data, pwent->password.len);
tpw->pebuf.salt.len = pwent->salt.len;
memcpy(tpw->pebuf.salt.data, pwent->salt.data, pwent->salt.len);
tpw->pebuf.index = pwent->index;
}
#endif /* ENABLE_YP */
_TYPE( struct t_pwent * )
t_getpwbyname(tpw, user)
struct t_pw * tpw;
const char * user;
{
char indexbuf[16];
char passbuf[MAXB64PARAMLEN];
char saltstr[MAXB64SALTLEN];
char username[MAXUSERLEN];
#ifdef ENABLE_YP
struct t_passwd * nisent;
#endif
t_rewindpw(tpw);
while(t_nextfield(tpw->instream, username, MAXUSERLEN) > 0) {
#ifdef ENABLE_YP
if(tpw->state == FILE_NIS && *username == '+') {
if(strlen(username) == 1 || strcmp(user, username+1) == 0) {
nisent = _yp_gettpnam(user); /* Entry is +username or + */
if(nisent != NULL) {
savepwent(tpw, &nisent->tp);
return &tpw->pebuf;
}
}
}
#endif
if(strcmp(user, username) == 0)
if(t_nextfield(tpw->instream, passbuf, MAXB64PARAMLEN) > 0 &&
(tpw->pebuf.password.len = t_fromb64(tpw->pwbuf, passbuf)) > 0 &&
t_nextfield(tpw->instream, saltstr, MAXB64SALTLEN) > 0 &&
(tpw->pebuf.salt.len = t_fromb64(tpw->saltbuf, saltstr)) > 0 &&
t_nextfield(tpw->instream, indexbuf, 16) > 0 &&
(tpw->pebuf.index = atoi(indexbuf)) > 0) {
strcpy(tpw->userbuf, username);
tpw->pebuf.name = tpw->userbuf;
tpw->pebuf.password.data = tpw->pwbuf;
tpw->pebuf.salt.data = tpw->saltbuf;
t_nextline(tpw->instream);
return &tpw->pebuf;
}
if(t_nextline(tpw->instream) < 0)
return NULL;
}
return NULL;
}
/* System password file accessors */
static int
pwinit()
{
if(syspw == NULL) {
if((syspw = t_openpwbyname(DEFAULT_PASSWD)) == NULL)
return -1;
syspw->state = FILE_NIS;
}
return 0;
}
static void
pwsetup(out, tpwd, tcnf)
struct t_passwd * out;
struct t_pwent * tpwd;
struct t_confent * tcnf;
{
out->tp.name = tpwd->name;
out->tp.password.len = tpwd->password.len;
out->tp.password.data = tpwd->password.data;
out->tp.salt.len = tpwd->salt.len;
out->tp.salt.data = tpwd->salt.data;
out->tp.index = tpwd->index;
out->tc.index = tcnf->index;
out->tc.modulus.len = tcnf->modulus.len;
out->tc.modulus.data = tcnf->modulus.data;
out->tc.generator.len = tcnf->generator.len;
out->tc.generator.data = tcnf->generator.data;
}
_TYPE( struct t_passwd * )
gettpnam
(user)
const char * user;
{
struct t_pwent * tpptr;
struct t_confent * tcptr;
if(pwinit() < 0)
return NULL;
tpptr = t_getpwbyname(syspw, user);
if(tpptr == NULL)
return NULL;
tcptr =
gettcid
(tpptr->index);
if(tcptr == NULL)
return NULL;
pwsetup(&tpass, tpptr, tcptr);
return &tpass;
}

View File

@ -0,0 +1,310 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#ifndef T_PWD_H
#define T_PWD_H
#ifndef P
#if defined (__STDC__) || defined (__cplusplus)
#define P(x) x
#else
#define P(x) ()
#endif
#endif
/* For building dynamic link libraries under windows, windows NT
* using MSVC1.5 or MSVC2.0
*/
#ifndef _DLLDECL
#define _DLLDECL
#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
#define _MSVC15EXPORT _export
#define _MSVC20EXPORT
#define _DLLAPI _export _pascal
#define _TYPE(a) a _MSVC15EXPORT
#define DLLEXPORT 1
#elif MSVC20
#define _MSVC15EXPORT
#define _MSVC20EXPORT _declspec(dllexport)
#define _DLLAPI
#define _TYPE(a) _MSVC20EXPORT a
#define DLLEXPORT 1
#else /* Default, non-dll. Use this for Unix or DOS */
#define _MSVC15DEXPORT
#define _MSVC20EXPORT
#define _DLLAPI
#define _TYPE(a) a
#endif
#endif
#define MAXPARAMBITS 2048
#define MAXPARAMLEN ((MAXPARAMBITS + 7) / 8)
#define MAXB64PARAMLEN ((MAXPARAMBITS + 5) / 6 + 1)
#define MAXHEXPARAMLEN ((MAXPARAMBITS + 3) / 4 + 1)
#define MAXOCTPARAMLEN ((MAXPARAMBITS + 2) / 3 + 1)
#define MAXUSERLEN 32
#define MAXSALTLEN 32
#define MAXB64SALTLEN 44 /* 256 bits in b64 + null */
#define SALTLEN 10 /* Normally 80 bits */
#define RESPONSE_LEN 20 /* 160-bit proof hashes */
#define SESSION_KEY_LEN (2 * RESPONSE_LEN) /* 320-bit session key */
#define DEFAULT_PASSWD "tpasswd"
struct t_num { /* Standard byte-oriented integer representation */
int len;
unsigned char * data;
};
struct t_preconf { /* Structure returned by t_getpreparam() */
char * mod_b64;
char * gen_b64;
char * comment;
struct t_num modulus;
struct t_num generator;
};
/*
* The built-in (known good) parameters access routines
*
* "t_getprecount" returns the number of precompiled parameter sets.
* "t_getpreparam" returns the indicated parameter set.
* Memory is statically allocated - callers need not perform any memory mgmt.
*/
_TYPE( int ) t_getprecount();
_TYPE( struct t_preconf * ) t_getpreparam P((int));
struct t_confent { /* One configuration file entry (index, N, g) */
int index;
struct t_num modulus;
struct t_num generator;
};
struct t_conf { /* An open configuration file */
FILE * instream;
char close_on_exit;
unsigned char modbuf[MAXPARAMLEN];
unsigned char genbuf[MAXPARAMLEN];
struct t_confent tcbuf;
};
/*
* The configuration file routines are designed along the lines of the
* "getpw" functions in the standard C library.
*
* "t_openconf" accepts a stdio stream and interprets it as a config file.
* "t_openconfbyname" accepts a filename and does the same thing.
* "t_closeconf" closes the config file.
* "t_getconfent" fetches the next sequential configuration entry.
* "t_getconfbyindex" fetches the configuration entry whose index
* matches the one supplied, or NULL if one can't be found.
* "t_getconflast" fetches the last configuration entry in the file.
* "t_makeconfent" generates a set of configuration entry parameters
* randomly.
* "t_newconfent" returns an empty configuration entry.
* "t_cmpconfent" compares two configuration entries a la strcmp.
* "t_checkconfent" verifies that a set of configuration parameters
* are suitable. N must be prime and should be a safe prime.
* "t_putconfent" writes a configuration entry to a stream.
*/
_TYPE( struct t_conf * ) t_openconf P((FILE *));
_TYPE( struct t_conf * ) t_openconfbyname P((const char *));
_TYPE( void ) t_closeconf P((struct t_conf *));
_TYPE( void ) t_rewindconf P((struct t_conf *));
_TYPE( struct t_confent * ) t_getconfent P((struct t_conf *));
_TYPE( struct t_confent * ) t_getconfbyindex P((struct t_conf *, int));
_TYPE( struct t_confent * ) t_getconflast P((struct t_conf *));
_TYPE( struct t_confent * ) t_makeconfent P((struct t_conf *, int));
_TYPE( struct t_confent * ) t_makeconfent_c P((struct t_conf *, int));
_TYPE( struct t_confent * ) t_newconfent P((struct t_conf *));
_TYPE( int ) t_cmpconfent P((const struct t_confent *, const struct t_confent *));
_TYPE( int ) t_checkconfent P((const struct t_confent *));
_TYPE( void ) t_putconfent P((const struct t_confent *, FILE *));
/* libc-style system conf file access */
_TYPE( struct t_confent *) gettcent();
_TYPE( struct t_confent *) gettcid P((int));
_TYPE( void ) settcent();
_TYPE( void ) endtcent();
#ifdef ENABLE_NSW
extern struct t_confent * _gettcent();
extern struct t_confent * _gettcid P((int));
extern void _settcent();
extern void _endtcent();
#endif
/* A hack to support '+'-style entries in the passwd file */
typedef enum fstate {
FILE_ONLY, /* Ordinary file, don't consult NIS ever */
FILE_NIS, /* Currently accessing file, use NIS if encountered */
IN_NIS, /* Currently in a '+' entry; use NIS for getXXent */
} FILE_STATE;
struct t_pwent { /* A single password file entry */
char * name;
struct t_num password;
struct t_num salt;
int index;
};
struct t_pw { /* An open password file */
FILE * instream;
char close_on_exit;
FILE_STATE state;
char userbuf[MAXUSERLEN];
unsigned char pwbuf[MAXPARAMLEN];
unsigned char saltbuf[SALTLEN];
struct t_pwent pebuf;
};
/*
* The password manipulation routines are patterned after the getpw*
* standard C library function calls.
*
* "t_openpw" reads a stream as if it were a password file.
* "t_openpwbyname" opens the named file as a password file.
* "t_closepw" closes an open password file.
* "t_rewindpw" starts the internal file pointer from the beginning
* of the password file.
* "t_getpwent" retrieves the next sequential password entry.
* "t_getpwbyname" looks up the password entry corresponding to the
* specified user.
* "t_makepwent" constructs a password entry from a username, password,
* numeric salt, and configuration entry.
* "t_putpwent" writes a password entry to a stream.
*/
_TYPE( struct t_pw * ) t_openpw P((FILE *));
_TYPE( struct t_pw * ) t_openpwbyname P((const char *));
_TYPE( void ) t_closepw P((struct t_pw *));
_TYPE( void ) t_rewindpw P((struct t_pw *));
_TYPE( struct t_pwent * ) t_getpwent P((struct t_pw *));
_TYPE( struct t_pwent * ) t_getpwbyname P((struct t_pw *, const char *));
_TYPE( struct t_pwent * ) t_makepwent P((struct t_pw *, const char *,
const char *, const struct t_num *,
const struct t_confent *));
_TYPE( void ) t_putpwent P((const struct t_pwent *, FILE *));
struct t_passwd {
struct t_pwent tp;
struct t_confent tc;
};
/* libc-style system password file access */
_TYPE( struct t_passwd * ) gettpent();
_TYPE( struct t_passwd * ) gettpnam P((const char *));
_TYPE( void ) settpent();
_TYPE( void ) endtpent();
#ifdef ENABLE_NSW
extern struct t_passwd * _gettpent();
extern struct t_passwd * _gettpnam P((const char *));
extern void _settpent();
extern void _endtpent();
#endif
/*
* Utility functions
*
* "t_verifypw" accepts a username and password, and checks against the
* system password file to see if the password for that user is correct.
* Returns > 0 if it is correct, 0 if not, and -1 if some error occurred
* (i.e. the user doesn't exist on the system). This is intended ONLY
* for local authentication; for remote authentication, look at the
* t_client and t_server source. (That's the whole point of SRP!)
* "t_changepw" modifies the specified file, substituting the given password
* entry for the one already in the file. If no matching entry is found,
* the new entry is simply appended to the file.
* "t_deletepw" removes the specified user from the specified file.
*/
_TYPE( int ) t_verifypw P((const char *, const char *));
_TYPE( int ) t_changepw P((const char *, const struct t_pwent *));
_TYPE( int ) t_deletepw P((const char *, const char *));
/* Conversion utilities */
/*
* All these calls accept output as the first parameter. In the case of
* t_tohex and t_tob64, the last argument is the length of the byte-string
* input.
*/
_TYPE( char * t_tohex ) P((char *, char *, unsigned));
_TYPE( int ) t_fromhex P((char *, char *));
_TYPE( char * ) t_tob64 P((char *, char *, unsigned));
_TYPE( int ) t_fromb64 P((char *, char *));
/* Miscellaneous utilities */
/*
* "t_random" is a cryptographic random number generator, which is seeded
* from various high-entropy sources and uses a one-way hash function
* in a feedback configuration.
* "t_sessionkey" is the interleaved hash used to generate session keys
* from a large integer.
* "t_getpass" reads a password from the terminal without echoing.
*/
_TYPE( void ) t_random P((unsigned char *, unsigned));
_TYPE( void ) t_stronginitrand();
_TYPE( unsigned char * )
t_sessionkey P((unsigned char *, unsigned char *, unsigned));
_TYPE( int ) t_getpass P((char *, unsigned, const char *));
/*
* Return value of t_checkprime:
* < 0 : not prime
* = 0 : prime, but not safe
* > 0 : safe
*/
#define NUM_NOTPRIME -1
#define NUM_NOTSAFE 0
#define NUM_SAFE 1
_TYPE( int ) t_checkprime P((const struct t_num *));
#endif

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include <stdio.h>
#include "config.h"
#define FSEPARATOR ':'
int
t_nextfield(fp, s, max)
FILE * fp;
char * s;
unsigned max;
{
int c, count = 0;
while((c = getc(fp)) != EOF) {
if(c == '\n') {
ungetc(c, fp);
break;
}
else if(c == FSEPARATOR)
break;
if(count < max - 1) {
*s++ = c;
++count;
}
}
*s++ = '\0';
return count;
}
int
t_nextline(fp)
FILE * fp;
{
int c;
while((c = getc(fp)) != '\n')
if(c == EOF)
return -1;
return 0;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#ifndef _T_READ_H_
#define _T_READ_H_
#if !defined(P)
#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
#endif
#endif
extern int t_nextfield P((FILE *, char *, unsigned));
extern int t_nextline P((FILE *));
#endif

View File

@ -0,0 +1,259 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include <stdio.h>
#include "t_defines.h"
#include "t_pwd.h"
#include "t_server.h"
_TYPE( struct t_server * )
t_serveropenraw(ent, tce)
struct t_pwent * ent;
struct t_confent * tce;
{
struct t_server * ts;
unsigned char buf1[SHA_DIGESTSIZE], buf2[SHA_DIGESTSIZE];
SHA1_CTX ctxt;
int i;
if((ts = malloc(sizeof(struct t_server))) == 0)
return 0;
SHA1Init(&ts->ckhash);
ts->index = ent->index;
ts->n.len = tce->modulus.len;
ts->n.data = ts->nbuf;
memcpy(ts->n.data, tce->modulus.data, ts->n.len);
SHA1Init(&ctxt);
SHA1Update(&ctxt, ts->n.data, ts->n.len);
SHA1Final(buf1, &ctxt);
ts->g.len = tce->generator.len;
ts->g.data = ts->gbuf;
memcpy(ts->g.data, tce->generator.data, ts->g.len);
SHA1Init(&ctxt);
SHA1Update(&ctxt, ts->g.data, ts->g.len);
SHA1Final(buf2, &ctxt);
for(i = 0; i < sizeof(buf1); ++i)
buf1[i] ^= buf2[i];
SHA1Update(&ts->ckhash, buf1, sizeof(buf1));
SHA1Init(&ctxt);
SHA1Update(&ctxt, ent->name, strlen(ent->name));
SHA1Final(buf1, &ctxt);
SHA1Update(&ts->ckhash, buf1, sizeof(buf1));
ts->v.len = ent->password.len;
ts->v.data = ts->vbuf;
memcpy(ts->v.data, ent->password.data, ts->v.len);
ts->s.len = ent->salt.len;
ts->s.data = ts->saltbuf;
memcpy(ts->s.data, ent->salt.data, ts->s.len);
SHA1Update(&ts->ckhash, ts->s.data, ts->s.len);
ts->b.data = ts->bbuf;
ts->B.data = ts->Bbuf;
SHA1Init(&ts->hash);
SHA1Init(&ts->oldhash);
SHA1Init(&ts->oldckhash);
return ts;
}
_TYPE( struct t_num * )
t_servergenexp(ts)
struct t_server * ts;
{
BigInteger b, B, v, n, g;
if(ts->n.len < BLEN)
ts->b.len = ts->n.len;
else
ts->b.len = BLEN;
t_random(ts->b.data, ts->b.len);
b = BigIntegerFromBytes(ts->b.data, ts->b.len);
n = BigIntegerFromBytes(ts->n.data, ts->n.len);
g = BigIntegerFromBytes(ts->g.data, ts->g.len);
B = BigIntegerFromInt(0);
BigIntegerModExp(B, g, b, n);
v = BigIntegerFromBytes(ts->v.data, ts->v.len);
BigIntegerAdd(B, B, v);
if(BigIntegerCmp(B, n) > 0)
BigIntegerSub(B, B, n);
ts->B.len = BigIntegerToBytes(B, ts->B.data);
BigIntegerFree(v);
BigIntegerFree(B);
BigIntegerFree(b);
BigIntegerFree(g);
BigIntegerFree(n);
SHA1Update(&ts->oldckhash, ts->B.data, ts->B.len);
return &ts->B;
}
_TYPE( unsigned char * )
t_servergetkey(ts, clientval)
struct t_server * ts;
struct t_num * clientval;
{
BigInteger n, v, A, b, prod, res, S;
SHA1_CTX ctxt;
unsigned char sbuf[MAXPARAMLEN];
unsigned char dig[SHA_DIGESTSIZE];
unsigned slen;
unsigned int u;
SHA1Update(&ts->ckhash, clientval->data, clientval->len);
SHA1Update(&ts->ckhash, ts->B.data, ts->B.len);
SHA1Init(&ctxt);
SHA1Update(&ctxt, ts->B.data, ts->B.len);
SHA1Final(dig, &ctxt);
u = (dig[0] << 24) | (dig[1] << 16) | (dig[2] << 8) | dig[3];
SHA1Update(&ts->oldhash, clientval->data, clientval->len);
SHA1Update(&ts->hash, clientval->data, clientval->len);
n = BigIntegerFromBytes(ts->n.data, ts->n.len);
b = BigIntegerFromBytes(ts->b.data, ts->b.len);
v = BigIntegerFromBytes(ts->v.data, ts->v.len);
A = BigIntegerFromBytes(clientval->data, clientval->len);
prod = BigIntegerFromInt(0);
BigIntegerModExpInt(prod, v, u, n);
res = BigIntegerFromInt(0);
BigIntegerModMul(res, prod, A, n);
BigIntegerFree(A);
BigIntegerFree(v);
BigIntegerFree(prod);
if(BigIntegerCmpInt(res, 1) <= 0) { /* Check for Av^u == 1 (mod n) */
BigIntegerFree(res);
BigIntegerFree(b);
BigIntegerFree(n);
return NULL;
}
S = BigIntegerFromInt(0);
BigIntegerAddInt(S, res, 1);
if(BigIntegerCmp(S, n) == 0) { /* Check for Av^u == -1 (mod n) */
BigIntegerFree(res);
BigIntegerFree(b);
BigIntegerFree(n);
BigIntegerFree(S);
return NULL;
}
BigIntegerModExp(S, res, b, n);
slen = BigIntegerToBytes(S, sbuf);
BigIntegerFree(S);
BigIntegerFree(res);
BigIntegerFree(b);
BigIntegerFree(n);
t_sessionkey(ts->session_key, sbuf, slen);
memset(sbuf, 0, slen);
SHA1Update(&ts->oldhash, ts->session_key, sizeof(ts->session_key));
SHA1Update(&ts->oldckhash, ts->session_key, sizeof(ts->session_key));
SHA1Update(&ts->ckhash, ts->session_key, sizeof(ts->session_key));
return ts->session_key;
}
_TYPE( int )
t_serververify(ts, resp)
struct t_server * ts;
unsigned char * resp;
{
unsigned char expected[SHA_DIGESTSIZE];
int i;
SHA1Final(expected, &ts->oldckhash);
i = memcmp(expected, resp, sizeof(expected));
if(i == 0) {
SHA1Final(ts->session_response, &ts->oldhash);
return 0;
}
SHA1Final(expected, &ts->ckhash);
i = memcmp(expected, resp, sizeof(expected));
if(i == 0) {
SHA1Update(&ts->hash, expected, sizeof(expected));
SHA1Update(&ts->hash, ts->session_key, sizeof(ts->session_key));
SHA1Final(ts->session_response, &ts->hash);
}
return i;
}
_TYPE( unsigned char * )
t_serverresponse(ts)
struct t_server * ts;
{
return ts->session_response;
}
_TYPE( void )
t_serverclose(ts)
struct t_server * ts;
{
memset(ts->bbuf, 0, sizeof(ts->bbuf));
memset(ts->vbuf, 0, sizeof(ts->vbuf));
memset(ts->saltbuf, 0, sizeof(ts->saltbuf));
memset(ts->session_key, 0, sizeof(ts->session_key));
free(ts);
}

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 1997-1999 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#ifndef T_SERVER_H
#define T_SERVER_H
#include "t_sha.h"
#if !defined(P)
#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
#endif
#endif
#ifndef _DLLDECL
#define _DLLDECL
#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
#define _MSVC15EXPORT _export
#define _MSVC20EXPORT
#define _DLLAPI _export _pascal
#define _TYPE(a) a _MSVC15EXPORT
#define DLLEXPORT 1
#elif MSVC20
#define _MSVC15EXPORT
#define _MSVC20EXPORT _declspec(dllexport)
#define _DLLAPI
#define _TYPE(a) _MSVC20EXPORT a
#define DLLEXPORT 1
#else /* Default, non-dll. Use this for Unix or DOS */
#define _MSVC15DEXPORT
#define _MSVC20EXPORT
#define _DLLAPI
#define _TYPE(a) a
#endif
#endif
#define BLEN 32
struct t_server {
int index;
struct t_num n;
struct t_num g;
struct t_num v;
struct t_num s;
struct t_num b;
struct t_num B;
SHA1_CTX oldhash, hash, oldckhash, ckhash;
unsigned char session_key[SESSION_KEY_LEN];
unsigned char session_response[RESPONSE_LEN];
unsigned char nbuf[MAXPARAMLEN], gbuf[MAXPARAMLEN], vbuf[MAXPARAMLEN];
unsigned char saltbuf[MAXSALTLEN], bbuf[BLEN], Bbuf[MAXPARAMLEN];
};
/*
* SRP server-side negotiation
*
* This code negotiates the server side of an SRP exchange.
* "t_serveropen" accepts a username (sent by the client), a pointer
* to an open password file, and a pointer to an open configuration
* file. The server should then call...
* "t_servergenexp" will generate a random 256-bit exponent and
* raise g (from the configuration file) to that power, returning
* the result. This result should be sent to the client as y(p).
* "t_servergetkey" accepts the exponential w(p), which should be
* sent by the client, and computes the 256-bit session key.
* This data should be saved before the session is closed.
* "t_serverresponse" computes the session key proof as SHA(w(p), K).
* "t_serverclose" closes the session and frees its memory.
*
* Note that authentication is not performed per se; it is up
* to either/both sides of the protocol to now verify securely
* that their session keys agree in order to establish authenticity.
* One possible way is through "oracle hashing"; one side sends
* r, the other replies with H(r,K), where H() is a hash function.
*
* t_serverresponse and t_serververify now implement a version of
* the session-key verification described above.
*/
_TYPE( struct t_server * )
t_serveropen P((const char *));
_TYPE( struct t_server * )
t_serveropenfromfiles P((const char *, struct t_pw *, struct t_conf *));
_TYPE( struct t_server * )
t_serveropenraw P((struct t_pwent *, struct t_confent *));
_TYPE( struct t_num * ) t_servergenexp P((struct t_server *));
_TYPE( unsigned char * ) t_servergetkey P((struct t_server *, struct t_num *));
_TYPE( int ) t_serververify P((struct t_server *, unsigned char *));
_TYPE( unsigned char * ) t_serverresponse P((struct t_server *));
_TYPE( void ) t_serverclose P((struct t_server *));
#endif

View File

@ -0,0 +1,166 @@
#include "t_defines.h"
#include "t_sha.h"
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define WORDS_BIGENDIAN * This should be #define'd if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#include <stdio.h>
#include <string.h>
static void SHA1Transform(uint32 state[5], const unsigned char buffer[64]);
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifndef WORDS_BIGENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
static void SHA1Transform(uint32 state[5], const unsigned char buffer[64])
{
uint32 a, b, c, d, e;
typedef union {
unsigned char c[64];
uint32 l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
#ifdef SHA1HANDSOFF
static unsigned char workspace[64];
block = (CHAR64LONG16*)workspace;
memcpy(block, buffer, 64);
#else
block = (CHAR64LONG16*)buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/* SHA1Init - Initialize new context */
void SHA1Init(SHA1_CTX* context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len)
{
unsigned int i, j;
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
{
uint32 i, j;
unsigned char finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
SHA1Update(context, (unsigned char *)"\200", 1);
while ((context->count[0] & 504) != 448) {
SHA1Update(context, (unsigned char *)"\0", 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++) {
digest[i] = (unsigned char)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
/* Wipe variables */
i = j = 0;
memset(context->buffer, 0, 64);
memset(context->state, 0, 20);
memset(context->count, 0, 8);
memset(&finalcount, 0, 8);
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */
SHA1Transform(context->state, context->buffer);
#endif
}

View File

@ -0,0 +1,26 @@
#ifndef T_SHA_H
#define T_SHA_H
#if !defined(P)
#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
#endif
#endif
#define SHA_DIGESTSIZE 20
typedef unsigned int uint32;
typedef struct {
uint32 state[5];
uint32 count[2];
unsigned char buffer[64];
} SHA1_CTX;
void SHA1Init P((SHA1_CTX* context));
void SHA1Update P((SHA1_CTX* context, const unsigned char* data, unsigned int len));
void SHA1Final P((unsigned char digest[20], SHA1_CTX* context));
#endif /* T_SHA_H */

View File

@ -0,0 +1,151 @@
/*
* Physically random numbers (very nearly uniform)
* D. P. Mitchell
* Modified by Matt Blaze 7/95
*/
/*
* The authors of this software are Don Mitchell and Matt Blaze.
* Copyright (c) 1995 by AT&T.
* Permission to use, copy, and modify this software without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software and in all copies of the supporting
* documentation for such software.
*
* This software may be subject to United States export controls.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
/*
* WARNING: depending on the particular platform, raw_truerand()
* output may be biased or correlated. In general, you can expect
* about 16 bits of "pseudo-entropy" out of each 32 bit word returned
* by truerand(), but it may not be uniformly diffused. You should
* raw_therefore run the output through some post-whitening function
* (like MD5 or DES or whatever) before using it to generate key
* material. (RSAREF's random package does this for you when you feed
* raw_truerand() bits to the seed input function.)
*
* The application interface, for 8, 16, and 32 bit properly "whitened"
* random numbers, can be found in trand8(), trand16(), and trand32().
* Use those instead of calling raw_truerand() directly.
*
* The basic idea here is that between clock "skew" and various
* hard-to-predict OS event arrivals, counting a tight loop will yield
* a little (maybe a third of a bit or so) of "good" randomness per
* interval clock tick. This seems to work well even on unloaded
* machines. If there is a human operator at the machine, you should
* augment truerand with other measure, like keyboard event timing.
* On server machines (e.g., when you need to generate a
* Diffie-Hellman secret) truerand alone may be good enough.
*
* Test these assumptions on your own platform before fielding a
* system based on this software or these techniques.
*
* This software seems to work well (at 10 or so bits per
* raw_truerand() call) on a Sun Sparc-20 under SunOS 4.1.3 and on a
* P100 under BSDI 2.0. You're on your own elsewhere.
*
*/
#include "t_defines.h"
#include <signal.h>
#include <setjmp.h>
#include <sys/time.h>
#include <math.h>
#include <stdio.h>
#ifdef OLD_TRUERAND
static jmp_buf env;
#endif
static unsigned volatile count
#ifndef OLD_TRUERAND
, done = 0
#endif
;
static unsigned ocount;
static unsigned buffer;
static void
tick()
{
struct itimerval it, oit;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
it.it_value.tv_sec = 0;
it.it_value.tv_usec = 16665;
if (setitimer(ITIMER_REAL, &it, &oit) < 0)
perror("tick");
}
static void
interrupt()
{
if (count) {
#ifdef OLD_TRUERAND
longjmp(env, 1);
#else
++done;
return;
#endif
}
(void) signal(SIGALRM, interrupt);
tick();
}
static unsigned long
roulette()
{
#ifdef OLD_TRUERAND
if (setjmp(env)) {
count ^= (count>>3) ^ (count>>6) ^ ocount;
count &= 0x7;
ocount=count;
buffer = (buffer<<3) ^ count;
return buffer;
}
#else
done = 0;
#endif
(void) signal(SIGALRM, interrupt);
count = 0;
tick();
#ifdef OLD_TRUERAND
for (;;)
#else
while(done == 0)
#endif
count++; /* about 1 MHz on VAX 11/780 */
#ifndef OLD_TRUERAND
count ^= (count>>3) ^ (count>>6) ^ ocount;
count &= 0x7;
ocount=count;
buffer = (buffer<<3) ^ count;
return buffer;
#endif
}
unsigned long
raw_truerand()
{
count=0;
(void) roulette();
(void) roulette();
(void) roulette();
(void) roulette();
(void) roulette();
(void) roulette();
(void) roulette();
(void) roulette();
(void) roulette();
(void) roulette();
return roulette();
}

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 1997-2000 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following conditions apply:
*
* 1. Any software that incorporates the SRP authentication technology
* must display the following acknowlegment:
* "This product uses the 'Secure Remote Password' cryptographic
* authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
*
* 2. Any software that incorporates all or part of the SRP distribution
* itself must also display the following acknowledgment:
* "This product includes software developed by Tom Wu and Eugene
* Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
*
* 3. Redistributions in source or binary form must retain an intact copy
* of this copyright notice and list of conditions.
*/
#include <unistd.h> /* close getlogin */
#include <stdlib.h> /* atexit exit */
#include <stdio.h>
#include <string.h>
#include "t_pwd.h"
#define MIN_BASIS_BITS 512
#define BASIS_BITS 2048
extern int optind;
extern char *optarg;
extern int errno;
char *progName;
int debug = 0;
int verbose = 0;
int composite = 0;
int main(argc, argv)
int argc;
char *argv[];
{
char *chp;
char *configFile = NULL;
char cbuf[256];
char b64buf[MAXB64PARAMLEN];
int c, ch, i, lastidx, keylen, yesno, fsize, status, nparams;
FILE *efp;
struct t_preconf * tpc;
struct t_conf tcs;
struct t_conf * tc = &tcs;
struct t_confent * tcent;
progName = *argv;
if ((chp = strrchr(progName, '/')) != (char *) 0) progName = chp + 1;
while ((ch = getopt(argc, argv, "dv2c:")) != EOF)
switch(ch) {
case 'c':
configFile = optarg;
break;
case 'v':
verbose++;
break;
case 'd':
debug++;
break;
case '2':
composite++;
break;
default:
fprintf(stderr, "usage: %s [-dv2] [-c configfile]\n", progName);
exit(1);
}
argc -= optind;
argv += optind;
lastidx = 0;
keylen = 0;
tcent = t_newconfent(tc);
printf("\nThis program will generate a set of parameters for the EPS\n");
printf("password file. The size of these parameters, measured in bits,\n");
printf("determines the level of security offered by SRP, and is related\n");
printf("to the security of similarly-sized RSA or Diffie-Hellman keys.\n");
printf("Choosing a predefined field is generally preferable to generating\n");
printf("a new field because clients can avoid costly parameter verification.\n");
printf("Either way, the values generated by this program are public and\n");
printf("can even shared between systems.\n");
printf("\nEnter the new field size, in bits. Suggested sizes:\n\n");
printf(" 512 (fast, minimally secure)\n");
printf(" 768 (moderate security)\n");
printf("1024 (most popular default)\n");
printf("1536 (additional security, possibly slow)\n");
printf("2048 (maximum supported security level)\n");
printf("\nField size (%d to %d): ", MIN_BASIS_BITS, BASIS_BITS);
fgets(cbuf, sizeof(cbuf), stdin);
fsize = atoi(cbuf);
if(fsize < MIN_BASIS_BITS || fsize > BASIS_BITS) {
fprintf(stderr, "%s: field size must be between %d and %d\n",
progName, MIN_BASIS_BITS, BASIS_BITS);
exit(1);
}
if(fsize <= keylen)
fprintf(stderr, "Warning: new field size is not larger than old field size\n");
printf("\nInitializing random number generator...");
fflush(stdout);
t_initrand();
if(composite)
printf("done.\n\nGenerating a %d-bit composite with safe prime factors. This may take a while.\n", fsize);
else
printf("done.\n\nGenerating a %d-bit safe prime. This may take a while.\n", fsize);
while((tcent = (composite ? t_makeconfent_c(tc, fsize) :
t_makeconfent(tc, fsize))) == NULL)
printf("Parameter generation failed, retrying...\n");
tcent->index = lastidx + 1;
printf("\nParameters successfully generated.\n");
printf("N = [%s]\n", t_tob64(b64buf,
tcent->modulus.data, tcent->modulus.len));
printf("g = [%s]\n", t_tob64(b64buf,
tcent->generator.data, tcent->generator.len));
printf("\nYou must update the pre_params array in t_getconf.c\n");
}

View File

@ -0,0 +1,235 @@
/* This bit implements a simple API for using the SRP library over sockets. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "t_defines.h"
#include "t_pwd.h"
#include "t_server.h"
#include "t_client.h"
#include "tinysrp.h"
#ifndef MSG_WAITALL
#ifdef linux
#define MSG_WAITALL 0x100 /* somehow not defined on my box */
#endif
#endif
/* This is called by the client with a connected socket, username, and
passphrase. pass can be NULL in which case the user is queried. */
int tsrp_client_authenticate(int s, char *user, char *pass, TSRP_SESSION *tsrp)
{
int i, index;
unsigned char username[MAXUSERLEN + 1], sbuf[MAXSALTLEN];
unsigned char msgbuf[MAXPARAMLEN + 1], bbuf[MAXPARAMLEN];
unsigned char passbuf[128], *skey;
struct t_client *tc;
struct t_preconf *tcp; /* @@@ should go away */
struct t_num salt, *A, B;
/* Send the username. */
i = strlen(user);
if (i > MAXUSERLEN) {
i = MAXUSERLEN;
}
msgbuf[0] = i;
memcpy(msgbuf + 1, user, i);
if (send(s, msgbuf, i + 1, 0) < 0) {
return 0;
}
memcpy(username, user, i);
username[i] = '\0';
/* Get the prime index and salt. */
i = recv(s, msgbuf, 2, MSG_WAITALL);
if (i <= 0) {
return 0;
}
index = msgbuf[0];
if (index <= 0 || index > t_getprecount()) {
return 0;
}
tcp = t_getpreparam(index - 1);
salt.len = msgbuf[1];
if (salt.len > MAXSALTLEN) {
return 0;
}
salt.data = sbuf;
i = recv(s, sbuf, salt.len, MSG_WAITALL);
if (i <= 0) {
return 0;
}
/* @@@ t_clientopen() needs a variant that takes the index */
tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &salt);
if (tc == NULL) {
return 0;
}
/* Calculate A and send it to the server. */
A = t_clientgenexp(tc);
msgbuf[0] = A->len - 1; /* len is max 256 */
memcpy(msgbuf + 1, A->data, A->len);
if (send(s, msgbuf, A->len + 1, 0) < 0) {
return 0;
}
/* Ask the user for the passphrase. */
if (pass == NULL) {
t_getpass(passbuf, sizeof(passbuf), "Enter password:");
pass = passbuf;
}
t_clientpasswd(tc, pass);
/* Get B from the server. */
i = recv(s, msgbuf, 1, 0);
if (i <= 0) {
return 0;
}
B.len = msgbuf[0] + 1;
B.data = bbuf;
i = recv(s, bbuf, B.len, MSG_WAITALL);
if (i <= 0) {
return 0;
}
/* Compute the session key. */
skey = t_clientgetkey(tc, &B);
if (skey == NULL) {
return 0;
}
/* Send the response. */
if (send(s, t_clientresponse(tc), RESPONSE_LEN, 0) < 0) {
return 0;
}
/* Get the server's response. */
i = recv(s, msgbuf, RESPONSE_LEN, MSG_WAITALL);
if (i <= 0) {
return 0;
}
if (t_clientverify(tc, msgbuf) != 0) {
return 0;
}
/* All done. Now copy the key and clean up. */
if (tsrp) {
memcpy(tsrp->username, username, strlen(username) + 1);
memcpy(tsrp->key, skey, SESSION_KEY_LEN);
}
t_clientclose(tc);
return 1;
}
/* This is called by the server with a connected socket. */
int tsrp_server_authenticate(int s, TSRP_SESSION *tsrp)
{
int i, j;
unsigned char username[MAXUSERLEN], *skey;
unsigned char msgbuf[MAXPARAMLEN + 1], abuf[MAXPARAMLEN];
struct t_server *ts;
struct t_num A, *B;
/* Get the username. */
i = recv(s, msgbuf, 1, 0);
if (i <= 0) {
return 0;
}
j = msgbuf[0];
i = recv(s, username, j, MSG_WAITALL);
if (i <= 0) {
return 0;
}
username[j] = '\0';
ts = t_serveropen(username);
if (ts == NULL) {
return 0;
}
/* Send the prime index and the salt. */
msgbuf[0] = ts->index; /* max 256 primes... */
i = ts->s.len;
msgbuf[1] = i;
memcpy(msgbuf + 2, ts->s.data, i);
if (send(s, msgbuf, i + 2, 0) < 0) {
return 0;
}
/* Calculate B while we're waiting. */
B = t_servergenexp(ts);
/* Get A from the client. */
i = recv(s, msgbuf, 1, 0);
if (i <= 0) {
return 0;
}
A.len = msgbuf[0] + 1;
A.data = abuf;
i = recv(s, abuf, A.len, MSG_WAITALL);
if (i <= 0) {
return 0;
}
/* Now send B. */
msgbuf[0] = B->len - 1;
memcpy(msgbuf + 1, B->data, B->len);
if (send(s, msgbuf, B->len + 1, 0) < 0) {
return 0;
}
/* Calculate the session key while we're waiting. */
skey = t_servergetkey(ts, &A);
if (skey == NULL) {
return 0;
}
/* Get the response from the client. */
i = recv(s, msgbuf, RESPONSE_LEN, MSG_WAITALL);
if (i <= 0) {
return 0;
}
if (t_serververify(ts, msgbuf) != 0) {
return 0;
}
/* Client authenticated. Now authenticate ourselves to the client. */
if (send(s, t_serverresponse(ts), RESPONSE_LEN, 0) < 0) {
return 0;
}
/* Copy the key and clean up. */
if (tsrp) {
memcpy(tsrp->username, username, strlen(username) + 1);
memcpy(tsrp->key, skey, SESSION_KEY_LEN);
}
t_serverclose(ts);
return 1;
}

View File

@ -0,0 +1,18 @@
/* Simple API for the tinysrp library. */
#ifndef T_PWD_H
#define MAXUSERLEN 32
#define SESSION_KEY_LEN 40 /* 320-bit session key */
#endif
typedef struct {
char username[MAXUSERLEN + 1];
unsigned char key[SESSION_KEY_LEN];
} TSRP_SESSION;
/* These functions are passed a connected socket, and return true for a
successful authentication. If tsrp is not NULL, the username and key
fields are filled in. */
extern int tsrp_server_authenticate(int s, TSRP_SESSION *tsrp);
extern int tsrp_client_authenticate(int s, char *user, char *pass, TSRP_SESSION *tsrp);

View File

@ -0,0 +1,2 @@
moo:A9lHvOGAMJvw1m3vcDsQRUFovh6/QUmLDKqwhv.drKQzbE9nS7HrOZLUPx2MmS6ewwybN8RHqpWqnUJRCMFT14FMbYXR7kYNUUQNx43A7F.xrVOU7tlFq5NjoK9sfFtp6PMdbIOP5wzWmipiNFlCOu4sjlSZb.o7C1chLzTKU.0:19AI0Hc9jEkdFc:5
new user:1FsanML2fbTOEsa072bLjyRD1LEqoRD2GwElfN0VmHeR.FAg5A.2.G5bTjIHmMmHL60kgoAHJZhRrgopalYmujlyAuQoKiHJb98SHm1oJaQ9nl/DrZCvfyw5LpVMqg.CupdiWz6OtmOz8fwC96ItExFnNDt6SmsVDIOn4HqXG6C0lLaqEvcqlN3gFDlJXyP2yldM.LJ1TkHTHmA3DjRkmWEUL3mWEgzkEHyPcRB3Jd5ncDT7jaNbJTTLRoOtgRsaqE7OXuPADoK8MGBcUquYBRrGwyU4Y/wW4gLc3QmV793zxkk.P3.dxkLSjro/Kk94D7kC6fx3K9tadLJyzd94rr:3v/KRlxT0.oYF1:1

View File

@ -0,0 +1,348 @@
/* Add passphrases to the tpasswd file. Use the last entry in the config
file by default or a particular one specified by index. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
#include "t_pwd.h"
#include "t_read.h"
#include "t_sha.h"
#include "t_defines.h"
char *Progname;
char Usage[] = "usage: %s [-n configindex] [-p passfile] user\n";
#define USAGE() fprintf(stderr, Usage, Progname)
void doit(char *);
int Configindex = -1;
char *Passfile = DEFAULT_PASSWD;
int main(int argc, char **argv)
{
int c;
Progname = *argv;
/* Parse option arguments. */
while ((c = getopt(argc, argv, "n:p:")) != EOF) {
switch (c) {
case 'n':
Configindex = atoi(optarg);
break;
case 'p':
Passfile = optarg;
break;
default:
USAGE();
exit(1);
}
}
argc -= optind;
argv += optind;
if (argc != 1) {
USAGE();
exit(1);
}
doit(argv[0]);
return 0;
}
void doit(char *name)
{
char passphrase[128], passphrase1[128];
FILE *f;
struct t_conf *tc;
struct t_confent *tcent;
struct t_pw eps_passwd;
/* Get the config entry. */
if (Configindex <= 0) {
Configindex = t_getprecount();
}
tcent = gettcid(Configindex);
if (tcent == NULL) {
fprintf(stderr, "Invalid configuration file entry.\n");
exit(1);
}
/* Ask for the passphrase twice. */
printf("Setting passphrase for %s\n", name);
if (t_getpass(passphrase, sizeof(passphrase), "Enter passphrase: ") < 0) {
exit(1);
}
if (t_getpass(passphrase1, sizeof(passphrase1), "Verify: ") < 0) {
exit(1);
}
if (strcmp(passphrase, passphrase1) != 0) {
fprintf(stderr, "mismatch\n");
exit(1);
}
/* Create the passphrase verifier. */
t_makepwent(&eps_passwd, name, passphrase, NULL, tcent);
/* Don't need these anymore. */
memset(passphrase, 0, sizeof(passphrase));
memset(passphrase1, 0, sizeof(passphrase1));
/* See if the passphrase file is there; create it if not. */
if ((f = fopen(Passfile, "r+")) == NULL) {
creat(Passfile, 0400);
} else {
fclose(f);
}
/* Change the passphrase. */
if (t_changepw(Passfile, &eps_passwd.pebuf) < 0) {
fprintf(stderr, "Error changing passphrase\n");
exit(1);
}
}
/* TODO: Implement a more general method to handle delete/change */
_TYPE( int )
t_changepw(pwname, diff)
const char * pwname;
const struct t_pwent * diff;
{
char * bakfile;
char * bakfile2;
struct stat st;
FILE * passfp;
FILE * bakfp;
if(pwname == NULL)
pwname = DEFAULT_PASSWD;
if((passfp = fopen(pwname, "rb")) == NULL || fstat(fileno(passfp), &st) < 0)
return -1;
if((bakfile = malloc(strlen(pwname) + 5)) == NULL) {
fclose(passfp);
return -1;
}
else if((bakfile2 = malloc(strlen(pwname) + 5)) == NULL) {
fclose(passfp);
free(bakfile);
return -1;
}
sprintf(bakfile, "%s.bak", pwname);
sprintf(bakfile2, "%s.sav", pwname);
if((bakfp = fopen(bakfile2, "wb")) == NULL &&
(unlink(bakfile2) < 0 || (bakfp = fopen(bakfile2, "wb")) == NULL)) {
fclose(passfp);
fclose(bakfp);
return -1;
}
#ifdef NO_FCHMOD
chmod(bakfile2, st.st_mode & 0777);
#else
fchmod(fileno(bakfp), st.st_mode & 0777);
#endif
t_pwcopy(bakfp, passfp, diff);
fclose(bakfp);
fclose(passfp);
#ifdef USE_RENAME
unlink(bakfile);
if(rename(pwname, bakfile) < 0)
return -1;
if(rename(bakfile2, pwname) < 0)
return -1;
#else
unlink(bakfile);
link(pwname, bakfile);
unlink(pwname);
link(bakfile2, pwname);
unlink(bakfile2);
#endif
free(bakfile);
free(bakfile2);
return 0;
}
_TYPE( struct t_pwent * )
t_makepwent(tpw, user, pass, salt, confent)
struct t_pw * tpw;
const char * user;
const char * pass;
const struct t_num * salt;
const struct t_confent * confent;
{
BigInteger x, v, n, g;
unsigned char dig[SHA_DIGESTSIZE];
SHA1_CTX ctxt;
tpw->pebuf.name = tpw->userbuf;
tpw->pebuf.password.data = tpw->pwbuf;
tpw->pebuf.salt.data = tpw->saltbuf;
strncpy(tpw->pebuf.name, user, MAXUSERLEN);
tpw->pebuf.index = confent->index;
if(salt) {
tpw->pebuf.salt.len = salt->len;
memcpy(tpw->pebuf.salt.data, salt->data, salt->len);
}
else {
memset(dig, 0, SALTLEN); /* salt is 80 bits */
tpw->pebuf.salt.len = SALTLEN;
do {
t_random(tpw->pebuf.salt.data, SALTLEN);
} while(memcmp(tpw->pebuf.salt.data, dig, SALTLEN) == 0);
if(tpw->pebuf.salt.data[0] == 0)
tpw->pebuf.salt.data[0] = 0xff;
}
n = BigIntegerFromBytes(confent->modulus.data, confent->modulus.len);
g = BigIntegerFromBytes(confent->generator.data, confent->generator.len);
v = BigIntegerFromInt(0);
SHA1Init(&ctxt);
SHA1Update(&ctxt, user, strlen(user));
SHA1Update(&ctxt, ":", 1);
SHA1Update(&ctxt, pass, strlen(pass));
SHA1Final(dig, &ctxt);
SHA1Init(&ctxt);
SHA1Update(&ctxt, tpw->pebuf.salt.data, tpw->pebuf.salt.len);
SHA1Update(&ctxt, dig, sizeof(dig));
SHA1Final(dig, &ctxt);
/* x = H(s, H(u, ':', p)) */
x = BigIntegerFromBytes(dig, sizeof(dig));
BigIntegerModExp(v, g, x, n);
tpw->pebuf.password.len = BigIntegerToBytes(v, tpw->pebuf.password.data);
BigIntegerFree(v);
BigIntegerFree(x);
BigIntegerFree(g);
BigIntegerFree(n);
return &tpw->pebuf;
}
int
t_pwcopy(pwdest, pwsrc, diff)
FILE * pwdest;
FILE * pwsrc;
struct t_pwent * diff;
{
struct t_pw * src;
struct t_pwent * ent;
if((src = t_openpw(pwsrc)) == NULL)
return -1;
while((ent = t_getpwent(src)) != NULL)
if(diff && strcmp(diff->name, ent->name) == 0) {
t_putpwent(diff, pwdest);
diff = NULL;
}
else
t_putpwent(ent, pwdest);
if(diff)
t_putpwent(diff, pwdest);
return 0;
}
_TYPE( struct t_pwent * )
t_getpwent(tpw)
struct t_pw * tpw;
{
char indexbuf[16];
char passbuf[MAXB64PARAMLEN];
char saltstr[MAXB64SALTLEN];
#ifdef ENABLE_YP
struct t_passwd * nisent;
/* FIXME: should tell caller to get conf entry from NIS also */
if(tpw->state == IN_NIS) {
nisent = _yp_gettpent();
if(nisent != NULL) {
savepwent(tpw, &nisent->tp);
return &tpw->pebuf;
}
tpw->state = FILE_NIS;
}
#endif
while(1) {
if(t_nextfield(tpw->instream, tpw->userbuf, MAXUSERLEN) > 0) {
#ifdef ENABLE_YP
if(tpw->state == FILE_NIS && *tpw->userbuf == '+') {
t_nextline(tpw->instream);
if(strlen(tpw->userbuf) > 1) { /* +name:... */
nisent = _yp_gettpnam(tpw->userbuf + 1);
if(nisent != NULL) {
savepwent(tpw, nisent);
return &tpw->pebuf;
}
}
else { /* +:... */
tpw->state = IN_NIS;
_yp_settpent();
return t_getpwent(tpw);
}
}
#endif
if(t_nextfield(tpw->instream, passbuf, MAXB64PARAMLEN) > 0 &&
(tpw->pebuf.password.len = t_fromb64(tpw->pwbuf, passbuf)) > 0 &&
t_nextfield(tpw->instream, saltstr, MAXB64SALTLEN) > 0 &&
(tpw->pebuf.salt.len = t_fromb64(tpw->saltbuf, saltstr)) > 0 &&
t_nextfield(tpw->instream, indexbuf, 16) > 0 &&
(tpw->pebuf.index = atoi(indexbuf)) > 0) {
tpw->pebuf.name = tpw->userbuf;
tpw->pebuf.password.data = tpw->pwbuf;
tpw->pebuf.salt.data = tpw->saltbuf;
t_nextline(tpw->instream);
return &tpw->pebuf;
}
}
if(t_nextline(tpw->instream) < 0)
return NULL;
}
}
_TYPE( void )
t_putpwent(ent, fp)
const struct t_pwent * ent;
FILE * fp;
{
char strbuf[MAXB64PARAMLEN];
char saltbuf[MAXB64SALTLEN];
fprintf(fp, "%s:%s:%s:%d\n", ent->name,
t_tob64(strbuf, ent->password.data, ent->password.len),
t_tob64(saltbuf, ent->salt.data, ent->salt.len), ent->index);
}