Update libsec from plan 9

This commit updates libsec from the latest version of plan 9.
In addition, I have applied all the applicable changes made
to plan9port's libsec.
This commit is contained in:
David Arroyo 2021-02-05 10:23:50 -05:00
parent 90971376a5
commit e7580103a0
24 changed files with 1776 additions and 572 deletions

View file

@ -1,7 +1,7 @@
#ifndef _LIBSEC_H_
#define _LIBSEC_H_ 1
#if defined(__cplusplus)
extern "C" {
extern "C" {
#endif
/*
#pragma lib "libsec.a"
@ -14,9 +14,9 @@ AUTOLIB(sec)
typedef struct mpint mpint;
#endif
/*******************************************************/
/* AES definitions */
/*******************************************************/
/*
* AES definitions
*/
enum
{
@ -31,19 +31,30 @@ struct AESstate
ulong setup;
int rounds;
int keybytes;
uint ctrsz;
uchar key[AESmaxkey]; /* unexpanded key */
u32int ekey[4*(AESmaxrounds + 1)]; /* encryption key */
u32int dkey[4*(AESmaxrounds + 1)]; /* decryption key */
uchar ivec[AESbsize]; /* initialization vector */
uchar mackey[3 * AESbsize]; /* 3 XCBC mac 96 keys */
};
/* block ciphers */
void aes_encrypt(const u32int rk[], int Nr, const uchar pt[16], uchar ct[16]);
void aes_decrypt(const u32int rk[], int Nr, const uchar ct[16], uchar pt[16]);
void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
void aesCBCencrypt(uchar *p, int len, AESstate *s);
void aesCBCdecrypt(uchar *p, int len, AESstate *s);
void aesCTRdecrypt(uchar *p, int len, AESstate *s);
void aesCTRencrypt(uchar *p, int len, AESstate *s);
/*******************************************************/
/* Blowfish Definitions */
/*******************************************************/
void setupAESXCBCstate(AESstate *s);
uchar* aesXCBCmac(uchar *p, int len, AESstate *s);
/*
* Blowfish Definitions
*/
enum
{
@ -70,9 +81,9 @@ void bfCBCdecrypt(uchar*, int, BFstate*);
void bfECBencrypt(uchar*, int, BFstate*);
void bfECBdecrypt(uchar*, int, BFstate*);
/*******************************************************/
/* DES definitions */
/*******************************************************/
/*
* DES definitions
*/
enum
{
@ -128,51 +139,82 @@ void des3CBCdecrypt(uchar*, int, DES3state*);
void des3ECBencrypt(uchar*, int, DES3state*);
void des3ECBdecrypt(uchar*, int, DES3state*);
/*******************************************************/
/* digests */
/*******************************************************/
/*
* digests
*/
enum
{
SHA1dlen= 20, /* SHA digest length */
SHA2_224dlen= 28, /* SHA-224 digest length */
SHA2_256dlen= 32, /* SHA-256 digest length */
SHA2_384dlen= 48, /* SHA-384 digest length */
SHA2_512dlen= 64, /* SHA-512 digest length */
MD4dlen= 16, /* MD4 digest length */
MD5dlen= 16 /* MD5 digest length */
MD5dlen= 16, /* MD5 digest length */
AESdlen= 16, /* TODO: see rfc */
Hmacblksz = 64, /* in bytes; from rfc2104 */
};
typedef struct DigestState DigestState;
struct DigestState
{
ulong len;
u32int state[5];
uchar buf[128];
int blen;
char malloced;
char seeded;
uvlong len;
union {
u32int state[8];
u64int bstate[8];
};
uchar buf[256];
int blen;
char malloced;
char seeded;
};
typedef struct DigestState SHAstate; /* obsolete name */
typedef struct DigestState SHA1state;
typedef struct DigestState SHA2_224state;
typedef struct DigestState SHA2_256state;
typedef struct DigestState SHA2_384state;
typedef struct DigestState SHA2_512state;
typedef struct DigestState MD5state;
typedef struct DigestState MD4state;
typedef struct DigestState AEShstate;
DigestState* md4(uchar*, ulong, uchar*, DigestState*);
DigestState* md5(uchar*, ulong, uchar*, DigestState*);
DigestState* sha1(uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_md5(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_sha1(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
char* sha1pickle(SHA1state*);
SHA1state* sha1unpickle(char*);
DigestState* md4(uchar*, ulong, uchar*, DigestState*);
DigestState* md5(uchar*, ulong, uchar*, DigestState*);
DigestState* sha1(uchar*, ulong, uchar*, DigestState*);
DigestState* sha2_224(uchar*, ulong, uchar*, DigestState*);
DigestState* sha2_256(uchar*, ulong, uchar*, DigestState*);
DigestState* sha2_384(uchar*, ulong, uchar*, DigestState*);
DigestState* sha2_512(uchar*, ulong, uchar*, DigestState*);
DigestState* aes(uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_x(uchar *p, ulong len, uchar *key, ulong klen,
uchar *digest, DigestState *s,
DigestState*(*x)(uchar*, ulong, uchar*, DigestState*),
int xlen);
DigestState* hmac_md5(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_sha1(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_sha2_224(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_sha2_256(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_sha2_384(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_sha2_512(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_aes(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
char* md5pickle(MD5state*);
MD5state* md5unpickle(char*);
char* sha1pickle(SHA1state*);
SHA1state* sha1unpickle(char*);
/*******************************************************/
/* random number generation */
/*******************************************************/
/*
* random number generation
*/
void genrandom(uchar *buf, int nbytes);
void prng(uchar *buf, int nbytes);
ulong fastrand(void);
ulong nfastrand(ulong);
/*******************************************************/
/* primes */
/*******************************************************/
/*
* primes
*/
void genprime(mpint *p, int n, int accuracy); /* generate an n bit probable prime */
void gensafeprime(mpint *p, mpint *alpha, int n, int accuracy); /* prime and generator */
void genstrongprime(mpint *p, int n, int accuracy); /* generate an n bit strong prime */
@ -180,9 +222,9 @@ void DSAprimes(mpint *q, mpint *p, uchar seed[SHA1dlen]);
int probably_prime(mpint *n, int nrep); /* miller-rabin test */
int smallprimetest(mpint *p); /* returns -1 if not prime, 0 otherwise */
/*******************************************************/
/* rc4 */
/*******************************************************/
/*
* rc4
*/
typedef struct RC4state RC4state;
struct RC4state
{
@ -196,9 +238,9 @@ void rc4(RC4state*, uchar*, int);
void rc4skip(RC4state*, int);
void rc4back(RC4state*, int);
/*******************************************************/
/* rsa */
/*******************************************************/
/*
* rsa
*/
typedef struct RSApub RSApub;
typedef struct RSApriv RSApriv;
typedef struct PEMChain PEMChain;
@ -225,14 +267,14 @@ struct RSApriv
mpint *c2; /* (inv p) mod q */
};
struct PEMChain
{
PEMChain *next;
uchar *pem;
int pemlen;
struct PEMChain{
PEMChain*next;
uchar *pem;
int pemlen;
};
RSApriv* rsagen(int nlen, int elen, int rounds);
RSApriv* rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q);
mpint* rsaencrypt(RSApub *k, mpint *in, mpint *out);
mpint* rsadecrypt(RSApriv *k, mpint *in, mpint *out);
RSApub* rsapuballoc(void);
@ -241,16 +283,20 @@ RSApriv* rsaprivalloc(void);
void rsaprivfree(RSApriv*);
RSApub* rsaprivtopub(RSApriv*);
RSApub* X509toRSApub(uchar*, int, char*, int);
uchar* RSApubtoasn1(RSApub*, int*);
RSApub* asn1toRSApub(uchar*, int);
RSApriv* asn1toRSApriv(uchar*, int);
uchar* decodepem(char *s, char *type, int *len, char**);
void asn1dump(uchar *der, int len);
uchar* decodePEM(char *s, char *type, int *len, char**);
PEMChain* decodepemchain(char *s, char *type);
uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
RSApriv* rsafill(mpint *n, mpint *ek, mpint *dk, mpint *p, mpint *q);
uchar* X509req(RSApriv *priv, char *subj, int *certlen);
char* X509verify(uchar *cert, int ncert, RSApub *pk);
void X509dump(uchar *cert, int ncert);
/*******************************************************/
/* elgamal */
/*******************************************************/
/*
* elgamal
*/
typedef struct EGpub EGpub;
typedef struct EGpriv EGpriv;
typedef struct EGsig EGsig;
@ -289,9 +335,9 @@ EGsig* egsigalloc(void);
void egsigfree(EGsig*);
EGpub* egprivtopub(EGpriv*);
/*******************************************************/
/* dsa */
/*******************************************************/
/*
* dsa
*/
typedef struct DSApub DSApub;
typedef struct DSApriv DSApriv;
typedef struct DSAsig DSAsig;
@ -330,9 +376,9 @@ void dsasigfree(DSAsig*);
DSApub* dsaprivtopub(DSApriv*);
DSApriv* asn1toDSApriv(uchar*, int);
/*******************************************************/
/* TLS */
/*******************************************************/
/*
* TLS
*/
typedef struct Thumbprint{
struct Thumbprint *next;
uchar sha1[SHA1dlen];
@ -342,9 +388,14 @@ typedef struct TLSconn{
char dir[40]; /* connection directory */
uchar *cert; /* certificate (local on input, remote on output) */
uchar *sessionID;
int certlen, sessionIDlen;
int certlen;
int sessionIDlen;
int (*trace)(char*fmt, ...);
PEMChain *chain;
char *sessionType;
uchar *sessionKey;
int sessionKeylen;
char *sessionConst;
} TLSconn;
/* tlshand.c */

View file

@ -11,6 +11,12 @@ setupAESstate, aesCBCencrypt, aesCBCdecrypt - advanced encryption standard (rijn
.B #include <libsec.h>
.PP
.B
void aes_encrypt(u32int rk[], int Nr, uchar pt[16], uchar ct[16]);
.PP
.B
void aes_decrypt(u32int rk[], int Nr, uchar ct[16], uchar pt[16]);
.PP
.B
void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
.PP
.B
@ -19,22 +25,50 @@ void aesCBCencrypt(uchar*, int, AESstate*)
.B
void aesCBCdecrypt(uchar*, int, AESstate*)
.PP
.SH DESCRIPTION
.B
void aesCTRencrypt(uchar *p, int len, AESstate *s)
.PP
DES is being replaced by Rijndael, also known as AES, as the preferred
block ciper.
.IR setupAESstate ,
.B
void aesCTRdecrypt(uchar *p, int len, AESstate *s)
.PP
.B
void setupAESXCBCstate(AESstate *s)
.PP
.B
void aesXCBCmac(uchar *p, int len, AESstate *s)
.PP
.SH DESCRIPTION
AES (a.k.a. Rijndael) has replaced DES as the preferred
block cipher.
.I Aes_encrypt
and
.I aes_decrypt
are the block ciphers, corresponding to
.IR des (2)'s
.IR block_cipher .
.IR SetupAESstate ,
.IR aesCBCencrypt ,
and
.I aesCBCdecrypt
implement cipher block chaining encryption.
implement cipher-block-chaining encryption.
.I AesCTRencrypt
and
.I aesCTRdecrypt
implement counter mode, per RFC 3686;
they are identical operations.
.I setupAESXCBCstate
and
.I aesXCBCmac
implement AES XCBC message authentication, per RFC 3566.
All ciphering is performed in place.
.I Keybytes
should be 16, 24, or 32.
The initialization vector
.I ivec
of
.I AESbsize
bytes should random enough to be unlikely to be reused but does not need to be
bytes should be random enough to be unlikely to be reused
but does not need to be
cryptographically strongly unpredictable.
.SH SOURCE
.B \*9/src/libsec
@ -49,3 +83,13 @@ cryptographically strongly unpredictable.
.MR sechash (3) ,
.MR prime (3) ,
.MR rand (3)
.SH BUGS
The functions
.IR aes_encrypt ,
.IR aes_decrypt ,
.IR aesCTRencrypt ,
.IR aesCTRdecrypt ,
.IR setupAESXCBCstate ,
and
.IR aesXCBCmac
have not yet been verified by running test vectors through them.

View file

@ -2,7 +2,7 @@
.SH NAME
asn1dump,
asn1toRSApriv,
decodepem,
decodePEM,
decodepemchain,
rsadecrypt,
rsaencrypt,
@ -65,7 +65,7 @@ RSApriv* asn1toRSApriv(uchar *priv, int npriv)
void asn1dump(uchar *der, int len)
.PP
.B
uchar* decodepem(char *s, char *type, int *len)
uchar* decodePEM(char *s, char *type, int *len)
.PP
.B
PEMChain* decodepemchain(char *s, char *type)
@ -103,7 +103,7 @@ using his private key:
{
RSApub pub;
mpint *dk; // exp (decryption key)
// precomputed crt values
mpint *p;
mpint *q;

View file

@ -1,6 +1,11 @@
.TH SECHASH 3
.SH NAME
md4, md5, sha1, hmac_md5, hmac_sha1, md5pickle, md5unpickle, sha1pickle, sha1unpickle \- cryptographically secure hashes
md4, md5,
sha1, sha2_224, sha2_256, sha2_384, sha2_512,
aes, hmac_x, hmac_md5,
hmac_sha1, hmac_sha2_224, hmac_sha2_256, hmac_sha2_384, hmac_sha2_512,
hmac_aes, md5pickle, md5unpickle,
sha1pickle, sha1unpickle \- cryptographically secure hashes
.SH SYNOPSIS
.B #include <u.h>
.br
@ -35,7 +40,41 @@ DigestState* sha1(uchar *data, ulong dlen, uchar *digest,
char* sha1pickle(MD5state *state)
.PP
.B
MD5state* sha1unpickle(char *p);
SHA1state* sha1unpickle(char *p);
.PP
.B
DigestState* sha2_224(uchar *data, ulong dlen, uchar *digest,
.B
DigestState *state)
.PP
.B
DigestState* sha2_256(uchar *data, ulong dlen, uchar *digest,
.B
DigestState *state)
.PP
.B
DigestState* sha2_384(uchar *data, ulong dlen, uchar *digest,
.B
DigestState *state)
.PP
.B
DigestState* sha2_512(uchar *data, ulong dlen, uchar *digest,
.B
DigestState *state)
.PP
.B
DigestState* aes(uchar *data, ulong dlen, uchar *digest,
.B
DigestState *state)
.PP
.B
DigestState* hmac_x(uchar *data, ulong dlen,
.br
.B
uchar *key, ulong klen,
.br
.B
uchar *digest, DigestState *state)
.PP
.B
DigestState* hmac_md5(uchar *data, ulong dlen,
@ -52,12 +91,56 @@ DigestState* hmac_sha1(uchar *data, ulong dlen,
.B
uchar *key, ulong klen,
.br
.B
uchar *digest, DigestState *state)
.PP
.B
DigestState* hmac_sha2_224(uchar *data, ulong dlen,
.br
.B
uchar *key, ulong klen,
.br
.B
uchar *digest, DigestState *state)
.PP
.B
DigestState* hmac_sha2_256(uchar *data, ulong dlen,
.br
.B
uchar *key, ulong klen,
.br
.B
uchar *digest, DigestState *state)
.PP
.B
DigestState* hmac_sha2_384(uchar *data, ulong dlen,
.br
.B
uchar *key, ulong klen,
.br
.B
uchar *digest, DigestState *state)
.PP
.B
DigestState* hmac_sha2_512(uchar *data, ulong dlen,
.br
.B
uchar *key, ulong klen,
.br
.B
uchar *digest, DigestState *state)
.PP
.B
DigestState* hmac_sha2_aes(uchar *data, ulong dlen,
.br
.B
uchar *key, ulong klen,
.br
.B
uchar *digest, DigestState *state)
.SH DESCRIPTION
.PP
These functions implement
the cryptographic hash functions MD4, MD5, and SHA1. The output of the
We support several secure hash functions. The output of a
hash is called a
.IR digest .
A hash is secure if, given the hashed data and the digest,
@ -71,14 +154,30 @@ The routines
.IR md4 ,
.IR md5 ,
.IR sha1 ,
.IR sha2_224 ,
.IR sha2_256 ,
.IR sha2_384 ,
.IR sha2_512 ,
.IR aes ,
.IR hmac_md5 ,
.IR hmac_sha1 ,
.IR hmac_sha2_224 ,
.IR hmac_sha2_256 ,
.IR hmac_sha2_384 ,
.IR hmac_sha2_512 ,
and
.I hmac_sha1
.I hmac_aes
differ only in the length of the resulting digest
and in the security of the hash. Usage for each is the same.
and in the security of the hash.
.I Sha2_*
and
.I hmac_sha2_*
are the SHA-2 functions; the number after the final underscore
is the number of bits in the resulting digest.
Usage for each is the same.
The first call to the routine should have
.B nil
as the
as the
.I state
parameter. This call returns a state which can be used to chain
subsequent calls.
@ -113,20 +212,32 @@ bounded on each end by some secret:
The constants
.IR MD4dlen ,
.IR MD5dlen ,
.IR SHA1dlen ,
.IR SHA2_224dlen ,
.IR SHA2_256dlen ,
.IR SHA2_384dlen,
.IR SHA2_512dlen ,
and
.I SHA1dlen
.I AESdlen
define the lengths of the digests.
.PP
.I Hmac_md5
.IR Hmac_md5 ,
.IR hmac_sha1 ,
.IR hmac_sha2_224 ,
.IR hmac_sha2_256 ,
.IR hmac_sha2_384 ,
.IR hmac_sha2_512 ,
and
.I hmac_sha1
.I hmac_aes
are used slightly differently. These hash algorithms are keyed and require
a key to be specified on every call.
The digest lengths for these hashes are
.I MD5dlen
and
.I SHA1dlen
respectively.
The digest lengths for these hashes are the obvious ones from
the above list of length constants.
These routines all call
.I hmac_x
internally, but
.I hmac_x
is not intended for general use.
.PP
The functions
.I md5pickle

View file

@ -50,7 +50,7 @@ main(int argc, char **argv)
tot += n;
}
buf[tot] = 0;
bin = decodepem(buf, tag, &len, nil);
bin = decodePEM(buf, tag, &len, nil);
if(bin == nil)
sysfatal("cannot extract section '%s' from pem", tag);
if((n=write(1, bin, len)) != len)

View file

@ -30,10 +30,12 @@
*/
#include <u.h>
#include <libc.h>
#include <mp.h>
#include <libsec.h>
typedef uchar u8;
typedef u32int u32;
#define FULL_UNROLL
static const u32 Td0[256];
@ -41,14 +43,28 @@ static const u32 Td1[256];
static const u32 Td2[256];
static const u32 Td3[256];
static const u8 Te4[256];
static uchar basekey[3][16] = {
{
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
},
{
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
},
{
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
},
};
static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
#ifdef NOTUSED
static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
#endif
static int rijndaelKeySetup(u32 erk[/*4*(Nr + 1)*/], u32 drk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
static void rijndaelEncrypt(const u32int rk[], int Nr, const uchar pt[16], uchar ct[16]);
static void rijndaelDecrypt(const u32int rk[], int Nr, const uchar ct[16], uchar pt[16]);
static int aes_setupEnc(u32int rk[/*4*(Nr + 1)*/], const uchar cipherKey[],
int keyBits);
static int aes_setup(u32int erk[/*4*(Nr + 1)*/], u32int drk[/*4*(Nr + 1)*/],
const uchar cipherKey[], int keyBits);
void aes_encrypt(const u32int rk[], int Nr, const uchar pt[16], uchar ct[16]);
void aes_decrypt(const u32int rk[], int Nr, const uchar ct[16], uchar pt[16]);
void
setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
@ -58,17 +74,96 @@ setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
keybytes = AESmaxkey;
memmove(s->key, key, keybytes);
s->keybytes = keybytes;
s->rounds = rijndaelKeySetup(s->ekey, s->dkey, s->key, keybytes * 8);
s->rounds = aes_setup(s->ekey, s->dkey, s->key, keybytes * 8);
if(ivec != nil)
memmove(s->ivec, ivec, AESbsize);
if(keybytes==16 || keybytes==24 || keybytes==32)
s->setup = 0xcafebabe;
/* else rijndaelKeySetup was invalid */
/* else aes_setup was invalid */
}
/* Define by analogy with desCBCencrypt; AES modes are not standardized yet. */
/* Because of the way that non-multiple-of-16 buffers are handled, */
/* the decryptor must be fed buffers of the same size as the encryptor. */
/*
* AES-XCBC-MAC-96 message authentication, per rfc3566.
*/
void
setupAESXCBCstate(AESstate *s) /* was setupmac96 */
{
int i, j;
uint q[16 / sizeof(uint)];
uchar *p;
assert(s->keybytes == 16);
for(i = 0; i < 3; i++)
aes_encrypt(s->ekey, s->rounds, basekey[i],
s->mackey + AESbsize*i);
p = s->mackey;
memset(q, 0, AESbsize);
/*
* put the in the right endian. once figured, probably better
* to use some fcall macros.
* keys for encryption in local endianness for the algorithm...
* only key1 is used for encryption;
* BUG!!: I think this is what I got wrong.
*/
for(i = 0; i < 16 / sizeof(uint); i ++){
for(j = 0; j < sizeof(uint); j++)
q[i] |= p[sizeof(uint)-j-1] << 8*j;
p += sizeof(uint);
}
memmove(s->mackey, q, 16);
}
/*
* Not dealing with > 128-bit keys, not dealing with strange corner cases like
* empty message. Should be fine for AES-XCBC-MAC-96.
*/
uchar*
aesXCBCmac(uchar *p, int len, AESstate *s)
{
uchar *p2, *ip, *eip, *mackey;
uchar q[AESbsize];
assert(s->keybytes == 16); /* more complicated for bigger */
memset(s->ivec, 0, AESbsize); /* E[0] is 0+ */
for(; len > AESbsize; len -= AESbsize){
memmove(q, p, AESbsize);
p2 = q;
ip = s->ivec;
for(eip = ip + AESbsize; ip < eip; )
*p2++ ^= *ip++;
aes_encrypt((u32int *)s->mackey, s->rounds, q, s->ivec);
p += AESbsize;
}
/* the last one */
memmove(q, p, len);
p2 = q+len;
if(len == AESbsize)
mackey = s->mackey + AESbsize; /* k2 */
else{
mackey = s->mackey+2*AESbsize; /* k3 */
*p2++ = 1 << 7; /* padding */
len = AESbsize - len - 1;
memset(p2, 0, len);
}
ip = s->ivec;
p2 = q;
for(eip = ip + AESbsize; ip < eip; )
*p2++ ^= *ip++ ^ *mackey++;
aes_encrypt((u32int *)s->mackey, s->rounds, q, s->ivec);
return s->ivec; /* only the 12 bytes leftmost */
}
/*
* Define by analogy with desCBCencrypt; AES modes are not standardized yet.
* Because of the way that non-multiple-of-16 buffers are handled,
* the decryptor must be fed buffers of the same size as the encryptor.
*/
void
aesCBCencrypt(uchar *p, int len, AESstate *s)
{
@ -80,7 +175,7 @@ aesCBCencrypt(uchar *p, int len, AESstate *s)
ip = s->ivec;
for(eip = ip+AESbsize; ip < eip; )
*p2++ ^= *ip++;
rijndaelEncrypt(s->ekey, s->rounds, p, q);
aes_encrypt(s->ekey, s->rounds, p, q);
memmove(s->ivec, q, AESbsize);
memmove(p, q, AESbsize);
p += AESbsize;
@ -88,7 +183,7 @@ aesCBCencrypt(uchar *p, int len, AESstate *s)
if(len > 0){
ip = s->ivec;
rijndaelEncrypt(s->ekey, s->rounds, ip, q);
aes_encrypt(s->ekey, s->rounds, ip, q);
memmove(s->ivec, q, AESbsize);
for(eip = ip+len; ip < eip; )
*p++ ^= *ip++;
@ -103,7 +198,7 @@ aesCBCdecrypt(uchar *p, int len, AESstate *s)
for(; len >= AESbsize; len -= AESbsize){
memmove(tmp, p, AESbsize);
rijndaelDecrypt(s->dkey, s->rounds, p, q);
aes_decrypt(s->dkey, s->rounds, p, q);
memmove(p, q, AESbsize);
tp = tmp;
ip = s->ivec;
@ -115,28 +210,220 @@ aesCBCdecrypt(uchar *p, int len, AESstate *s)
if(len > 0){
ip = s->ivec;
rijndaelEncrypt(s->ekey, s->rounds, ip, q);
aes_encrypt(s->ekey, s->rounds, ip, q);
memmove(s->ivec, q, AESbsize);
for(eip = ip+len; ip < eip; )
*p++ ^= *ip++;
}
}
/*
* AES-CTR mode, per rfc3686.
* CTRs could be precalculated for efficiency
* and there would also be less back and forth mp
*/
static void
incrementCTR(uchar *p, uint ctrsz)
{
int len;
uchar *ctr;
mpint *mpctr, *mpctrsz;
ctr = p + AESbsize - ctrsz;
mpctr = betomp(ctr, ctrsz, nil);
mpctrsz = itomp(1 << (ctrsz*8), nil);
mpadd(mpctr, mpone, mpctr);
mpmod(mpctr, mpctrsz, mpctr);
len = mptobe(mpctr, ctr, ctrsz, nil);
assert(len == ctrsz);
mpfree(mpctrsz);
mpfree(mpctr);
}
void
aesCTRencrypt(uchar *p, int len, AESstate *s)
{
uchar q[AESbsize];
uchar *ip, *eip, *ctr;
ctr = s->ivec;
for(; len >= AESbsize; len -= AESbsize){
ip = q;
aes_encrypt(s->ekey, s->rounds, ctr, q);
for(eip = p + AESbsize; p < eip; )
*p++ ^= *ip++;
incrementCTR(ctr, s->ctrsz);
}
if(len > 0){
ip = q;
aes_encrypt(s->ekey, s->rounds, ctr, q);
for(eip = p + len; p < eip; )
*p++ ^= *ip++;
incrementCTR(ctr, s->ctrsz);
}
}
void
aesCTRdecrypt(uchar *p, int len, AESstate *s)
{
aesCTRencrypt(p, len, s);
}
/* taken from sha1; TODO: verify suitability (esp. byte order) for aes */
/*
* encodes input (ulong) into output (uchar). Assumes len is
* a multiple of 4.
*/
static void
encode(uchar *output, u32int *input, ulong len)
{
ulong x;
uchar *e;
for(e = output + len; output < e;) {
x = *input++;
*output++ = x >> 24;
*output++ = x >> 16;
*output++ = x >> 8;
*output++ = x;
}
}
/* TODO: verify use of aes_encrypt here */
AEShstate*
aes(uchar *p, ulong len, uchar *digest, AEShstate *s)
{
uchar buf[128];
u32int x[16];
int i;
uchar *e;
if(s == nil){
s = malloc(sizeof(*s));
if(s == nil)
return nil;
memset(s, 0, sizeof(*s));
s->malloced = 1;
}
if(s->seeded == 0){
/* seed the state, these constants would look nicer big-endian */
s->state[0] = 0x67452301;
s->state[1] = 0xefcdab89;
s->state[2] = 0x98badcfe;
s->state[3] = 0x10325476;
/* in sha1 (20-byte digest), but not md5 (16 bytes)*/
s->state[4] = 0xc3d2e1f0;
s->seeded = 1;
}
/* fill out the partial 64 byte block from previous calls */
if(s->blen){
i = 64 - s->blen;
if(len < i)
i = len;
memmove(s->buf + s->blen, p, i);
len -= i;
s->blen += i;
p += i;
if(s->blen == 64){
/* encrypt s->buf into s->state */
/* _sha1block(s->buf, s->blen, s->state); */
aes_encrypt((u32int *)s->buf, 1, s->buf, (uchar *)s->state);
s->len += s->blen;
s->blen = 0;
}
}
/* do 64 byte blocks */
i = len & ~0x3f;
if(i){
/* encrypt p into s->state */
/* _sha1block(p, i, s->state); */
aes_encrypt((u32int *)s->buf, 1, p, (uchar *)s->state);
s->len += i;
len -= i;
p += i;
}
/* save the left overs if not last call */
if(digest == 0){
if(len){
memmove(s->buf, p, len);
s->blen += len;
}
return s;
}
/*
* this is the last time through, pad what's left with 0x80,
* 0's, and the input count to create a multiple of 64 bytes
*/
if(s->blen){
p = s->buf;
len = s->blen;
} else {
memmove(buf, p, len);
p = buf;
}
s->len += len;
e = p + len;
if(len < 56)
i = 56 - len;
else
i = 120 - len;
memset(e, 0, i);
*e = 0x80;
len += i;
/* append the count */
x[0] = s->len>>29; /* byte-order dependent */
x[1] = s->len<<3;
encode(p+len, x, 8);
/* digest the last part */
/* encrypt p into s->state */
/* _sha1block(p, len+8, s->state); */
aes_encrypt((u32int *)s->buf, 1, p, (uchar *)s->state);
s->len += len+8; /* sha1: +8 */
/* return result and free state */
encode((uchar *)digest, (u32int *)s->state, AESdlen);
if(s->malloced == 1)
free(s);
return nil;
}
DigestState*
hmac_aes(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, aes, AESdlen);
}
/*
* this function has been changed for plan 9.
* Expand the cipher key into the encryption and decryption key schedules.
*
* @return the number of rounds for the given cipher key size.
*/
static int rijndaelKeySetup(u32 erk[/*4*(Nr + 1)*/], u32 drk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
static int
aes_setup(u32int erk[/* 4*(Nr + 1) */], u32int drk[/* 4*(Nr + 1) */],
const uchar cipherKey[], int keyBits)
{
int Nr, i;
/* expand the cipher key: */
Nr = rijndaelKeySetupEnc(erk, cipherKey, keyBits);
Nr = aes_setupEnc(erk, cipherKey, keyBits);
/*
* invert the order of the round keys and
* apply the inverse MixColumn transform to all round keys but the first and the last
* invert the order of the round keys and apply the inverse MixColumn
* transform to all round keys but the first and the last
*/
drk[0 ] = erk[4*Nr ];
drk[1 ] = erk[4*Nr + 1];
@ -174,6 +461,7 @@ static int rijndaelKeySetup(u32 erk[/*4*(Nr + 1)*/], u32 drk[/*4*(Nr + 1)*/], co
return Nr;
}
/*
Te0[x] = S [x].[02, 01, 01, 03];
Te1[x] = S [x].[03, 02, 01, 01];
@ -853,26 +1141,24 @@ static const u8 Td4[256] = {
static const u32 rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
0x1B000000, 0x36000000,
/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
};
#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
#define GETU32(pt) (((u32)(pt)[0]<<24) ^ ((u32)(pt)[1]<<16) ^ \
((u32)(pt)[2]<< 8) ^ ((u32)(pt)[3]))
#define PUTU32(ct, st) { (ct)[0] = (u8)((st)>>24); (ct)[1] = (u8)((st)>>16); \
(ct)[2] = (u8)((st)>> 8); (ct)[3] = (u8)(st); }
#ifdef _MSC_VER
#define GETU32(p) SWAP(*((u32 *)(p)))
#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
#else
#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
#endif
/**
/*
* Expand the cipher key into the encryption key schedule.
*
* @return the number of rounds for the given cipher key size.
*/
static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
int i = 0;
static int
aes_setupEnc(u32int rk[/*4*(Nr + 1)*/], const uchar cipherKey[], int keyBits)
{
int i = 0;
u32 temp;
rk[0] = GETU32(cipherKey );
@ -922,90 +1208,46 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int
rk[6] = GETU32(cipherKey + 24);
rk[7] = GETU32(cipherKey + 28);
if (keyBits == 256) {
for (;;) {
temp = rk[ 7];
rk[ 8] = rk[ 0] ^
(Te4[(temp >> 16) & 0xff] << 24) ^
(Te4[(temp >> 8) & 0xff] << 16) ^
(Te4[(temp ) & 0xff] << 8) ^
(Te4[(temp >> 24) ] ) ^
rcon[i];
rk[ 9] = rk[ 1] ^ rk[ 8];
rk[10] = rk[ 2] ^ rk[ 9];
rk[11] = rk[ 3] ^ rk[10];
for (;;) {
temp = rk[ 7];
rk[ 8] = rk[ 0] ^
(Te4[(temp >> 16) & 0xff] << 24) ^
(Te4[(temp >> 8) & 0xff] << 16) ^
(Te4[(temp ) & 0xff] << 8) ^
(Te4[(temp >> 24) ] ) ^
rcon[i];
rk[ 9] = rk[ 1] ^ rk[ 8];
rk[10] = rk[ 2] ^ rk[ 9];
rk[11] = rk[ 3] ^ rk[10];
if (++i == 7) {
return 14;
}
temp = rk[11];
rk[12] = rk[ 4] ^
(Te4[(temp >> 24) ] << 24) ^
(Te4[(temp >> 16) & 0xff] << 16) ^
(Te4[(temp >> 8) & 0xff] << 8) ^
(Te4[(temp ) & 0xff] );
rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14];
temp = rk[11];
rk[12] = rk[ 4] ^
(Te4[(temp >> 24) ] << 24) ^
(Te4[(temp >> 16) & 0xff] << 16) ^
(Te4[(temp >> 8) & 0xff] << 8) ^
(Te4[(temp ) & 0xff] );
rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14];
rk += 8;
}
}
}
return 0;
}
/**
* Expand the cipher key into the decryption key schedule.
*
* @return the number of rounds for the given cipher key size.
*/
#ifdef NOTUSED
static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
int Nr, i, j;
u32 temp;
/* expand the cipher key: */
Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
/* invert the order of the round keys: */
for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
}
/* apply the inverse MixColumn transform to all round keys but the first and the last: */
for (i = 1; i < Nr; i++) {
rk += 4;
rk[0] =
Td0[Te4[(rk[0] >> 24) ]] ^
Td1[Te4[(rk[0] >> 16) & 0xff]] ^
Td2[Te4[(rk[0] >> 8) & 0xff]] ^
Td3[Te4[(rk[0] ) & 0xff]];
rk[1] =
Td0[Te4[(rk[1] >> 24) ]] ^
Td1[Te4[(rk[1] >> 16) & 0xff]] ^
Td2[Te4[(rk[1] >> 8) & 0xff]] ^
Td3[Te4[(rk[1] ) & 0xff]];
rk[2] =
Td0[Te4[(rk[2] >> 24) ]] ^
Td1[Te4[(rk[2] >> 16) & 0xff]] ^
Td2[Te4[(rk[2] >> 8) & 0xff]] ^
Td3[Te4[(rk[2] ) & 0xff]];
rk[3] =
Td0[Te4[(rk[3] >> 24) ]] ^
Td1[Te4[(rk[3] >> 16) & 0xff]] ^
Td2[Te4[(rk[3] >> 8) & 0xff]] ^
Td3[Te4[(rk[3] ) & 0xff]];
}
return Nr;
}
#endif
static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
u32 s0, s1, s2, s3, t0, t1, t2, t3;
/* using round keys in rk, perform Nr rounds of encrypting pt into ct */
void
aes_encrypt(const u32int rk[/* 4*(Nr + 1) */], int Nr, const uchar pt[16],
uchar ct[16])
{
ulong s0, s1, s2, s3, t0, t1, t2, t3;
#ifndef FULL_UNROLL
int r;
int r;
#endif /* ?FULL_UNROLL */
/*
/*
* map byte array block to cipher state
* and add initial round key:
*/
@ -1014,7 +1256,7 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
s2 = GETU32(pt + 8) ^ rk[2];
s3 = GETU32(pt + 12) ^ rk[3];
#ifdef FULL_UNROLL
/* round 1: */
/* round 1: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
@ -1024,7 +1266,7 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
/* round 3: */
/* round 3: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
@ -1034,7 +1276,7 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
/* round 5: */
/* round 5: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
@ -1044,7 +1286,7 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
/* round 7: */
/* round 7: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
@ -1054,99 +1296,98 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
/* round 9: */
/* round 9: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
if (Nr > 10) {
/* round 10: */
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
/* round 11: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
if (Nr > 12) {
/* round 12: */
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
/* round 13: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
}
}
rk += Nr << 2;
#else /* !FULL_UNROLL */
/*
if (Nr > 10) {
/* round 10: */
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
/* round 11: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
if (Nr > 12) {
/* round 12: */
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
/* round 13: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
}
}
rk += Nr << 2;
#else /* !FULL_UNROLL */
/*
* Nr - 1 full rounds:
*/
r = Nr >> 1;
for (;;) {
t0 =
Te0[(s0 >> 24) ] ^
Te1[(s1 >> 16) & 0xff] ^
Te2[(s2 >> 8) & 0xff] ^
Te3[(s3 ) & 0xff] ^
rk[4];
t1 =
Te0[(s1 >> 24) ] ^
Te1[(s2 >> 16) & 0xff] ^
Te2[(s3 >> 8) & 0xff] ^
Te3[(s0 ) & 0xff] ^
rk[5];
t2 =
Te0[(s2 >> 24) ] ^
Te1[(s3 >> 16) & 0xff] ^
Te2[(s0 >> 8) & 0xff] ^
Te3[(s1 ) & 0xff] ^
rk[6];
t3 =
Te0[(s3 >> 24) ] ^
Te1[(s0 >> 16) & 0xff] ^
Te2[(s1 >> 8) & 0xff] ^
Te3[(s2 ) & 0xff] ^
rk[7];
r = Nr >> 1;
for (;;) {
t0 =
Te0[(s0 >> 24) ] ^
Te1[(s1 >> 16) & 0xff] ^
Te2[(s2 >> 8) & 0xff] ^
Te3[(s3 ) & 0xff] ^
rk[4];
t1 =
Te0[(s1 >> 24) ] ^
Te1[(s2 >> 16) & 0xff] ^
Te2[(s3 >> 8) & 0xff] ^
Te3[(s0 ) & 0xff] ^
rk[5];
t2 =
Te0[(s2 >> 24) ] ^
Te1[(s3 >> 16) & 0xff] ^
Te2[(s0 >> 8) & 0xff] ^
Te3[(s1 ) & 0xff] ^
rk[6];
t3 =
Te0[(s3 >> 24) ] ^
Te1[(s0 >> 16) & 0xff] ^
Te2[(s1 >> 8) & 0xff] ^
Te3[(s2 ) & 0xff] ^
rk[7];
rk += 8;
if (--r == 0) {
break;
}
rk += 8;
if (--r == 0)
break;
s0 =
Te0[(t0 >> 24) ] ^
Te1[(t1 >> 16) & 0xff] ^
Te2[(t2 >> 8) & 0xff] ^
Te3[(t3 ) & 0xff] ^
rk[0];
s1 =
Te0[(t1 >> 24) ] ^
Te1[(t2 >> 16) & 0xff] ^
Te2[(t3 >> 8) & 0xff] ^
Te3[(t0 ) & 0xff] ^
rk[1];
s2 =
Te0[(t2 >> 24) ] ^
Te1[(t3 >> 16) & 0xff] ^
Te2[(t0 >> 8) & 0xff] ^
Te3[(t1 ) & 0xff] ^
rk[2];
s3 =
Te0[(t3 >> 24) ] ^
Te1[(t0 >> 16) & 0xff] ^
Te2[(t1 >> 8) & 0xff] ^
Te3[(t2 ) & 0xff] ^
rk[3];
}
#endif /* ?FULL_UNROLL */
/*
s0 =
Te0[(t0 >> 24) ] ^
Te1[(t1 >> 16) & 0xff] ^
Te2[(t2 >> 8) & 0xff] ^
Te3[(t3 ) & 0xff] ^
rk[0];
s1 =
Te0[(t1 >> 24) ] ^
Te1[(t2 >> 16) & 0xff] ^
Te2[(t3 >> 8) & 0xff] ^
Te3[(t0 ) & 0xff] ^
rk[1];
s2 =
Te0[(t2 >> 24) ] ^
Te1[(t3 >> 16) & 0xff] ^
Te2[(t0 >> 8) & 0xff] ^
Te3[(t1 ) & 0xff] ^
rk[2];
s3 =
Te0[(t3 >> 24) ] ^
Te1[(t0 >> 16) & 0xff] ^
Te2[(t1 >> 8) & 0xff] ^
Te3[(t2 ) & 0xff] ^
rk[3];
}
#endif /* ?FULL_UNROLL */
/*
* apply last round and
* map cipher state to byte array block:
*/
@ -1180,13 +1421,16 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
PUTU32(ct + 12, s3);
}
static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
u32 s0, s1, s2, s3, t0, t1, t2, t3;
void
aes_decrypt(const u32int rk[/* 4*(Nr + 1) */], int Nr, const uchar ct[16],
uchar pt[16])
{
ulong s0, s1, s2, s3, t0, t1, t2, t3;
#ifndef FULL_UNROLL
int r;
#endif /* ?FULL_UNROLL */
int r;
#endif /* ?FULL_UNROLL */
/*
/*
* map byte array block to cipher state
* and add initial round key:
*/
@ -1264,8 +1508,8 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
}
}
rk += Nr << 2;
#else /* !FULL_UNROLL */
rk += Nr << 2;
#else /* !FULL_UNROLL */
/*
* Nr - 1 full rounds:
*/
@ -1297,9 +1541,8 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16
rk[7];
rk += 8;
if (--r == 0) {
if (--r == 0)
break;
}
s0 =
Td0[(t0 >> 24) ] ^
@ -1326,8 +1569,8 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16
Td3[(t0 ) & 0xff] ^
rk[3];
}
#endif /* ?FULL_UNROLL */
/*
#endif /* ?FULL_UNROLL */
/*
* apply last round and
* map cipher state to byte array block:
*/
@ -1363,11 +1606,14 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16
#ifdef INTERMEDIATE_VALUE_KAT
static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
static void
aes_encryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
int rounds)
{
int r;
u32 s0, s1, s2, s3, t0, t1, t2, t3;
/*
/*
* map byte array block to cipher state
* and add initial round key:
*/
@ -1375,9 +1621,9 @@ static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
s1 = GETU32(block + 4) ^ rk[1];
s2 = GETU32(block + 8) ^ rk[2];
s3 = GETU32(block + 12) ^ rk[3];
rk += 4;
rk += 4;
/*
/*
* Nr - 1 full rounds:
*/
for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) {
@ -1405,45 +1651,42 @@ static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
Te2[(s1 >> 8) & 0xff] ^
Te3[(s2 ) & 0xff] ^
rk[3];
s0 = t0;
s1 = t1;
s2 = t2;
s3 = t3;
rk += 4;
}
}
/*
/*
* apply last round and
* map cipher state to byte array block:
*/
if (rounds == Nr) {
t0 =
(Te4[(s0 >> 24) ] << 24) ^
(Te4[(s1 >> 16) & 0xff] << 16) ^
(Te4[(s2 >> 8) & 0xff] << 8) ^
(Te4[(s3 ) & 0xff] ) ^
rk[0];
t1 =
(Te4[(s1 >> 24) ] << 24) ^
(Te4[(s2 >> 16) & 0xff] << 16) ^
(Te4[(s3 >> 8) & 0xff] << 8) ^
(Te4[(s0 ) & 0xff] ) ^
rk[1];
t2 =
(Te4[(s2 >> 24) ] << 24) ^
(Te4[(s3 >> 16) & 0xff] << 16) ^
(Te4[(s0 >> 8) & 0xff] << 8) ^
(Te4[(s1 ) & 0xff] ) ^
rk[2];
t3 =
(Te4[(s3 >> 24) ] << 24) ^
(Te4[(s0 >> 16) & 0xff] << 16) ^
(Te4[(s1 >> 8) & 0xff] << 8) ^
(Te4[(s2 ) & 0xff] ) ^
rk[3];
t0 =
(Te4[(s0 >> 24) ] << 24) ^
(Te4[(s1 >> 16) & 0xff] << 16) ^
(Te4[(s2 >> 8) & 0xff] << 8) ^
(Te4[(s3 ) & 0xff] ) ^
rk[0];
t1 =
(Te4[(s1 >> 24) ] << 24) ^
(Te4[(s2 >> 16) & 0xff] << 16) ^
(Te4[(s3 >> 8) & 0xff] << 8) ^
(Te4[(s0 ) & 0xff] ) ^
rk[1];
t2 =
(Te4[(s2 >> 24) ] << 24) ^
(Te4[(s3 >> 16) & 0xff] << 16) ^
(Te4[(s0 >> 8) & 0xff] << 8) ^
(Te4[(s1 ) & 0xff] ) ^
rk[2];
t3 =
(Te4[(s3 >> 24) ] << 24) ^
(Te4[(s0 >> 16) & 0xff] << 16) ^
(Te4[(s1 >> 8) & 0xff] << 8) ^
(Te4[(s2 ) & 0xff] ) ^
rk[3];
s0 = t0;
s1 = t1;
s2 = t2;
@ -1456,11 +1699,14 @@ static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
PUTU32(block + 12, s3);
}
static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
static void
aes_decryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
int rounds)
{
int r;
u32 s0, s1, s2, s3, t0, t1, t2, t3;
/*
/*
* map byte array block to cipher state
* and add initial round key:
*/
@ -1468,9 +1714,9 @@ static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
s1 = GETU32(block + 4) ^ rk[1];
s2 = GETU32(block + 8) ^ rk[2];
s3 = GETU32(block + 12) ^ rk[3];
rk += 4;
rk += 4;
/*
/*
* Nr - 1 full rounds:
*/
for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) {
@ -1504,10 +1750,9 @@ static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
s2 = t2;
s3 = t3;
rk += 4;
}
}
/*
/*
* complete the last round and
* map cipher state to byte array block:
*/
@ -1533,10 +1778,10 @@ static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
(Td4[(s0 ) & 0xff] );
if (rounds == Nr) {
t0 ^= rk[0];
t1 ^= rk[1];
t2 ^= rk[2];
t3 ^= rk[3];
t0 ^= rk[0];
t1 ^= rk[1];
t2 ^= rk[2];
t3 ^= rk[3];
}
PUTU32(block , t0);
@ -1545,4 +1790,4 @@ static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
PUTU32(block + 12, t3);
}
#endif /* INTERMEDIATE_VALUE_KAT */
#endif /* INTERMEDIATE_VALUE_KAT */

View file

@ -6,7 +6,7 @@
#define STRLEN(s) (sizeof(s)-1)
uchar*
decodepem(char *s, char *type, int *len, char **news)
decodePEM(char *s, char *type, int *len, char **new_s)
{
uchar *d;
char *t, *e, *tt;
@ -44,8 +44,8 @@ decodepem(char *s, char *type, int *len, char **news)
return nil;
}
if(news)
*news = tt+1;
if(new_s)
*new_s = tt+1;
n = ((tt - t) * 6 + 7) / 8;
d = malloc(n);
if(d == nil){
@ -72,7 +72,7 @@ decodepemchain(char *s, char *type)
e = strchr(s, '\0');
while (s < e) {
d = decodepem(s, type, &n, &s);
d = decodePEM(s, type, &n, &s);
if(d == nil)
break;
chp = malloc(sizeof(PEMChain));

View file

@ -2,27 +2,25 @@
#include <libsec.h>
/* rfc2104 */
static DigestState*
DigestState*
hmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen)
{
int i;
uchar pad[65], innerdigest[256];
uchar pad[Hmacblksz+1], innerdigest[256];
if(xlen > sizeof(innerdigest))
return nil;
if(klen>64)
if(klen > Hmacblksz)
return nil;
/* first time through */
if(s == nil){
for(i=0; i<64; i++)
pad[i] = 0x36;
pad[64] = 0;
for(i=0; i<klen; i++)
if(s == nil || s->seeded == 0){
memset(pad, 0x36, Hmacblksz);
pad[Hmacblksz] = 0;
for(i = 0; i < klen; i++)
pad[i] ^= key[i];
s = (*x)(pad, 64, nil, nil);
s = (*x)(pad, Hmacblksz, nil, s);
if(s == nil)
return nil;
}
@ -32,25 +30,12 @@ hmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *
return s;
/* last time through */
for(i=0; i<64; i++)
pad[i] = 0x5c;
pad[64] = 0;
for(i=0; i<klen; i++)
memset(pad, 0x5c, Hmacblksz);
pad[Hmacblksz] = 0;
for(i = 0; i < klen; i++)
pad[i] ^= key[i];
(*x)(nil, 0, innerdigest, s);
s = (*x)(pad, 64, nil, nil);
s = (*x)(pad, Hmacblksz, nil, nil);
(*x)(innerdigest, xlen, digest, s);
return nil;
}
DigestState*
hmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen);
}
DigestState*
hmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, md5, MD5dlen);
}

View file

@ -24,7 +24,7 @@ enum
S31= 3,
S32= 9,
S33= 11,
S34= 15
S34= 15,
};
typedef struct MD4Table MD4Table;

View file

@ -145,3 +145,10 @@ encode(uchar *output, u32int *input, ulong len)
*output++ = x >> 24;
}
}
DigestState*
hmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, md5, MD5dlen);
}

View file

@ -7,7 +7,7 @@ md5pickle(MD5state *s)
char *p;
int m, n;
m = 17+4*9+4*((s->blen+3)/3);
m = 17+4*9+4*((s->blen+3)/3 + 1);
p = malloc(m);
if(p == nil)
return p;

View file

@ -49,6 +49,11 @@ ALLOFILES=\
sha1.$O\
sha1block.$O\
sha1pickle.$O\
sha2_128.$O\
sha2_64.$O\
sha2block128.$O\
sha2block64.$O\
sha2test.$O\
smallprimetest.$O\
thumb.$O\
tlshand.$O\

View file

@ -1,56 +1,61 @@
aes.c 2004/1225
blowfish.c 2004/1225
decodepem.c 2004/1225
des.c 2004/1225
des3CBC.c 2004/1225
des3ECB.c 2004/1225
desCBC.c 2004/1225
desECB.c 2004/1225
desmodes.c 2004/1225
dsaalloc.c 2004/1225
dsagen.c 2004/1225
dsaprimes.c 2004/1225
dsaprivtopub.c 2004/1225
dsasign.c 2004/1225
dsaverify.c 2004/1225
egalloc.c 2004/1225
egdecrypt.c 2004/1225
egencrypt.c 2004/1225
eggen.c 2004/1225
egprivtopub.c 2004/1225
egsign.c 2004/1225
egtest.c 2004/1225
egverify.c 2004/1225
fastrand.c 2004/1225
genprime.c 2004/1225
genrandom.c 2004/1225
gensafeprime.c 2004/1225
genstrongprime.c 2004/1225
hmac.c 2004/1225
hmactest.c 2004/1225
md4.c 2004/1225
md4test.c 2004/1225
md5.c 2004/1225
md5block.c 2004/1225
md5pickle.c 2004/1225
nfastrand.c 2004/1225
primetest.c 2004/1225
prng.c 2004/1225
probably_prime.c 2004/1225
rc4.c 2004/1225
readcert.c 2004/1225
rsaalloc.c 2004/1225
rsadecrypt.c 2004/1225
rsaencrypt.c 2004/1225
rsafill.c 2004/1225
rsagen.c 2004/1225
rsaprivtopub.c 2004/1225
rsatest.c 2004/1225
sha1.c 2004/1225
sha1block.c 2004/1225
sha1pickle.c 2004/1225
smallprimes.c 2004/1225
smallprimetest.c 2004/1225
thumb.c 2004/1225
tlshand.c 2004/1225
x509.c 2004/1225
aes.c 2021/0202
blowfish.c 2021/0202
decodepem.c 2021/0202
des3CBC.c 2021/0202
des3ECB.c 2021/0202
des.c 2021/0202
desCBC.c 2021/0202
desECB.c 2021/0202
desmodes.c 2021/0202
dsaalloc.c 2021/0202
dsagen.c 2021/0202
dsaprimes.c 2021/0202
dsaprivtopub.c 2021/0202
dsasign.c 2021/0202
dsaverify.c 2021/0202
egalloc.c 2021/0202
egdecrypt.c 2021/0202
egencrypt.c 2021/0202
eggen.c 2021/0202
egprivtopub.c 2021/0202
egsign.c 2021/0202
egtest.c 2021/0202
egverify.c 2021/0202
fastrand.c 2021/0202
genprime.c 2021/0202
genrandom.c 2021/0202
gensafeprime.c 2021/0202
genstrongprime.c 2021/0202
hmac.c 2021/0202
hmactest.c 2021/0202
md4.c 2021/0202
md4test.c 2021/0202
md5block.c 2021/0202
md5.c 2021/0202
md5pickle.c 2021/0202
nfastrand.c 2021/0202
primetest.c 2021/0202
prng.c 2021/0202
probably_prime.c 2021/0202
rc4.c 2021/0202
readcert.c 2021/0202
rsaalloc.c 2021/0202
rsadecrypt.c 2021/0202
rsaencrypt.c 2021/0202
rsafill.c 2021/0202
rsagen.c 2021/0202
rsaprivtopub.c 2021/0202
rsatest.c 2021/0202
sha1block.c 2021/0202
sha1.c 2021/0202
sha1pickle.c 2021/0202
sha2_128.c 2021/0202
sha2_64.c 2021/0202
sha2block128.c 2021/0202
sha2block64.c 2021/0202
sha2test.c 2021/0202
smallprimes.c 2021/0202
smallprimetest.c 2021/0202
thumb.c 2021/0202
tlshand.c 2021/0202
x509.c 2021/0202

View file

@ -2,10 +2,12 @@
#include <mp.h>
#include <libsec.h>
/* Miller-Rabin probabilistic primality testing */
/* Knuth (1981) Seminumerical Algorithms, p.379 */
/* Menezes et al () Handbook, p.39 */
/* 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep */
/*
* Miller-Rabin probabilistic primality testing
* Knuth (1981) Seminumerical Algorithms, p.379
* Menezes et al () Handbook, p.39
* 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep
*/
int
probably_prime(mpint *n, int nrep)
{

View file

@ -14,8 +14,10 @@ readfile(char *name)
fd = open(name, OREAD);
if(fd < 0)
return nil;
if((d = dirfstat(fd)) == nil)
if((d = dirfstat(fd)) == nil) {
close(fd);
return nil;
}
s = malloc(d->length + 1);
if(s == nil || readn(fd, s, d->length) != d->length){
free(s);
@ -37,10 +39,10 @@ readcert(char *filename, int *pcertlen)
pem = readfile(filename);
if(pem == nil){
werrstr("can't read %s", filename);
werrstr("can't read %s: %r", filename);
return nil;
}
binary = decodepem(pem, "CERTIFICATE", pcertlen, nil);
binary = decodePEM(pem, "CERTIFICATE", pcertlen, nil);
free(pem);
if(binary == nil){
werrstr("can't parse %s", filename);
@ -49,18 +51,15 @@ readcert(char *filename, int *pcertlen)
return binary;
}
PEMChain *
readcertchain(char *filename)
{
char *chfile;
PEMChain *chp;
chfile = readfile(filename);
if (chfile == nil) {
werrstr("can't read %s", filename);
werrstr("can't read %s: %r", filename);
return nil;
}
chp = decodepemchain(chfile, "CERTIFICATE");
return chp;
return decodepemchain(chfile, "CERTIFICATE");
}

View file

@ -6,16 +6,15 @@
void
main(void)
{
RSApriv *rsa;
Biobuf b;
char *p;
int n;
mpint *clr, *enc, *clr2;
uchar buf[4096];
uchar *e;
vlong start;
char *p;
uchar buf[4096];
Biobuf b;
RSApriv *rsa;
mpint *clr, *enc, *clr2;
fmtinstall('B', mpconv);
fmtinstall('B', mpfmt);
rsa = rsagen(1024, 16, 0);
if(rsa == nil)

View file

@ -125,3 +125,10 @@ encode(uchar *output, u32int *input, ulong len)
*output++ = x;
}
}
DigestState*
hmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen);
}

191
src/libsec/port/sha2_128.c Normal file
View file

@ -0,0 +1,191 @@
/*
* sha2 128-bit
*/
#include <u.h>
#include <libc.h>
#include <libsec.h>
static void encode64(uchar*, u64int*, ulong);
static DigestState* sha2_128(uchar *, ulong, uchar *, SHA2_256state *, int);
extern void _sha2block128(uchar*, ulong, u64int*);
/*
* for sha2_384 and sha2_512, len must be multiple of 128 for all but
* the last call. There must be room in the input buffer to pad.
*
* Note: sha2_384 calls sha2_512block as sha2_384; it just uses a different
* initial seed to produce a truncated 384b hash result. otherwise
* it's the same as sha2_512.
*/
SHA2_384state*
sha2_384(uchar *p, ulong len, uchar *digest, SHA2_384state *s)
{
if(s == nil) {
s = mallocz(sizeof(*s), 1);
if(s == nil)
return nil;
s->malloced = 1;
}
if(s->seeded == 0){
/*
* seed the state with the first 64 bits of the fractional
* parts of the square roots of the 9th thru 16th primes.
*/
s->bstate[0] = 0xcbbb9d5dc1059ed8LL;
s->bstate[1] = 0x629a292a367cd507LL;
s->bstate[2] = 0x9159015a3070dd17LL;
s->bstate[3] = 0x152fecd8f70e5939LL;
s->bstate[4] = 0x67332667ffc00b31LL;
s->bstate[5] = 0x8eb44a8768581511LL;
s->bstate[6] = 0xdb0c2e0d64f98fa7LL;
s->bstate[7] = 0x47b5481dbefa4fa4LL;
s->seeded = 1;
}
return sha2_128(p, len, digest, s, SHA2_384dlen);
}
SHA2_512state*
sha2_512(uchar *p, ulong len, uchar *digest, SHA2_512state *s)
{
if(s == nil) {
s = mallocz(sizeof(*s), 1);
if(s == nil)
return nil;
s->malloced = 1;
}
if(s->seeded == 0){
/*
* seed the state with the first 64 bits of the fractional
* parts of the square roots of the first 8 primes 2..19).
*/
s->bstate[0] = 0x6a09e667f3bcc908LL;
s->bstate[1] = 0xbb67ae8584caa73bLL;
s->bstate[2] = 0x3c6ef372fe94f82bLL;
s->bstate[3] = 0xa54ff53a5f1d36f1LL;
s->bstate[4] = 0x510e527fade682d1LL;
s->bstate[5] = 0x9b05688c2b3e6c1fLL;
s->bstate[6] = 0x1f83d9abfb41bd6bLL;
s->bstate[7] = 0x5be0cd19137e2179LL;
s->seeded = 1;
}
return sha2_128(p, len, digest, s, SHA2_512dlen);
}
/* common 128 byte block padding and count code for SHA2_384 and SHA2_512 */
static DigestState*
sha2_128(uchar *p, ulong len, uchar *digest, SHA2_512state *s, int dlen)
{
int i;
u64int x[16];
uchar buf[256];
uchar *e;
/* fill out the partial 128 byte block from previous calls */
if(s->blen){
i = 128 - s->blen;
if(len < i)
i = len;
memmove(s->buf + s->blen, p, i);
len -= i;
s->blen += i;
p += i;
if(s->blen == 128){
_sha2block128(s->buf, s->blen, s->bstate);
s->len += s->blen;
s->blen = 0;
}
}
/* do 128 byte blocks */
i = len & ~(128-1);
if(i){
_sha2block128(p, i, s->bstate);
s->len += i;
len -= i;
p += i;
}
/* save the left overs if not last call */
if(digest == 0){
if(len){
memmove(s->buf, p, len);
s->blen += len;
}
return s;
}
/*
* this is the last time through, pad what's left with 0x80,
* 0's, and the input count to create a multiple of 128 bytes.
*/
if(s->blen){
p = s->buf;
len = s->blen;
} else {
memmove(buf, p, len);
p = buf;
}
s->len += len;
e = p + len;
if(len < 112)
i = 112 - len;
else
i = 240 - len;
memset(e, 0, i);
*e = 0x80;
len += i;
/* append the count */
x[0] = 0; /* assume 32b length, i.e. < 4GB */
x[1] = s->len<<3;
encode64(p+len, x, 16);
/* digest the last part */
_sha2block128(p, len+16, s->bstate);
s->len += len+16;
/* return result and free state */
encode64(digest, s->bstate, dlen);
if(s->malloced == 1)
free(s);
return nil;
}
/*
* Encodes input (ulong long) into output (uchar).
* Assumes len is a multiple of 8.
*/
static void
encode64(uchar *output, u64int *input, ulong len)
{
u64int x;
uchar *e;
for(e = output + len; output < e;) {
x = *input++;
*output++ = x >> 56;
*output++ = x >> 48;
*output++ = x >> 40;
*output++ = x >> 32;
*output++ = x >> 24;
*output++ = x >> 16;
*output++ = x >> 8;
*output++ = x;
}
}
DigestState*
hmac_sha2_384(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, sha2_384, SHA2_384dlen);
}
DigestState*
hmac_sha2_512(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, sha2_512, SHA2_512dlen);
}

187
src/libsec/port/sha2_64.c Normal file
View file

@ -0,0 +1,187 @@
/*
* sha2 64-bit
*/
#include <u.h>
#include <libc.h>
#include <libsec.h>
static void encode32(uchar*, u32int*, ulong);
static DigestState* sha2_64(uchar *, ulong, uchar *, SHA2_256state *, int);
extern void _sha2block64(uchar*, ulong, u32int*);
/*
* for sha2_224 and sha2_256, len must be multiple of 64 for all but
* the last call. There must be room in the input buffer to pad.
*
* Note: sha2_224 calls sha2_256block as sha2_224, just uses different
* initial seed and produces a 224b hash result. otherwise it's
* the same as sha2_256.
*/
SHA2_224state*
sha2_224(uchar *p, ulong len, uchar *digest, SHA2_224state *s)
{
if(s == nil) {
s = mallocz(sizeof(*s), 1);
if(s == nil)
return nil;
s->malloced = 1;
}
if(s->seeded == 0){
/*
* seed the state with the first 32 bits of the fractional
* parts of the square roots of the first 8 primes 2..19).
*/
s->state[0] = 0xc1059ed8;
s->state[1] = 0x367cd507;
s->state[2] = 0x3070dd17;
s->state[3] = 0xf70e5939;
s->state[4] = 0xffc00b31;
s->state[5] = 0x68581511;
s->state[6] = 0x64f98fa7;
s->state[7] = 0xbefa4fa4;
s->seeded = 1;
}
return sha2_64(p, len, digest, s, SHA2_224dlen);
}
SHA2_256state*
sha2_256(uchar *p, ulong len, uchar *digest, SHA2_256state *s)
{
if(s == nil) {
s = mallocz(sizeof(*s), 1);
if(s == nil)
return nil;
s->malloced = 1;
}
if(s->seeded == 0){
/*
* seed the state with the first 32 bits of the fractional
* parts of the square roots of the first 8 primes 2..19).
*/
s->state[0] = 0x6a09e667;
s->state[1] = 0xbb67ae85;
s->state[2] = 0x3c6ef372;
s->state[3] = 0xa54ff53a;
s->state[4] = 0x510e527f;
s->state[5] = 0x9b05688c;
s->state[6] = 0x1f83d9ab;
s->state[7] = 0x5be0cd19;
s->seeded = 1;
}
return sha2_64(p, len, digest, s, SHA2_256dlen);
}
/* common 64 byte block padding and count code for SHA2_224 and SHA2_256 */
static DigestState*
sha2_64(uchar *p, ulong len, uchar *digest, SHA2_256state *s, int dlen)
{
int i;
u32int x[16];
uchar buf[128];
uchar *e;
/* fill out the partial 64 byte block from previous calls */
if(s->blen){
i = 64 - s->blen;
if(len < i)
i = len;
memmove(s->buf + s->blen, p, i);
len -= i;
s->blen += i;
p += i;
if(s->blen == 64){
_sha2block64(s->buf, s->blen, s->state);
s->len += s->blen;
s->blen = 0;
}
}
/* do 64 byte blocks */
i = len & ~(64-1);
if(i){
_sha2block64(p, i, s->state);
s->len += i;
len -= i;
p += i;
}
/* save the left overs if not last call */
if(digest == 0){
if(len){
memmove(s->buf, p, len);
s->blen += len;
}
return s;
}
/*
* this is the last time through, pad what's left with 0x80,
* 0's, and the input count to create a multiple of 64 bytes.
*/
if(s->blen){
p = s->buf;
len = s->blen;
} else {
memmove(buf, p, len);
p = buf;
}
s->len += len;
e = p + len;
if(len < 56)
i = 56 - len;
else
i = 120 - len;
memset(e, 0, i);
*e = 0x80;
len += i;
/* append the count */
x[0] = s->len>>29;
x[1] = s->len<<3;
encode32(p+len, x, 8);
/* digest the last part */
_sha2block64(p, len+8, s->state);
s->len += len+8;
/* return result and free state */
encode32(digest, s->state, dlen);
if(s->malloced == 1)
free(s);
return nil;
}
/*
* Encodes input (ulong) into output (uchar).
* Assumes len is a multiple of 4.
*/
static void
encode32(uchar *output, u32int *input, ulong len)
{
u32int x;
uchar *e;
for(e = output + len; output < e;) {
x = *input++;
*output++ = x >> 24;
*output++ = x >> 16;
*output++ = x >> 8;
*output++ = x;
}
}
DigestState*
hmac_sha2_224(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, sha2_224, SHA2_224dlen);
}
DigestState*
hmac_sha2_256(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
DigestState *s)
{
return hmac_x(p, len, key, klen, digest, s, sha2_256, SHA2_256dlen);
}

View file

@ -0,0 +1,101 @@
/*
* sha2_512 block cipher
*
* Implementation straight from Federal Information Processing Standards
* publication 180-2 (+Change Notice to include SHA-224) August 1, 2002
* note: the following upper and lower case macro names are distinct
* and reflect the functions defined in FIPS pub. 180-2.
*/
#include <u.h>
#include <libc.h>
#define ROTR(x,n) (((x) >> (n)) | ((x) << (64-(n))))
#define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x) >> 7))
#define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x) >> 6))
#define SIGMA0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
#define SIGMA1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41))
#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
/*
* first 64 bits of the fractional parts of cube roots of
* first 80 primes (2..311).
*/
static u64int K512[80] = {
0x428a2f98d728ae22LL, 0x7137449123ef65cdLL, 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL,
0x3956c25bf348b538LL, 0x59f111f1b605d019LL, 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL,
0xd807aa98a3030242LL, 0x12835b0145706fbeLL, 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL,
0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL, 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL,
0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL, 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL,
0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL, 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL,
0x983e5152ee66dfabLL, 0xa831c66d2db43210LL, 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL,
0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL, 0x06ca6351e003826fLL, 0x142929670a0e6e70LL,
0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL, 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL,
0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL, 0x81c2c92e47edaee6LL, 0x92722c851482353bLL,
0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL, 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL,
0xd192e819d6ef5218LL, 0xd69906245565a910LL, 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL,
0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL, 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL,
0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL, 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL,
0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL, 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL,
0x90befffa23631e28LL, 0xa4506cebde82bde9LL, 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL,
0xca273eceea26619cLL, 0xd186b8c721c0c207LL, 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL,
0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL, 0x113f9804bef90daeLL, 0x1b710b35131c471bLL,
0x28db77f523047d84LL, 0x32caab7b40c72493LL, 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL,
0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL, 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL };
void
_sha2block128(uchar *p, ulong len, u64int *s)
{
u64int a, b, c, d, e, f, g, h, t1, t2;
u64int *kp, *wp;
u64int w[80];
uchar *end;
/* at this point, we have a multiple of 64 bytes */
for(end = p+len; p < end;){
a = s[0];
b = s[1];
c = s[2];
d = s[3];
e = s[4];
f = s[5];
g = s[6];
h = s[7];
for(wp = w; wp < &w[16]; wp++, p += 8)
wp[0] = ((vlong)p[0])<<56 | ((vlong)p[1])<<48 |
((vlong)p[2])<<40 | ((vlong)p[3])<<32 |
p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7];
for(; wp < &w[80]; wp++) {
u64int s0, s1;
s0 = sigma0(wp[-15]);
s1 = sigma1(wp[-2]);
/* wp[0] = sigma1(wp[-2]) + wp[-7] + sigma0(wp[-15]) + wp[-16]; */
wp[0] = s1 + wp[-7] + s0 + wp[-16];
}
for(kp = K512, wp = w; wp < &w[80]; ) {
t1 = h + SIGMA1(e) + Ch(e,f,g) + *kp++ + *wp++;
t2 = SIGMA0(a) + Maj(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
/* save state */
s[0] += a;
s[1] += b;
s[2] += c;
s[3] += d;
s[4] += e;
s[5] += f;
s[6] += g;
s[7] += h;
}
}

View file

@ -0,0 +1,92 @@
/*
* sha2_256 block cipher
*
* Implementation straight from Federal Information Processing Standards
* publication 180-2 (+Change Notice to include SHA-224) August 1, 2002
* note: the following upper and lower case macro names are distinct
* and reflect the functions defined in FIPS pub. 180-2.
*/
#include <u.h>
#include <libc.h>
#define ROTR(x,n) (((x) >> (n)) | ((x) << (32-(n))))
#define sigma0(x) (ROTR((x),7) ^ ROTR((x),18) ^ ((x) >> 3))
#define sigma1(x) (ROTR((x),17) ^ ROTR((x),19) ^ ((x) >> 10))
#define SIGMA0(x) (ROTR((x),2) ^ ROTR((x),13) ^ ROTR((x),22))
#define SIGMA1(x) (ROTR((x),6) ^ ROTR((x),11) ^ ROTR((x),25))
#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
/*
* first 32 bits of the fractional parts of cube roots of
* first 64 primes (2..311).
*/
static u32int K256[64] = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,
0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,
0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,
0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,
0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,
0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,
0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,
0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,
0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2,
};
void
_sha2block64(uchar *p, ulong len, u32int *s)
{
u32int a, b, c, d, e, f, g, h, t1, t2;
u32int *kp, *wp;
u32int w[64];
uchar *end;
/* at this point, we have a multiple of 64 bytes */
for(end = p+len; p < end;){
a = s[0];
b = s[1];
c = s[2];
d = s[3];
e = s[4];
f = s[5];
g = s[6];
h = s[7];
for(wp = w; wp < &w[16]; wp++, p += 4)
wp[0] = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
for(; wp < &w[64]; wp++)
wp[0] = sigma1(wp[-2]) + wp[-7] +
sigma0(wp[-15]) + wp[-16];
for(kp = K256, wp = w; wp < &w[64]; ) {
t1 = h + SIGMA1(e) + Ch(e,f,g) + *kp++ + *wp++;
t2 = SIGMA0(a) + Maj(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
/* save state */
s[0] += a;
s[1] += b;
s[2] += c;
s[3] += d;
s[4] += e;
s[5] += f;
s[6] += g;
s[7] += h;
}
}

View file

@ -0,0 +1,63 @@
#include <u.h>
#include <libc.h>
#include "libsec.h"
char *tests[] = {
"",
"a",
"abc",
"message digest",
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
"123456789012345678901234567890123456789012345678901234567890"
"12345678901234567890",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi"
"jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
0
};
void
main(void)
{
int i;
char **pp;
uchar *p;
uchar digest[SHA2_512dlen];
print("SHA2_224 tests:\n");
for(pp = tests; *pp; pp++){
p = (uchar*)*pp;
sha2_224(p, strlen(*pp), digest, 0);
for(i = 0; i < SHA2_224dlen; i++)
print("%2.2ux", digest[i]);
print("\n");
}
print("\nSHA256 tests:\n");
for(pp = tests; *pp; pp++){
p = (uchar*)*pp;
sha2_256(p, strlen(*pp), digest, 0);
for(i = 0; i < SHA2_256dlen; i++)
print("%2.2ux", digest[i]);
print("\n");
}
print("\nSHA384 tests:\n");
for(pp = tests; *pp; pp++){
p = (uchar*)*pp;
sha2_384(p, strlen(*pp), digest, 0);
for(i = 0; i < SHA2_384dlen; i++)
print("%2.2ux", digest[i]);
print("\n");
}
print("\nSHA512 tests:\n");
for(pp = tests; *pp; pp++){
p = (uchar*)*pp;
sha2_512(p, strlen(*pp), digest, 0);
for(i = 0; i < SHA2_512dlen; i++)
print("%2.2ux", digest[i]);
print("\n");
}
}

View file

@ -17,7 +17,7 @@
enum {
TLSFinishedLen = 12,
SSL3FinishedLen = MD5dlen+SHA1dlen,
MaxKeyData = 104, /* amount of secret we may need */
MaxKeyData = 136, /* amount of secret we may need */
MaxChunk = 1<<14,
RandomSize = 32,
SidSize = 32,
@ -116,7 +116,7 @@ typedef struct Msg{
} u;
} Msg;
struct TlsSec{
typedef struct TlsSec{
char *server; /* name of remote; nil for server */
int ok; /* <0 killed; ==0 in progress; >0 reusable */
RSApub *rsapub;
@ -130,7 +130,7 @@ struct TlsSec{
void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int, uchar*, int);
void (*setFinished)(TlsSec*, MD5state, SHAstate, uchar*, int);
int nfin;
};
} TlsSec;
enum {
@ -242,6 +242,8 @@ static Algs cipherAlgs[] = {
{"rc4_128", "md5", 2 * (16 + MD5dlen), TLS_RSA_WITH_RC4_128_MD5},
{"rc4_128", "sha1", 2 * (16 + SHA1dlen), TLS_RSA_WITH_RC4_128_SHA},
{"3des_ede_cbc","sha1",2*(4*8+SHA1dlen), TLS_RSA_WITH_3DES_EDE_CBC_SHA},
{"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_RSA_WITH_AES_128_CBC_SHA},
{"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_RSA_WITH_AES_256_CBC_SHA}
};
static uchar compressors[] = {
@ -256,7 +258,7 @@ static char* msgPrint(char *buf, int n, Msg *m);
static int msgRecv(TlsConnection *c, Msg *m);
static int msgSend(TlsConnection *c, Msg *m, int act);
static void tlsError(TlsConnection *c, int err, char *msg, ...);
/* #pragma varargck argpos tlsError 3*/
#pragma varargck argpos tlsError 3
static int setVersion(TlsConnection *c, int version);
static int finishedMatch(TlsConnection *c, Finished *f);
static void tlsConnectionFree(TlsConnection *c);
@ -273,7 +275,6 @@ static TlsSec* tlsSecInitc(int cvers, uchar *crandom);
static int tlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers, uchar **epm, int *nepm, uchar *kd, int nkd);
static int tlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient);
static void tlsSecOk(TlsSec *sec);
/* static void tlsSecKill(TlsSec *sec); */
static void tlsSecClose(TlsSec *sec);
static void setMasterSecret(TlsSec *sec, Bytes *pm);
static void serverMasterSecret(TlsSec *sec, uchar *epm, int nepm);
@ -296,14 +297,12 @@ static void* erealloc(void*, int);
static void put32(uchar *p, u32int);
static void put24(uchar *p, int);
static void put16(uchar *p, int);
/* static u32int get32(uchar *p); */
static int get24(uchar *p);
static int get16(uchar *p);
static Bytes* newbytes(int len);
static Bytes* makebytes(uchar* buf, int len);
static void freebytes(Bytes* b);
static Ints* newints(int len);
/* static Ints* makeints(int* buf, int len); */
static void freeints(Ints* b);
/*================= client/server ======================== */
@ -357,6 +356,8 @@ tlsServer(int fd, TLSconn *conn)
conn->sessionIDlen = tls->sid->len;
conn->sessionID = emalloc(conn->sessionIDlen);
memcpy(conn->sessionID, tls->sid->data, conn->sessionIDlen);
if(conn->sessionKey != nil && conn->sessionType != nil && strcmp(conn->sessionType, "ttls") == 0)
tls->sec->prf(conn->sessionKey, conn->sessionKeylen, tls->sec->sec, MasterSecretSize, conn->sessionConst, tls->sec->crandom, RandomSize, tls->sec->srandom, RandomSize);
tlsConnectionFree(tls);
return data;
}
@ -408,6 +409,8 @@ tlsClient(int fd, TLSconn *conn)
conn->sessionIDlen = tls->sid->len;
conn->sessionID = emalloc(conn->sessionIDlen);
memcpy(conn->sessionID, tls->sid->data, conn->sessionIDlen);
if(conn->sessionKey != nil && conn->sessionType != nil && strcmp(conn->sessionType, "ttls") == 0)
tls->sec->prf(conn->sessionKey, conn->sessionKeylen, tls->sec->sec, MasterSecretSize, conn->sessionConst, tls->sec->crandom, RandomSize, tls->sec->srandom, RandomSize);
tlsConnectionFree(tls);
return data;
}
@ -1131,18 +1134,23 @@ msgRecv(TlsConnection *c, Msg *m)
}
break;
case HCertificateRequest:
if(n < 1)
goto Short;
nn = p[0];
p += 1;
n -= 1;
if(nn < 1 || nn > n)
goto Short;
m->u.certificateRequest.types = makebytes(p, nn);
p += nn;
n -= nn;
if(n < 2)
goto Short;
nn = get16(p);
p += 2;
n -= 2;
if(nn < 1 || nn > n)
goto Short;
m->u.certificateRequest.types = makebytes(p, nn);
nn = get24(p);
p += 3;
n -= 3;
if(nn == 0 || n != nn)
/* nn == 0 can happen; yahoo's servers do it */
if(nn != n)
goto Short;
/* cas */
i = 0;
@ -1155,7 +1163,8 @@ msgRecv(TlsConnection *c, Msg *m)
if(nn < 1 || nn > n)
goto Short;
m->u.certificateRequest.nca = i+1;
m->u.certificateRequest.cas = erealloc(m->u.certificateRequest.cas, (i+1)*sizeof(Bytes));
m->u.certificateRequest.cas = erealloc(
m->u.certificateRequest.cas, (i+1)*sizeof(Bytes));
m->u.certificateRequest.cas[i] = makebytes(p, nn);
p += nn;
n -= nn;
@ -1196,8 +1205,10 @@ msgRecv(TlsConnection *c, Msg *m)
goto Short;
Ok:
if(c->trace){
char buf[8000];
c->trace("recv %s", msgPrint(buf, sizeof buf, m));
char *buf;
buf = emalloc(8000);
c->trace("recv %s", msgPrint(buf, 8000, m));
free(buf);
}
return 1;
Short:
@ -1214,7 +1225,7 @@ msgClear(Msg *m)
switch(m->tag) {
default:
sysfatal("msgClear: unknown message type: %d\n", m->tag);
sysfatal("msgClear: unknown message type: %d", m->tag);
case HHelloRequest:
break;
case HClientHello:
@ -1591,9 +1602,9 @@ factotum_rsa_open(uchar *cert, int certlen)
RSApub *rsapub;
AuthRpc *rpc;
if((rpc = auth_allocrpc()) == nil){
/* start talking to factotum */
if((rpc = auth_allocrpc()) == nil)
return nil;
}
s = "proto=rsa service=tls role=client";
if(auth_rpc(rpc, "start", s, strlen(s)) != ARok){
factotum_rsa_close(rpc);
@ -1834,17 +1845,6 @@ tlsSecOk(TlsSec *sec)
sec->ok = 1;
}
/*
static void
tlsSecKill(TlsSec *sec)
{
if(!sec)
return;
factotum_rsa_close(sec->rpc);
sec->ok = -1;
}
*/
static void
tlsSecClose(TlsSec *sec)
{
@ -2055,9 +2055,12 @@ mptobytes(mpint* big)
uchar *a;
Bytes* ans;
a = nil;
n = (mpsignif(big)+7)/8;
m = mptobe(big, nil, n, &a);
ans = makebytes(a, m);
if(a != nil)
free(a);
return ans;
}
@ -2217,14 +2220,6 @@ put16(uchar *p, int x)
p[1] = x;
}
/*
static u32int
get32(uchar *p)
{
return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
}
*/
static int
get24(uchar *p)
{
@ -2237,8 +2232,7 @@ get16(uchar *p)
return (p[0]<<8)|p[1];
}
/* ANSI offsetof() */
#define OFFSET(x, s) ((intptr)(&(((s*)0)->x)))
#define OFFSET(x, s) offsetof(s, x)
/*
* malloc and return a new Bytes structure capable of
@ -2286,19 +2280,6 @@ newints(int len)
return ans;
}
/*
static Ints*
makeints(int* buf, int len)
{
Ints* ans;
ans = newints(len);
if(len > 0)
memmove(ans->data, buf, len*sizeof(int));
return ans;
}
*/
static void
freeints(Ints* b)
{

View file

@ -40,6 +40,7 @@ typedef struct Elist Elist;
#define REAL 9
#define ENUMERATED 10
#define EMBEDDED_PDV 11
#define UTF8String 12
#define SEQUENCE 16 /* also SEQUENCE OF */
#define SETOF 17 /* also SETOF OF */
#define NumericString 18
@ -134,10 +135,6 @@ static int is_oid(Elem* pe, Ints** poid);
static int is_string(Elem* pe, char** pstring);
static int is_time(Elem* pe, char** ptime);
static int decode(uchar* a, int alen, Elem* pelem);
/*
static int decode_seq(uchar* a, int alen, Elist** pelist);
static int decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval);
*/
static int encode(Elem e, Bytes** pbytes);
static int oid_lookup(Ints* o, Ints** tab);
static void freevalfields(Value* v);
@ -174,6 +171,7 @@ emalloc(int n)
exits("out of memory");
}
memset(p, 0, n);
setmalloctag(p, getcallerpc(&n));
return p;
}
@ -205,37 +203,6 @@ decode(uchar* a, int alen, Elem* pelem)
return ber_decode(&p, &a[alen], pelem);
}
/*
* Like decode, but continue decoding after first element
* of array ends.
*
static int
decode_seq(uchar* a, int alen, Elist** pelist)
{
uchar* p = a;
return seq_decode(&p, &a[alen], -1, 1, pelist);
}
*/
/*
* Decode the whole array as a BER encoding of an ASN1 value,
* (i.e., the part after the tag and length).
* Assume the value is encoded as universal tag "kind".
* The constr arg is 1 if the value is constructed, 0 if primitive.
* If there's an error, the return string will contain the error.
* Depending on the error, the returned value may or may not
* be nil.
*
static int
decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval)
{
uchar* p = a;
return value_decode(&p, &a[alen], alen, kind, isconstr, pval);
}
*/
/*
* All of the following decoding routines take arguments:
* uchar **pp;
@ -263,9 +230,11 @@ ber_decode(uchar** pp, uchar* pend, Elem* pelem)
if(err == ASN_OK) {
err = length_decode(pp, pend, &length);
if(err == ASN_OK) {
if(tag.class == Universal)
if(tag.class == Universal) {
err = value_decode(pp, pend, length, tag.num, isconstr, &val);
else
if(val.tag == VSeq || val.tag == VSet)
setmalloctag(val.u.seqval, getcallerpc(&pp));
}else
err = value_decode(pp, pend, length, OCTET_STRING, 0, &val);
if(err == ASN_OK) {
pelem->tag = tag;
@ -502,6 +471,7 @@ value_decode(uchar** pp, uchar* pend, int length, int kind, int isconstr, Value*
case SEQUENCE:
err = seq_decode(&p, pend, length, isconstr, &vl);
setmalloctag(vl, getcallerpc(&pp));
if(err == ASN_OK) {
pval->tag = VSeq ;
pval->u.seqval = vl;
@ -510,12 +480,13 @@ value_decode(uchar** pp, uchar* pend, int length, int kind, int isconstr, Value*
case SETOF:
err = seq_decode(&p, pend, length, isconstr, &vl);
setmalloctag(vl, getcallerpc(&pp));
if(err == ASN_OK) {
pval->tag = VSet;
pval->u.setval = vl;
}
break;
case UTF8String:
case NumericString:
case PrintableString:
case TeletexString:
@ -746,6 +717,7 @@ seq_decode(uchar** pp, uchar* pend, int length, int isconstr, Elist** pelist)
}
*pp = p;
*pelist = ans;
setmalloctag(ans, getcallerpc(&pp));
return err;
}
@ -1016,6 +988,7 @@ val_enc(uchar** pp, Elem e, int *pconstr, int lenonly)
}
break;
case UTF8String:
case NumericString:
case PrintableString:
case TeletexString:
@ -1246,6 +1219,7 @@ is_string(Elem* pe, char** pstring)
{
if(pe->tag.class == Universal) {
switch(pe->tag.num) {
case UTF8String:
case NumericString:
case PrintableString:
case TeletexString:
@ -1406,6 +1380,7 @@ mkel(Elem e, Elist* tail)
Elist* el;
el = (Elist*)emalloc(sizeof(Elist));
setmalloctag(el, getcallerpc(&e));
el->hd = e;
el->tl = tail;
return el;
@ -1575,6 +1550,7 @@ enum {
ALG_md4WithRSAEncryption,
ALG_md5WithRSAEncryption,
ALG_sha1WithRSAEncryption,
ALG_sha1WithRSAEncryptionOiw,
ALG_md5,
NUMALGS
};
@ -1587,6 +1563,7 @@ static Ints7 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };
static Ints7 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
static Ints7 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };
static Ints7 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 };
static Ints7 oid_sha1WithRSAEncryptionOiw ={6, 1, 3, 14, 3, 2, 29 };
static Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 };
static Ints *alg_oid_tab[NUMALGS+1] = {
(Ints*)(void*)&oid_rsaEncryption,
@ -1594,10 +1571,11 @@ static Ints *alg_oid_tab[NUMALGS+1] = {
(Ints*)(void*)&oid_md4WithRSAEncryption,
(Ints*)(void*)&oid_md5WithRSAEncryption,
(Ints*)(void*)&oid_sha1WithRSAEncryption,
(Ints*)(void*)&oid_sha1WithRSAEncryptionOiw,
(Ints*)(void*)&oid_md5,
nil
};
static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, md5, 0 };
static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, sha1, md5, nil };
static void
freecert(CertX509* c)
@ -1613,6 +1591,7 @@ freecert(CertX509* c)
free(c->subject);
freebytes(c->publickey);
freebytes(c->signature);
free(c);
}
/*
@ -1835,16 +1814,19 @@ static RSApub*
decode_rsapubkey(Bytes* a)
{
Elem e;
Elist *el;
Elist *el, *l;
mpint *mp;
RSApub* key;
l = nil;
key = rsapuballoc();
if(decode(a->data, a->len, &e) != ASN_OK)
goto errret;
if(!is_seq(&e, &el) || elistlen(el) != 2)
goto errret;
l = el;
key->n = mp = asn1mpint(&el->hd);
if(mp == nil)
goto errret;
@ -1853,8 +1835,13 @@ decode_rsapubkey(Bytes* a)
key->ek = mp = asn1mpint(&el->hd);
if(mp == nil)
goto errret;
if(l != nil)
freeelist(l);
return key;
errret:
if(l != nil)
freeelist(l);
rsapubfree(key);
return nil;
}
@ -2080,7 +2067,10 @@ digest_certinfo(Bytes *cert, DigestFun digestfun, uchar *digest)
length > pend - p)
return;
info = p;
if(ber_decode(&p, pend, &elem) != ASN_OK || elem.tag.num != SEQUENCE)
if(ber_decode(&p, pend, &elem) != ASN_OK)
return;
freevalfields(&elem.val);
if(elem.tag.num != SEQUENCE)
return;
infolen = p - info;
(*digestfun)(info, infolen, digest, nil);
@ -2096,6 +2086,10 @@ verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg)
int buflen;
mpint *pkcs1;
int nlen;
char *err;
err = nil;
pkcs1buf = nil;
/* one less than the byte length of the modulus */
nlen = (mpsignif(pk->n)-1)/8;
@ -2103,25 +2097,37 @@ verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg)
/* see 9.2.1 of rfc2437 */
pkcs1 = betomp(signature->data, signature->len, nil);
mpexp(pkcs1, pk->ek, pk->n, pkcs1);
pkcs1buf = nil;
buflen = mptobe(pkcs1, nil, 0, &pkcs1buf);
buf = pkcs1buf;
if(buflen != nlen || buf[0] != 1)
return "expected 1";
if(buflen != nlen || buf[0] != 1) {
err = "expected 1";
goto end;
}
buf++;
while(buf[0] == 0xff)
buf++;
if(buf[0] != 0)
return "expected 0";
if(buf[0] != 0) {
err = "expected 0";
goto end;
}
buf++;
buflen -= buf-pkcs1buf;
if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 ||
!is_octetstring(&el->tl->hd, &digest))
return "signature parse error";
!is_octetstring(&el->tl->hd, &digest)) {
err = "signature parse error";
goto end;
}
*psigalg = &el->hd;
if(memcmp(digest->data, edigest, digest->len) == 0)
return nil;
return "digests did not match";
goto end;
err = "digests did not match";
end:
if(pkcs1 != nil)
mpfree(pkcs1);
if(pkcs1buf != nil)
free(pkcs1buf);
return err;
}
RSApub*
@ -2148,6 +2154,97 @@ X509toRSApub(uchar *cert, int ncert, char *name, int nname)
return pk;
}
int
getalgo(Elem *e)
{
Value *v;
Elist *el;
int a;
if((a = parse_alg(e)) >= 0)
return a;
v = &e->val;
if(v->tag == VSeq){
print("Seq\n");
for(el = v->u.seqval; el!=nil; el = el->tl){
if((a = getalgo(&el->hd)) >= 0)
return a;
}
}
return -1;
}
static void edump(Elem e);
RSApub*
asn1toRSApub(uchar *der, int nder)
{
Elem e;
Elist *el, *l;
int n;
Bits *b;
RSApub *key;
mpint *mp;
if(decode(der, nder, &e) != ASN_OK){
print("didn't parse\n");
return nil;
}
if(!is_seq(&e, &el)){
print("no seq");
return nil;
}
if((n = elistlen(el)) != 2){
print("bad length %d\n", n);
return nil;
}
if((n = getalgo(&el->hd)) < 0){
print("no algo\n");
return nil;
}
if(n != 0){
print("cant do algorithm %d\n", n);
return nil;
}
if(!is_bitstring(&el->tl->hd, &b)){
print("no bits\n");
return nil;
}
if(decode(b->data, b->len, &e) != ASN_OK){
print("no second decode\n");
return nil;
}
if(!is_seq(&e, &el)){
print("no second seq\n");
return nil;
}
if(elistlen(el) != 2){
print("no second length\n");
return nil;
}
key = rsapuballoc();
l = el;
key->n = mp = asn1mpint(&el->hd);
if(mp == nil)
goto errret;
el = el->tl;
key->ek = mp = asn1mpint(&el->hd);
if(mp == nil)
goto errret;
if(l != nil)
freeelist(l);
return key;
errret:
if(l != nil)
freeelist(l);
rsapubfree(key);
return nil;
}
char*
X509verify(uchar *cert, int ncert, RSApub *pk)
{
@ -2345,6 +2442,34 @@ mkDN(char *dn)
return mkseq(el);
}
uchar*
RSApubtoasn1(RSApub *pub, int *keylen)
{
Elem pubkey;
Bytes *pkbytes;
uchar *key;
key = nil;
pubkey = mkseq(mkel(mkbigint(pub->n),mkel(mkint(mptoi(pub->ek)),nil)));
if(encode(pubkey, &pkbytes) != ASN_OK)
goto errret;
freevalfields(&pubkey.val);
pubkey = mkseq(
mkel(mkalg(ALG_rsaEncryption),
mkel(mkbits(pkbytes->data, pkbytes->len),
nil)));
freebytes(pkbytes);
if(encode(pubkey, &pkbytes) != ASN_OK)
goto errret;
if(keylen)
*keylen = pkbytes->len;
key = malloc(pkbytes->len);
memmove(key, pkbytes->data, pkbytes->len);
free(pkbytes);
errret:
freevalfields(&pubkey.val);
return key;
}
uchar*
X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
@ -2479,33 +2604,34 @@ tagdump(Tag tag)
if(tag.class != Universal)
return smprint("class%d,num%d", tag.class, tag.num);
switch(tag.num){
case BOOLEAN: return "BOOLEAN"; break;
case INTEGER: return "INTEGER"; break;
case BIT_STRING: return "BIT STRING"; break;
case OCTET_STRING: return "OCTET STRING"; break;
case NULLTAG: return "NULLTAG"; break;
case OBJECT_ID: return "OID"; break;
case ObjectDescriptor: return "OBJECT_DES"; break;
case EXTERNAL: return "EXTERNAL"; break;
case REAL: return "REAL"; break;
case ENUMERATED: return "ENUMERATED"; break;
case EMBEDDED_PDV: return "EMBEDDED PDV"; break;
case SEQUENCE: return "SEQUENCE"; break;
case SETOF: return "SETOF"; break;
case NumericString: return "NumericString"; break;
case PrintableString: return "PrintableString"; break;
case TeletexString: return "TeletexString"; break;
case VideotexString: return "VideotexString"; break;
case IA5String: return "IA5String"; break;
case UTCTime: return "UTCTime"; break;
case GeneralizedTime: return "GeneralizedTime"; break;
case GraphicString: return "GraphicString"; break;
case VisibleString: return "VisibleString"; break;
case GeneralString: return "GeneralString"; break;
case UniversalString: return "UniversalString"; break;
case BMPString: return "BMPString"; break;
default:
return smprint("Universal,num%d", tag.num);
case BOOLEAN: return "BOOLEAN";
case INTEGER: return "INTEGER";
case BIT_STRING: return "BIT STRING";
case OCTET_STRING: return "OCTET STRING";
case NULLTAG: return "NULLTAG";
case OBJECT_ID: return "OID";
case ObjectDescriptor: return "OBJECT_DES";
case EXTERNAL: return "EXTERNAL";
case REAL: return "REAL";
case ENUMERATED: return "ENUMERATED";
case EMBEDDED_PDV: return "EMBEDDED PDV";
case SEQUENCE: return "SEQUENCE";
case SETOF: return "SETOF";
case UTF8String: return "UTF8String";
case NumericString: return "NumericString";
case PrintableString: return "PrintableString";
case TeletexString: return "TeletexString";
case VideotexString: return "VideotexString";
case IA5String: return "IA5String";
case UTCTime: return "UTCTime";
case GeneralizedTime: return "GeneralizedTime";
case GraphicString: return "GraphicString";
case VisibleString: return "VisibleString";
case GeneralString: return "GeneralString";
case UniversalString: return "UniversalString";
case BMPString: return "BMPString";
default:
return smprint("Universal,num%d", tag.num);
}
}
@ -2525,7 +2651,10 @@ edump(Elem e)
case VBigInt: print("BigInt[%d] %.2x%.2x...",v.u.bigintval->len,v.u.bigintval->data[0],v.u.bigintval->data[1]); break;
case VReal: print("Real..."); break;
case VOther: print("Other..."); break;
case VBitString: print("BitString..."); break;
case VBitString: print("BitString");
for(i = 0; i<v.u.bitstringval->len; i++)
print(" %02x", v.u.bitstringval->data[i]);
break;
case VNull: print("Null"); break;
case VEOC: print("EOC..."); break;
case VObjId: print("ObjId");