mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
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:
parent
90971376a5
commit
e7580103a0
24 changed files with 1776 additions and 572 deletions
163
include/libsec.h
163
include/libsec.h
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ enum
|
|||
S31= 3,
|
||||
S32= 9,
|
||||
S33= 11,
|
||||
S34= 15
|
||||
S34= 15,
|
||||
};
|
||||
|
||||
typedef struct MD4Table MD4Table;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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\
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
191
src/libsec/port/sha2_128.c
Normal 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
187
src/libsec/port/sha2_64.c
Normal 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);
|
||||
}
|
101
src/libsec/port/sha2block128.c
Normal file
101
src/libsec/port/sha2block128.c
Normal 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;
|
||||
}
|
||||
}
|
92
src/libsec/port/sha2block64.c
Normal file
92
src/libsec/port/sha2block64.c
Normal 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;
|
||||
}
|
||||
}
|
63
src/libsec/port/sha2test.c
Normal file
63
src/libsec/port/sha2test.c
Normal 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");
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue