extern SConn* newSConn(int); // arg is open file descriptor
struct SConn{
void *chan;
int secretlen;
int (*secret)(SConn*, uchar*, int);//
int (*read)(SConn*, uchar*, int); // <0 if error; errmess in buffer
int (*write)(SConn*, uchar*, int);
void (*free)(SConn*); // also closes file descriptor
};
// secret(s,b,dir) sets secret for digest, encrypt, using the secretlen
// bytes in b to form keys for the two directions;
// set dir=0 in client, dir=1 in server
// error convention: write !message in-band
#define readstr secstore_readstr
static void writerr(SConn*, char*);
static int readstr(SConn*, char*); // call with buf of size Maxmsg+1
// returns -1 upon error, with error message in buf
// This group was generated by the seed EB7B6E35F7CD37B511D96C67D6688CC4DD440E1E.
static void
initPAKparams(void)
{
if(pak)
return;
pak = (PAKparams*)emalloc(sizeof(*pak));
pak->q = strtomp("E0F0EF284E10796C5A2A511E94748BA03C795C13", nil, 16, nil);
pak->p = strtomp("C41CFBE4D4846F67A3DF7DE9921A49D3B42DC33728427AB159CEC8CBBD"
"B12B5F0C244F1A734AEB9840804EA3C25036AD1B61AFF3ABBC247CD4B384224567A86"
"3A6F020E7EE9795554BCD08ABAD7321AF27E1E92E3DB1C6E7E94FAAE590AE9C48F96D9"
"3D178E809401ABE8A534A1EC44359733475A36A70C7B425125062B1142D", nil, 16, nil);
pak->r = strtomp("DF310F4E54A5FEC5D86D3E14863921E834113E060F90052AD332B3241CEF"
"2497EFA0303D6344F7C819691A0F9C4A773815AF8EAECFB7EC1D98F039F17A32A7E887"
"D97251A927D093F44A55577F4D70444AEBD06B9B45695EC23962B175F266895C67D21"
"C4656848614D888A4", nil, 16, nil);
pak->g = strtomp("2F1C308DC46B9A44B52DF7DACCE1208CCEF72F69C743ADD4D2327173444"
"ED6E65E074694246E07F9FD4AE26E0FDDD9F54F813C40CB9BCD4338EA6F242AB94CD41"
"0E676C290368A16B1A3594877437E516C53A6EEE5493A038A017E955E218E7819734E3E"
"2A6E0BAE08B14258F8C03CC1B30E0DDADFCF7CEDF0727684D3D255F1", nil, 16, nil);
}
// H = (sha(ver,C,sha(passphrase)))^r mod p,
// a hash function expensive to attack by brute force.
static void
longhash(char *ver, char *C, uchar *passwd, mpint *H)
{
uchar *Cp;
int i, n, nver, nC;
uchar buf[140], key[1];
// another, faster, hash function for each party to
// confirm that the other has the right secrets.
static void
shorthash(char *mess, char *C, char *S, char *m, char *mu, char *sigma, char *Hi, uchar *digest)
{
SHA1state *state;
state = sha1((uchar*)mess, strlen(mess), 0, 0);
state = sha1((uchar*)C, strlen(C), 0, state);
state = sha1((uchar*)S, strlen(S), 0, state);
state = sha1((uchar*)m, strlen(m), 0, state);
state = sha1((uchar*)mu, strlen(mu), 0, state);
state = sha1((uchar*)sigma, strlen(sigma), 0, state);
state = sha1((uchar*)Hi, strlen(Hi), 0, state);
state = sha1((uchar*)mess, strlen(mess), 0, state);
state = sha1((uchar*)C, strlen(C), 0, state);
state = sha1((uchar*)S, strlen(S), 0, state);
state = sha1((uchar*)m, strlen(m), 0, state);
state = sha1((uchar*)mu, strlen(mu), 0, state);
state = sha1((uchar*)sigma, strlen(sigma), 0, state);
sha1((uchar*)Hi, strlen(Hi), digest, state);
}
// On input, conn provides an open channel to the server;
// C is the name this client calls itself;
// pass is the user's passphrase
// On output, session secret has been set in conn
// (unless return code is negative, which means failure).
// If pS is not nil, it is set to the (alloc'd) name the server calls itself.
static int
PAKclient(SConn *conn, char *C, char *pass, char **pS)
{
char *mess, *mess2, *eol, *S, *hexmu, *ks, *hexm, *hexsigma = nil, *hexHi;
char kc[2*SHA1dlen+1];
uchar digest[SHA1dlen];
int rc = -1, n;
mpint *x, *m = mpnew(0), *mu = mpnew(0), *sigma = mpnew(0);
mpint *H = mpnew(0), *Hi = mpnew(0);