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

@ -14,9 +14,9 @@ AUTOLIB(sec)
typedef struct mpint mpint; typedef struct mpint mpint;
#endif #endif
/*******************************************************/ /*
/* AES definitions */ * AES definitions
/*******************************************************/ */
enum enum
{ {
@ -31,19 +31,30 @@ struct AESstate
ulong setup; ulong setup;
int rounds; int rounds;
int keybytes; int keybytes;
uint ctrsz;
uchar key[AESmaxkey]; /* unexpanded key */ uchar key[AESmaxkey]; /* unexpanded key */
u32int ekey[4*(AESmaxrounds + 1)]; /* encryption key */ u32int ekey[4*(AESmaxrounds + 1)]; /* encryption key */
u32int dkey[4*(AESmaxrounds + 1)]; /* decryption key */ u32int dkey[4*(AESmaxrounds + 1)]; /* decryption key */
uchar ivec[AESbsize]; /* initialization vector */ 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 setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
void aesCBCencrypt(uchar *p, int len, AESstate *s); void aesCBCencrypt(uchar *p, int len, AESstate *s);
void aesCBCdecrypt(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);
/*******************************************************/ void setupAESXCBCstate(AESstate *s);
/* Blowfish Definitions */ uchar* aesXCBCmac(uchar *p, int len, AESstate *s);
/*******************************************************/
/*
* Blowfish Definitions
*/
enum enum
{ {
@ -70,9 +81,9 @@ void bfCBCdecrypt(uchar*, int, BFstate*);
void bfECBencrypt(uchar*, int, BFstate*); void bfECBencrypt(uchar*, int, BFstate*);
void bfECBdecrypt(uchar*, int, BFstate*); void bfECBdecrypt(uchar*, int, BFstate*);
/*******************************************************/ /*
/* DES definitions */ * DES definitions
/*******************************************************/ */
enum enum
{ {
@ -128,51 +139,82 @@ void des3CBCdecrypt(uchar*, int, DES3state*);
void des3ECBencrypt(uchar*, int, DES3state*); void des3ECBencrypt(uchar*, int, DES3state*);
void des3ECBdecrypt(uchar*, int, DES3state*); void des3ECBdecrypt(uchar*, int, DES3state*);
/*******************************************************/ /*
/* digests */ * digests
/*******************************************************/ */
enum enum
{ {
SHA1dlen= 20, /* SHA digest length */ 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 */ 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; typedef struct DigestState DigestState;
struct DigestState struct DigestState
{ {
ulong len; uvlong len;
u32int state[5]; union {
uchar buf[128]; u32int state[8];
u64int bstate[8];
};
uchar buf[256];
int blen; int blen;
char malloced; char malloced;
char seeded; char seeded;
}; };
typedef struct DigestState SHAstate; /* obsolete name */ typedef struct DigestState SHAstate; /* obsolete name */
typedef struct DigestState SHA1state; 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 MD5state;
typedef struct DigestState MD4state; typedef struct DigestState MD4state;
typedef struct DigestState AEShstate;
DigestState* md4(uchar*, ulong, uchar*, DigestState*); DigestState* md4(uchar*, ulong, uchar*, DigestState*);
DigestState* md5(uchar*, ulong, uchar*, DigestState*); DigestState* md5(uchar*, ulong, uchar*, DigestState*);
DigestState* sha1(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_md5(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
DigestState* hmac_sha1(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*); char* sha1pickle(SHA1state*);
SHA1state* sha1unpickle(char*); SHA1state* sha1unpickle(char*);
/*******************************************************/ /*
/* random number generation */ * random number generation
/*******************************************************/ */
void genrandom(uchar *buf, int nbytes); void genrandom(uchar *buf, int nbytes);
void prng(uchar *buf, int nbytes); void prng(uchar *buf, int nbytes);
ulong fastrand(void); ulong fastrand(void);
ulong nfastrand(ulong); ulong nfastrand(ulong);
/*******************************************************/ /*
/* primes */ * primes
/*******************************************************/ */
void genprime(mpint *p, int n, int accuracy); /* generate an n bit probable prime */ 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 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 */ 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 probably_prime(mpint *n, int nrep); /* miller-rabin test */
int smallprimetest(mpint *p); /* returns -1 if not prime, 0 otherwise */ int smallprimetest(mpint *p); /* returns -1 if not prime, 0 otherwise */
/*******************************************************/ /*
/* rc4 */ * rc4
/*******************************************************/ */
typedef struct RC4state RC4state; typedef struct RC4state RC4state;
struct RC4state struct RC4state
{ {
@ -196,9 +238,9 @@ void rc4(RC4state*, uchar*, int);
void rc4skip(RC4state*, int); void rc4skip(RC4state*, int);
void rc4back(RC4state*, int); void rc4back(RC4state*, int);
/*******************************************************/ /*
/* rsa */ * rsa
/*******************************************************/ */
typedef struct RSApub RSApub; typedef struct RSApub RSApub;
typedef struct RSApriv RSApriv; typedef struct RSApriv RSApriv;
typedef struct PEMChain PEMChain; typedef struct PEMChain PEMChain;
@ -225,14 +267,14 @@ struct RSApriv
mpint *c2; /* (inv p) mod q */ mpint *c2; /* (inv p) mod q */
}; };
struct PEMChain struct PEMChain{
{ PEMChain*next;
PEMChain *next;
uchar *pem; uchar *pem;
int pemlen; int pemlen;
}; };
RSApriv* rsagen(int nlen, int elen, int rounds); 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* rsaencrypt(RSApub *k, mpint *in, mpint *out);
mpint* rsadecrypt(RSApriv *k, mpint *in, mpint *out); mpint* rsadecrypt(RSApriv *k, mpint *in, mpint *out);
RSApub* rsapuballoc(void); RSApub* rsapuballoc(void);
@ -241,16 +283,20 @@ RSApriv* rsaprivalloc(void);
void rsaprivfree(RSApriv*); void rsaprivfree(RSApriv*);
RSApub* rsaprivtopub(RSApriv*); RSApub* rsaprivtopub(RSApriv*);
RSApub* X509toRSApub(uchar*, int, char*, int); RSApub* X509toRSApub(uchar*, int, char*, int);
uchar* RSApubtoasn1(RSApub*, int*);
RSApub* asn1toRSApub(uchar*, int);
RSApriv* asn1toRSApriv(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); PEMChain* decodepemchain(char *s, char *type);
uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen); 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); 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 EGpub EGpub;
typedef struct EGpriv EGpriv; typedef struct EGpriv EGpriv;
typedef struct EGsig EGsig; typedef struct EGsig EGsig;
@ -289,9 +335,9 @@ EGsig* egsigalloc(void);
void egsigfree(EGsig*); void egsigfree(EGsig*);
EGpub* egprivtopub(EGpriv*); EGpub* egprivtopub(EGpriv*);
/*******************************************************/ /*
/* dsa */ * dsa
/*******************************************************/ */
typedef struct DSApub DSApub; typedef struct DSApub DSApub;
typedef struct DSApriv DSApriv; typedef struct DSApriv DSApriv;
typedef struct DSAsig DSAsig; typedef struct DSAsig DSAsig;
@ -330,9 +376,9 @@ void dsasigfree(DSAsig*);
DSApub* dsaprivtopub(DSApriv*); DSApub* dsaprivtopub(DSApriv*);
DSApriv* asn1toDSApriv(uchar*, int); DSApriv* asn1toDSApriv(uchar*, int);
/*******************************************************/ /*
/* TLS */ * TLS
/*******************************************************/ */
typedef struct Thumbprint{ typedef struct Thumbprint{
struct Thumbprint *next; struct Thumbprint *next;
uchar sha1[SHA1dlen]; uchar sha1[SHA1dlen];
@ -342,9 +388,14 @@ typedef struct TLSconn{
char dir[40]; /* connection directory */ char dir[40]; /* connection directory */
uchar *cert; /* certificate (local on input, remote on output) */ uchar *cert; /* certificate (local on input, remote on output) */
uchar *sessionID; uchar *sessionID;
int certlen, sessionIDlen; int certlen;
int sessionIDlen;
int (*trace)(char*fmt, ...); int (*trace)(char*fmt, ...);
PEMChain *chain; PEMChain *chain;
char *sessionType;
uchar *sessionKey;
int sessionKeylen;
char *sessionConst;
} TLSconn; } TLSconn;
/* tlshand.c */ /* tlshand.c */

View file

@ -11,6 +11,12 @@ setupAESstate, aesCBCencrypt, aesCBCdecrypt - advanced encryption standard (rijn
.B #include <libsec.h> .B #include <libsec.h>
.PP .PP
.B .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) void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
.PP .PP
.B .B
@ -19,22 +25,50 @@ void aesCBCencrypt(uchar*, int, AESstate*)
.B .B
void aesCBCdecrypt(uchar*, int, AESstate*) void aesCBCdecrypt(uchar*, int, AESstate*)
.PP .PP
.SH DESCRIPTION .B
void aesCTRencrypt(uchar *p, int len, AESstate *s)
.PP .PP
DES is being replaced by Rijndael, also known as AES, as the preferred .B
block ciper. void aesCTRdecrypt(uchar *p, int len, AESstate *s)
.IR setupAESstate , .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 , .IR aesCBCencrypt ,
and and
.I aesCBCdecrypt .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 .I Keybytes
should be 16, 24, or 32. should be 16, 24, or 32.
The initialization vector The initialization vector
.I ivec .I ivec
of of
.I AESbsize .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. cryptographically strongly unpredictable.
.SH SOURCE .SH SOURCE
.B \*9/src/libsec .B \*9/src/libsec
@ -49,3 +83,13 @@ cryptographically strongly unpredictable.
.MR sechash (3) , .MR sechash (3) ,
.MR prime (3) , .MR prime (3) ,
.MR rand (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 .SH NAME
asn1dump, asn1dump,
asn1toRSApriv, asn1toRSApriv,
decodepem, decodePEM,
decodepemchain, decodepemchain,
rsadecrypt, rsadecrypt,
rsaencrypt, rsaencrypt,
@ -65,7 +65,7 @@ RSApriv* asn1toRSApriv(uchar *priv, int npriv)
void asn1dump(uchar *der, int len) void asn1dump(uchar *der, int len)
.PP .PP
.B .B
uchar* decodepem(char *s, char *type, int *len) uchar* decodePEM(char *s, char *type, int *len)
.PP .PP
.B .B
PEMChain* decodepemchain(char *s, char *type) PEMChain* decodepemchain(char *s, char *type)

View file

@ -1,6 +1,11 @@
.TH SECHASH 3 .TH SECHASH 3
.SH NAME .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 .SH SYNOPSIS
.B #include <u.h> .B #include <u.h>
.br .br
@ -35,7 +40,41 @@ DigestState* sha1(uchar *data, ulong dlen, uchar *digest,
char* sha1pickle(MD5state *state) char* sha1pickle(MD5state *state)
.PP .PP
.B .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 .PP
.B .B
DigestState* hmac_md5(uchar *data, ulong dlen, DigestState* hmac_md5(uchar *data, ulong dlen,
@ -52,12 +91,56 @@ DigestState* hmac_sha1(uchar *data, ulong dlen,
.B .B
uchar *key, ulong klen, uchar *key, ulong klen,
.br .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 .B
uchar *digest, DigestState *state) uchar *digest, DigestState *state)
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP
These functions implement We support several secure hash functions. The output of a
the cryptographic hash functions MD4, MD5, and SHA1. The output of the
hash is called a hash is called a
.IR digest . .IR digest .
A hash is secure if, given the hashed data and the digest, A hash is secure if, given the hashed data and the digest,
@ -71,11 +154,27 @@ The routines
.IR md4 , .IR md4 ,
.IR md5 , .IR md5 ,
.IR sha1 , .IR sha1 ,
.IR sha2_224 ,
.IR sha2_256 ,
.IR sha2_384 ,
.IR sha2_512 ,
.IR aes ,
.IR 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 and
.I hmac_sha1 .I hmac_aes
differ only in the length of the resulting digest 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 The first call to the routine should have
.B nil .B nil
as the as the
@ -113,20 +212,32 @@ bounded on each end by some secret:
The constants The constants
.IR MD4dlen , .IR MD4dlen ,
.IR MD5dlen , .IR MD5dlen ,
.IR SHA1dlen ,
.IR SHA2_224dlen ,
.IR SHA2_256dlen ,
.IR SHA2_384dlen,
.IR SHA2_512dlen ,
and and
.I SHA1dlen .I AESdlen
define the lengths of the digests. define the lengths of the digests.
.PP .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 and
.I hmac_sha1 .I hmac_aes
are used slightly differently. These hash algorithms are keyed and require are used slightly differently. These hash algorithms are keyed and require
a key to be specified on every call. a key to be specified on every call.
The digest lengths for these hashes are The digest lengths for these hashes are the obvious ones from
.I MD5dlen the above list of length constants.
and These routines all call
.I SHA1dlen .I hmac_x
respectively. internally, but
.I hmac_x
is not intended for general use.
.PP .PP
The functions The functions
.I md5pickle .I md5pickle

View file

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

View file

@ -30,10 +30,12 @@
*/ */
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include <mp.h>
#include <libsec.h> #include <libsec.h>
typedef uchar u8; typedef uchar u8;
typedef u32int u32; typedef u32int u32;
#define FULL_UNROLL #define FULL_UNROLL
static const u32 Td0[256]; static const u32 Td0[256];
@ -41,14 +43,28 @@ static const u32 Td1[256];
static const u32 Td2[256]; static const u32 Td2[256];
static const u32 Td3[256]; static const u32 Td3[256];
static const u8 Te4[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); static int aes_setupEnc(u32int rk[/*4*(Nr + 1)*/], const uchar cipherKey[],
#ifdef NOTUSED int keyBits);
static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); static int aes_setup(u32int erk[/*4*(Nr + 1)*/], u32int drk[/*4*(Nr + 1)*/],
#endif const uchar cipherKey[], int keyBits);
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]); void aes_encrypt(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]); void aes_decrypt(const u32int rk[], int Nr, const uchar ct[16], uchar pt[16]);
void void
setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec) setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
@ -58,17 +74,96 @@ setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
keybytes = AESmaxkey; keybytes = AESmaxkey;
memmove(s->key, key, keybytes); memmove(s->key, key, keybytes);
s->keybytes = 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) if(ivec != nil)
memmove(s->ivec, ivec, AESbsize); memmove(s->ivec, ivec, AESbsize);
if(keybytes==16 || keybytes==24 || keybytes==32) if(keybytes==16 || keybytes==24 || keybytes==32)
s->setup = 0xcafebabe; 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, */ * AES-XCBC-MAC-96 message authentication, per rfc3566.
/* the decryptor must be fed buffers of the same size as the encryptor. */ */
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 void
aesCBCencrypt(uchar *p, int len, AESstate *s) aesCBCencrypt(uchar *p, int len, AESstate *s)
{ {
@ -80,7 +175,7 @@ aesCBCencrypt(uchar *p, int len, AESstate *s)
ip = s->ivec; ip = s->ivec;
for(eip = ip+AESbsize; ip < eip; ) for(eip = ip+AESbsize; ip < eip; )
*p2++ ^= *ip++; *p2++ ^= *ip++;
rijndaelEncrypt(s->ekey, s->rounds, p, q); aes_encrypt(s->ekey, s->rounds, p, q);
memmove(s->ivec, q, AESbsize); memmove(s->ivec, q, AESbsize);
memmove(p, q, AESbsize); memmove(p, q, AESbsize);
p += AESbsize; p += AESbsize;
@ -88,7 +183,7 @@ aesCBCencrypt(uchar *p, int len, AESstate *s)
if(len > 0){ if(len > 0){
ip = s->ivec; ip = s->ivec;
rijndaelEncrypt(s->ekey, s->rounds, ip, q); aes_encrypt(s->ekey, s->rounds, ip, q);
memmove(s->ivec, q, AESbsize); memmove(s->ivec, q, AESbsize);
for(eip = ip+len; ip < eip; ) for(eip = ip+len; ip < eip; )
*p++ ^= *ip++; *p++ ^= *ip++;
@ -103,7 +198,7 @@ aesCBCdecrypt(uchar *p, int len, AESstate *s)
for(; len >= AESbsize; len -= AESbsize){ for(; len >= AESbsize; len -= AESbsize){
memmove(tmp, p, AESbsize); memmove(tmp, p, AESbsize);
rijndaelDecrypt(s->dkey, s->rounds, p, q); aes_decrypt(s->dkey, s->rounds, p, q);
memmove(p, q, AESbsize); memmove(p, q, AESbsize);
tp = tmp; tp = tmp;
ip = s->ivec; ip = s->ivec;
@ -115,28 +210,220 @@ aesCBCdecrypt(uchar *p, int len, AESstate *s)
if(len > 0){ if(len > 0){
ip = s->ivec; ip = s->ivec;
rijndaelEncrypt(s->ekey, s->rounds, ip, q); aes_encrypt(s->ekey, s->rounds, ip, q);
memmove(s->ivec, q, AESbsize); memmove(s->ivec, q, AESbsize);
for(eip = ip+len; ip < eip; ) for(eip = ip+len; ip < eip; )
*p++ ^= *ip++; *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. * this function has been changed for plan 9.
* Expand the cipher key into the encryption and decryption key schedules. * Expand the cipher key into the encryption and decryption key schedules.
* *
* @return the number of rounds for the given cipher key size. * @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; int Nr, i;
/* expand the cipher key: */ /* expand the cipher key: */
Nr = rijndaelKeySetupEnc(erk, cipherKey, keyBits); Nr = aes_setupEnc(erk, cipherKey, keyBits);
/* /*
* invert the order of the round keys and * invert the order of the round keys and apply the inverse MixColumn
* apply the inverse MixColumn transform to all round keys but the first and the last * transform to all round keys but the first and the last
*/ */
drk[0 ] = erk[4*Nr ]; drk[0 ] = erk[4*Nr ];
drk[1 ] = erk[4*Nr + 1]; 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; return Nr;
} }
/* /*
Te0[x] = S [x].[02, 01, 01, 03]; Te0[x] = S [x].[02, 01, 01, 03];
Te1[x] = S [x].[03, 02, 01, 01]; Te1[x] = S [x].[03, 02, 01, 01];
@ -853,25 +1141,23 @@ static const u8 Td4[256] = {
static const u32 rcon[] = { static const u32 rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000, 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. * Expand the cipher key into the encryption key schedule.
* *
* @return the number of rounds for the given cipher key size. * @return the number of rounds for the given cipher key size.
*/ */
static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { static int
aes_setupEnc(u32int rk[/*4*(Nr + 1)*/], const uchar cipherKey[], int keyBits)
{
int i = 0; int i = 0;
u32 temp; u32 temp;
@ -945,62 +1231,18 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int
rk[13] = rk[ 5] ^ rk[12]; rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13]; rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14]; rk[15] = rk[ 7] ^ rk[14];
rk += 8; rk += 8;
} }
} }
return 0; return 0;
} }
/** /* using round keys in rk, perform Nr rounds of encrypting pt into ct */
* Expand the cipher key into the decryption key schedule. void
* aes_encrypt(const u32int rk[/* 4*(Nr + 1) */], int Nr, const uchar pt[16],
* @return the number of rounds for the given cipher key size. uchar ct[16])
*/ {
#ifdef NOTUSED ulong s0, s1, s2, s3, t0, t1, t2, t3;
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;
#ifndef FULL_UNROLL #ifndef FULL_UNROLL
int r; int r;
#endif /* ?FULL_UNROLL */ #endif /* ?FULL_UNROLL */
@ -1116,9 +1358,8 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
rk[7]; rk[7];
rk += 8; rk += 8;
if (--r == 0) { if (--r == 0)
break; break;
}
s0 = s0 =
Te0[(t0 >> 24) ] ^ Te0[(t0 >> 24) ] ^
@ -1180,8 +1421,11 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
PUTU32(ct + 12, s3); PUTU32(ct + 12, s3);
} }
static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { void
u32 s0, s1, s2, s3, t0, t1, t2, t3; 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 #ifndef FULL_UNROLL
int r; int r;
#endif /* ?FULL_UNROLL */ #endif /* ?FULL_UNROLL */
@ -1297,9 +1541,8 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16
rk[7]; rk[7];
rk += 8; rk += 8;
if (--r == 0) { if (--r == 0)
break; break;
}
s0 = s0 =
Td0[(t0 >> 24) ] ^ Td0[(t0 >> 24) ] ^
@ -1363,7 +1606,10 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16
#ifdef INTERMEDIATE_VALUE_KAT #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; int r;
u32 s0, s1, s2, s3, t0, t1, t2, t3; u32 s0, s1, s2, s3, t0, t1, t2, t3;
@ -1405,13 +1651,11 @@ static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
Te2[(s1 >> 8) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^
Te3[(s2 ) & 0xff] ^ Te3[(s2 ) & 0xff] ^
rk[3]; rk[3];
s0 = t0; s0 = t0;
s1 = t1; s1 = t1;
s2 = t2; s2 = t2;
s3 = t3; s3 = t3;
rk += 4; rk += 4;
} }
/* /*
@ -1443,7 +1687,6 @@ static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
(Te4[(s1 >> 8) & 0xff] << 8) ^ (Te4[(s1 >> 8) & 0xff] << 8) ^
(Te4[(s2 ) & 0xff] ) ^ (Te4[(s2 ) & 0xff] ) ^
rk[3]; rk[3];
s0 = t0; s0 = t0;
s1 = t1; s1 = t1;
s2 = t2; s2 = t2;
@ -1456,7 +1699,10 @@ static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
PUTU32(block + 12, s3); 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; int r;
u32 s0, s1, s2, s3, t0, t1, t2, t3; u32 s0, s1, s2, s3, t0, t1, t2, t3;
@ -1504,7 +1750,6 @@ static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[
s2 = t2; s2 = t2;
s3 = t3; s3 = t3;
rk += 4; rk += 4;
} }
/* /*

View file

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

View file

@ -2,27 +2,25 @@
#include <libsec.h> #include <libsec.h>
/* rfc2104 */ /* rfc2104 */
static DigestState* DigestState*
hmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s, hmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen) DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen)
{ {
int i; int i;
uchar pad[65], innerdigest[256]; uchar pad[Hmacblksz+1], innerdigest[256];
if(xlen > sizeof(innerdigest)) if(xlen > sizeof(innerdigest))
return nil; return nil;
if(klen > Hmacblksz)
if(klen>64)
return nil; return nil;
/* first time through */ /* first time through */
if(s == nil){ if(s == nil || s->seeded == 0){
for(i=0; i<64; i++) memset(pad, 0x36, Hmacblksz);
pad[i] = 0x36; pad[Hmacblksz] = 0;
pad[64] = 0; for(i = 0; i < klen; i++)
for(i=0; i<klen; i++)
pad[i] ^= key[i]; pad[i] ^= key[i];
s = (*x)(pad, 64, nil, nil); s = (*x)(pad, Hmacblksz, nil, s);
if(s == nil) if(s == nil)
return nil; return nil;
} }
@ -32,25 +30,12 @@ hmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *
return s; return s;
/* last time through */ /* last time through */
for(i=0; i<64; i++) memset(pad, 0x5c, Hmacblksz);
pad[i] = 0x5c; pad[Hmacblksz] = 0;
pad[64] = 0; for(i = 0; i < klen; i++)
for(i=0; i<klen; i++)
pad[i] ^= key[i]; pad[i] ^= key[i];
(*x)(nil, 0, innerdigest, s); (*x)(nil, 0, innerdigest, s);
s = (*x)(pad, 64, nil, nil); s = (*x)(pad, Hmacblksz, nil, nil);
(*x)(innerdigest, xlen, digest, s); (*x)(innerdigest, xlen, digest, s);
return nil; 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, S31= 3,
S32= 9, S32= 9,
S33= 11, S33= 11,
S34= 15 S34= 15,
}; };
typedef struct MD4Table MD4Table; typedef struct MD4Table MD4Table;

View file

@ -145,3 +145,10 @@ encode(uchar *output, u32int *input, ulong len)
*output++ = x >> 24; *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; char *p;
int m, n; 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); p = malloc(m);
if(p == nil) if(p == nil)
return p; return p;

View file

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

View file

@ -1,56 +1,61 @@
aes.c 2004/1225 aes.c 2021/0202
blowfish.c 2004/1225 blowfish.c 2021/0202
decodepem.c 2004/1225 decodepem.c 2021/0202
des.c 2004/1225 des3CBC.c 2021/0202
des3CBC.c 2004/1225 des3ECB.c 2021/0202
des3ECB.c 2004/1225 des.c 2021/0202
desCBC.c 2004/1225 desCBC.c 2021/0202
desECB.c 2004/1225 desECB.c 2021/0202
desmodes.c 2004/1225 desmodes.c 2021/0202
dsaalloc.c 2004/1225 dsaalloc.c 2021/0202
dsagen.c 2004/1225 dsagen.c 2021/0202
dsaprimes.c 2004/1225 dsaprimes.c 2021/0202
dsaprivtopub.c 2004/1225 dsaprivtopub.c 2021/0202
dsasign.c 2004/1225 dsasign.c 2021/0202
dsaverify.c 2004/1225 dsaverify.c 2021/0202
egalloc.c 2004/1225 egalloc.c 2021/0202
egdecrypt.c 2004/1225 egdecrypt.c 2021/0202
egencrypt.c 2004/1225 egencrypt.c 2021/0202
eggen.c 2004/1225 eggen.c 2021/0202
egprivtopub.c 2004/1225 egprivtopub.c 2021/0202
egsign.c 2004/1225 egsign.c 2021/0202
egtest.c 2004/1225 egtest.c 2021/0202
egverify.c 2004/1225 egverify.c 2021/0202
fastrand.c 2004/1225 fastrand.c 2021/0202
genprime.c 2004/1225 genprime.c 2021/0202
genrandom.c 2004/1225 genrandom.c 2021/0202
gensafeprime.c 2004/1225 gensafeprime.c 2021/0202
genstrongprime.c 2004/1225 genstrongprime.c 2021/0202
hmac.c 2004/1225 hmac.c 2021/0202
hmactest.c 2004/1225 hmactest.c 2021/0202
md4.c 2004/1225 md4.c 2021/0202
md4test.c 2004/1225 md4test.c 2021/0202
md5.c 2004/1225 md5block.c 2021/0202
md5block.c 2004/1225 md5.c 2021/0202
md5pickle.c 2004/1225 md5pickle.c 2021/0202
nfastrand.c 2004/1225 nfastrand.c 2021/0202
primetest.c 2004/1225 primetest.c 2021/0202
prng.c 2004/1225 prng.c 2021/0202
probably_prime.c 2004/1225 probably_prime.c 2021/0202
rc4.c 2004/1225 rc4.c 2021/0202
readcert.c 2004/1225 readcert.c 2021/0202
rsaalloc.c 2004/1225 rsaalloc.c 2021/0202
rsadecrypt.c 2004/1225 rsadecrypt.c 2021/0202
rsaencrypt.c 2004/1225 rsaencrypt.c 2021/0202
rsafill.c 2004/1225 rsafill.c 2021/0202
rsagen.c 2004/1225 rsagen.c 2021/0202
rsaprivtopub.c 2004/1225 rsaprivtopub.c 2021/0202
rsatest.c 2004/1225 rsatest.c 2021/0202
sha1.c 2004/1225 sha1block.c 2021/0202
sha1block.c 2004/1225 sha1.c 2021/0202
sha1pickle.c 2004/1225 sha1pickle.c 2021/0202
smallprimes.c 2004/1225 sha2_128.c 2021/0202
smallprimetest.c 2004/1225 sha2_64.c 2021/0202
thumb.c 2004/1225 sha2block128.c 2021/0202
tlshand.c 2004/1225 sha2block64.c 2021/0202
x509.c 2004/1225 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 <mp.h>
#include <libsec.h> #include <libsec.h>
/* Miller-Rabin probabilistic primality testing */ /*
/* Knuth (1981) Seminumerical Algorithms, p.379 */ * Miller-Rabin probabilistic primality testing
/* Menezes et al () Handbook, p.39 */ * Knuth (1981) Seminumerical Algorithms, p.379
/* 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep */ * Menezes et al () Handbook, p.39
* 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep
*/
int int
probably_prime(mpint *n, int nrep) probably_prime(mpint *n, int nrep)
{ {

View file

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

View file

@ -6,16 +6,15 @@
void void
main(void) main(void)
{ {
RSApriv *rsa;
Biobuf b;
char *p;
int n; int n;
mpint *clr, *enc, *clr2;
uchar buf[4096];
uchar *e;
vlong start; 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); rsa = rsagen(1024, 16, 0);
if(rsa == nil) if(rsa == nil)

View file

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

View file

@ -40,6 +40,7 @@ typedef struct Elist Elist;
#define REAL 9 #define REAL 9
#define ENUMERATED 10 #define ENUMERATED 10
#define EMBEDDED_PDV 11 #define EMBEDDED_PDV 11
#define UTF8String 12
#define SEQUENCE 16 /* also SEQUENCE OF */ #define SEQUENCE 16 /* also SEQUENCE OF */
#define SETOF 17 /* also SETOF OF */ #define SETOF 17 /* also SETOF OF */
#define NumericString 18 #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_string(Elem* pe, char** pstring);
static int is_time(Elem* pe, char** ptime); static int is_time(Elem* pe, char** ptime);
static int decode(uchar* a, int alen, Elem* pelem); 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 encode(Elem e, Bytes** pbytes);
static int oid_lookup(Ints* o, Ints** tab); static int oid_lookup(Ints* o, Ints** tab);
static void freevalfields(Value* v); static void freevalfields(Value* v);
@ -174,6 +171,7 @@ emalloc(int n)
exits("out of memory"); exits("out of memory");
} }
memset(p, 0, n); memset(p, 0, n);
setmalloctag(p, getcallerpc(&n));
return p; return p;
} }
@ -205,37 +203,6 @@ decode(uchar* a, int alen, Elem* pelem)
return ber_decode(&p, &a[alen], 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: * All of the following decoding routines take arguments:
* uchar **pp; * uchar **pp;
@ -263,9 +230,11 @@ ber_decode(uchar** pp, uchar* pend, Elem* pelem)
if(err == ASN_OK) { if(err == ASN_OK) {
err = length_decode(pp, pend, &length); err = length_decode(pp, pend, &length);
if(err == ASN_OK) { if(err == ASN_OK) {
if(tag.class == Universal) if(tag.class == Universal) {
err = value_decode(pp, pend, length, tag.num, isconstr, &val); 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); err = value_decode(pp, pend, length, OCTET_STRING, 0, &val);
if(err == ASN_OK) { if(err == ASN_OK) {
pelem->tag = tag; pelem->tag = tag;
@ -502,6 +471,7 @@ value_decode(uchar** pp, uchar* pend, int length, int kind, int isconstr, Value*
case SEQUENCE: case SEQUENCE:
err = seq_decode(&p, pend, length, isconstr, &vl); err = seq_decode(&p, pend, length, isconstr, &vl);
setmalloctag(vl, getcallerpc(&pp));
if(err == ASN_OK) { if(err == ASN_OK) {
pval->tag = VSeq ; pval->tag = VSeq ;
pval->u.seqval = vl; pval->u.seqval = vl;
@ -510,12 +480,13 @@ value_decode(uchar** pp, uchar* pend, int length, int kind, int isconstr, Value*
case SETOF: case SETOF:
err = seq_decode(&p, pend, length, isconstr, &vl); err = seq_decode(&p, pend, length, isconstr, &vl);
setmalloctag(vl, getcallerpc(&pp));
if(err == ASN_OK) { if(err == ASN_OK) {
pval->tag = VSet; pval->tag = VSet;
pval->u.setval = vl; pval->u.setval = vl;
} }
break; break;
case UTF8String:
case NumericString: case NumericString:
case PrintableString: case PrintableString:
case TeletexString: case TeletexString:
@ -746,6 +717,7 @@ seq_decode(uchar** pp, uchar* pend, int length, int isconstr, Elist** pelist)
} }
*pp = p; *pp = p;
*pelist = ans; *pelist = ans;
setmalloctag(ans, getcallerpc(&pp));
return err; return err;
} }
@ -1016,6 +988,7 @@ val_enc(uchar** pp, Elem e, int *pconstr, int lenonly)
} }
break; break;
case UTF8String:
case NumericString: case NumericString:
case PrintableString: case PrintableString:
case TeletexString: case TeletexString:
@ -1246,6 +1219,7 @@ is_string(Elem* pe, char** pstring)
{ {
if(pe->tag.class == Universal) { if(pe->tag.class == Universal) {
switch(pe->tag.num) { switch(pe->tag.num) {
case UTF8String:
case NumericString: case NumericString:
case PrintableString: case PrintableString:
case TeletexString: case TeletexString:
@ -1406,6 +1380,7 @@ mkel(Elem e, Elist* tail)
Elist* el; Elist* el;
el = (Elist*)emalloc(sizeof(Elist)); el = (Elist*)emalloc(sizeof(Elist));
setmalloctag(el, getcallerpc(&e));
el->hd = e; el->hd = e;
el->tl = tail; el->tl = tail;
return el; return el;
@ -1575,6 +1550,7 @@ enum {
ALG_md4WithRSAEncryption, ALG_md4WithRSAEncryption,
ALG_md5WithRSAEncryption, ALG_md5WithRSAEncryption,
ALG_sha1WithRSAEncryption, ALG_sha1WithRSAEncryption,
ALG_sha1WithRSAEncryptionOiw,
ALG_md5, ALG_md5,
NUMALGS 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_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
static Ints7 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 }; 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_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 Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 };
static Ints *alg_oid_tab[NUMALGS+1] = { static Ints *alg_oid_tab[NUMALGS+1] = {
(Ints*)(void*)&oid_rsaEncryption, (Ints*)(void*)&oid_rsaEncryption,
@ -1594,10 +1571,11 @@ static Ints *alg_oid_tab[NUMALGS+1] = {
(Ints*)(void*)&oid_md4WithRSAEncryption, (Ints*)(void*)&oid_md4WithRSAEncryption,
(Ints*)(void*)&oid_md5WithRSAEncryption, (Ints*)(void*)&oid_md5WithRSAEncryption,
(Ints*)(void*)&oid_sha1WithRSAEncryption, (Ints*)(void*)&oid_sha1WithRSAEncryption,
(Ints*)(void*)&oid_sha1WithRSAEncryptionOiw,
(Ints*)(void*)&oid_md5, (Ints*)(void*)&oid_md5,
nil 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 static void
freecert(CertX509* c) freecert(CertX509* c)
@ -1613,6 +1591,7 @@ freecert(CertX509* c)
free(c->subject); free(c->subject);
freebytes(c->publickey); freebytes(c->publickey);
freebytes(c->signature); freebytes(c->signature);
free(c);
} }
/* /*
@ -1835,16 +1814,19 @@ static RSApub*
decode_rsapubkey(Bytes* a) decode_rsapubkey(Bytes* a)
{ {
Elem e; Elem e;
Elist *el; Elist *el, *l;
mpint *mp; mpint *mp;
RSApub* key; RSApub* key;
l = nil;
key = rsapuballoc(); key = rsapuballoc();
if(decode(a->data, a->len, &e) != ASN_OK) if(decode(a->data, a->len, &e) != ASN_OK)
goto errret; goto errret;
if(!is_seq(&e, &el) || elistlen(el) != 2) if(!is_seq(&e, &el) || elistlen(el) != 2)
goto errret; goto errret;
l = el;
key->n = mp = asn1mpint(&el->hd); key->n = mp = asn1mpint(&el->hd);
if(mp == nil) if(mp == nil)
goto errret; goto errret;
@ -1853,8 +1835,13 @@ decode_rsapubkey(Bytes* a)
key->ek = mp = asn1mpint(&el->hd); key->ek = mp = asn1mpint(&el->hd);
if(mp == nil) if(mp == nil)
goto errret; goto errret;
if(l != nil)
freeelist(l);
return key; return key;
errret: errret:
if(l != nil)
freeelist(l);
rsapubfree(key); rsapubfree(key);
return nil; return nil;
} }
@ -2080,7 +2067,10 @@ digest_certinfo(Bytes *cert, DigestFun digestfun, uchar *digest)
length > pend - p) length > pend - p)
return; return;
info = p; 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; return;
infolen = p - info; infolen = p - info;
(*digestfun)(info, infolen, digest, nil); (*digestfun)(info, infolen, digest, nil);
@ -2096,6 +2086,10 @@ verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg)
int buflen; int buflen;
mpint *pkcs1; mpint *pkcs1;
int nlen; int nlen;
char *err;
err = nil;
pkcs1buf = nil;
/* one less than the byte length of the modulus */ /* one less than the byte length of the modulus */
nlen = (mpsignif(pk->n)-1)/8; 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 */ /* see 9.2.1 of rfc2437 */
pkcs1 = betomp(signature->data, signature->len, nil); pkcs1 = betomp(signature->data, signature->len, nil);
mpexp(pkcs1, pk->ek, pk->n, pkcs1); mpexp(pkcs1, pk->ek, pk->n, pkcs1);
pkcs1buf = nil;
buflen = mptobe(pkcs1, nil, 0, &pkcs1buf); buflen = mptobe(pkcs1, nil, 0, &pkcs1buf);
buf = pkcs1buf; buf = pkcs1buf;
if(buflen != nlen || buf[0] != 1) if(buflen != nlen || buf[0] != 1) {
return "expected 1"; err = "expected 1";
goto end;
}
buf++; buf++;
while(buf[0] == 0xff) while(buf[0] == 0xff)
buf++; buf++;
if(buf[0] != 0) if(buf[0] != 0) {
return "expected 0"; err = "expected 0";
goto end;
}
buf++; buf++;
buflen -= buf-pkcs1buf; buflen -= buf-pkcs1buf;
if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 || if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 ||
!is_octetstring(&el->tl->hd, &digest)) !is_octetstring(&el->tl->hd, &digest)) {
return "signature parse error"; err = "signature parse error";
goto end;
}
*psigalg = &el->hd; *psigalg = &el->hd;
if(memcmp(digest->data, edigest, digest->len) == 0) if(memcmp(digest->data, edigest, digest->len) == 0)
return nil; goto end;
return "digests did not match"; err = "digests did not match";
end:
if(pkcs1 != nil)
mpfree(pkcs1);
if(pkcs1buf != nil)
free(pkcs1buf);
return err;
} }
RSApub* RSApub*
@ -2148,6 +2154,97 @@ X509toRSApub(uchar *cert, int ncert, char *name, int nname)
return pk; 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* char*
X509verify(uchar *cert, int ncert, RSApub *pk) X509verify(uchar *cert, int ncert, RSApub *pk)
{ {
@ -2345,6 +2442,34 @@ mkDN(char *dn)
return mkseq(el); 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* uchar*
X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen) X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
@ -2479,31 +2604,32 @@ tagdump(Tag tag)
if(tag.class != Universal) if(tag.class != Universal)
return smprint("class%d,num%d", tag.class, tag.num); return smprint("class%d,num%d", tag.class, tag.num);
switch(tag.num){ switch(tag.num){
case BOOLEAN: return "BOOLEAN"; break; case BOOLEAN: return "BOOLEAN";
case INTEGER: return "INTEGER"; break; case INTEGER: return "INTEGER";
case BIT_STRING: return "BIT STRING"; break; case BIT_STRING: return "BIT STRING";
case OCTET_STRING: return "OCTET STRING"; break; case OCTET_STRING: return "OCTET STRING";
case NULLTAG: return "NULLTAG"; break; case NULLTAG: return "NULLTAG";
case OBJECT_ID: return "OID"; break; case OBJECT_ID: return "OID";
case ObjectDescriptor: return "OBJECT_DES"; break; case ObjectDescriptor: return "OBJECT_DES";
case EXTERNAL: return "EXTERNAL"; break; case EXTERNAL: return "EXTERNAL";
case REAL: return "REAL"; break; case REAL: return "REAL";
case ENUMERATED: return "ENUMERATED"; break; case ENUMERATED: return "ENUMERATED";
case EMBEDDED_PDV: return "EMBEDDED PDV"; break; case EMBEDDED_PDV: return "EMBEDDED PDV";
case SEQUENCE: return "SEQUENCE"; break; case SEQUENCE: return "SEQUENCE";
case SETOF: return "SETOF"; break; case SETOF: return "SETOF";
case NumericString: return "NumericString"; break; case UTF8String: return "UTF8String";
case PrintableString: return "PrintableString"; break; case NumericString: return "NumericString";
case TeletexString: return "TeletexString"; break; case PrintableString: return "PrintableString";
case VideotexString: return "VideotexString"; break; case TeletexString: return "TeletexString";
case IA5String: return "IA5String"; break; case VideotexString: return "VideotexString";
case UTCTime: return "UTCTime"; break; case IA5String: return "IA5String";
case GeneralizedTime: return "GeneralizedTime"; break; case UTCTime: return "UTCTime";
case GraphicString: return "GraphicString"; break; case GeneralizedTime: return "GeneralizedTime";
case VisibleString: return "VisibleString"; break; case GraphicString: return "GraphicString";
case GeneralString: return "GeneralString"; break; case VisibleString: return "VisibleString";
case UniversalString: return "UniversalString"; break; case GeneralString: return "GeneralString";
case BMPString: return "BMPString"; break; case UniversalString: return "UniversalString";
case BMPString: return "BMPString";
default: default:
return smprint("Universal,num%d", tag.num); 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 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 VReal: print("Real..."); break;
case VOther: print("Other..."); 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 VNull: print("Null"); break;
case VEOC: print("EOC..."); break; case VEOC: print("EOC..."); break;
case VObjId: print("ObjId"); case VObjId: print("ObjId");