#include <u.h>#include <libc.h>#include <auth.h>#include <mp.h>#include <libsec.h> // The main groups of functions are:// client/server - main handshake protocol definition// message functions - formating handshake messages// cipher choices - catalog of digest and encrypt algorithms// security functions - PKCS#1, sslHMAC, session keygen// general utility functions - malloc, serialization// The handshake protocol builds on the TLS/SSL3 record layer protocol,// which is implemented in kernel device #a. See also /lib/rfc/rfc2246. enum { TLSFinishedLen = 12, SSL3FinishedLen = MD5dlen+SHA1dlen, MaxKeyData = 160, // amount of secret we may need MAXdlen = SHA2_512dlen, RandomSize = 32, MasterSecretSize = 48, AQueue = 0, AFlush = 1,}; typedef struct Bytes{ int len; uchar data[];} Bytes; typedef struct Ints{ int len; int data[];} Ints; typedef struct Algs{ char *enc; char *digest; int nsecret; int tlsid; int ok;} Algs; typedef struct Namedcurve{ int tlsid; void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);} Namedcurve; typedef struct Finished{ uchar verify[SSL3FinishedLen]; int n;} Finished; typedef struct HandshakeHash { MD5state md5; SHAstate sha1; SHA2_256state sha2_256;} HandshakeHash; typedef struct TlsSec TlsSec;struct TlsSec { RSApub *rsapub; AuthRpc *rpc; // factotum for rsa private key uchar *psk; // pre-shared key int psklen; int clientVers; // version in ClientHello uchar sec[MasterSecretSize]; // master secret uchar srandom[RandomSize]; // server random uchar crandom[RandomSize]; // client random Namedcurve *nc; // selected curve for ECDHE // diffie hellman state DHstate dh; struct { ECdomain dom; ECpriv Q; } ec; uchar X[32]; // byte generation and handshake checksum void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int); void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int); int nfin;}; typedef struct TlsConnection{ TlsSec sec[1]; // security management goo int hand, ctl; // record layer file descriptors int erred; // set when tlsError called int (*trace)(char*fmt, ...); // for debugging int version; // protocol we are speaking Bytes *cert; // server certificate; only last - no chain int cipher; int nsecret; // amount of secret data to init keys char *digest; // name of digest algorithm to use char *enc; // name of encryption algorithm to use // for finished messages HandshakeHash handhash; Finished finished; uchar *sendp; uchar buf[1<<16];} TlsConnection; typedef struct Msg{ int tag; union { struct { int version; uchar random[RandomSize]; Bytes* sid; Ints* ciphers; Bytes* compressors; Bytes* extensions; } clientHello; struct { int version; uchar random[RandomSize]; Bytes* sid; int cipher; int compressor; Bytes* extensions; } serverHello; struct { int ncert; Bytes **certs; } certificate; struct { Bytes *types; Ints *sigalgs; int nca; Bytes **cas; } certificateRequest; struct { Bytes *pskid; Bytes *key; } clientKeyExchange; struct { Bytes *pskid; Bytes *dh_p; Bytes *dh_g; Bytes *dh_Ys; Bytes *dh_parameters; Bytes *dh_signature; int sigalg; int curve; } serverKeyExchange; struct { int sigalg; Bytes *signature; } certificateVerify; Finished finished; } u;} Msg; enum { SSL3Version = 0x0300, TLS10Version = 0x0301, TLS11Version = 0x0302, TLS12Version = 0x0303, ProtocolVersion = TLS12Version, // maximum version we speak MinProtoVersion = 0x0300, // limits on version we accept MaxProtoVersion = 0x03ff,}; // handshake typeenum { HHelloRequest, HClientHello, HServerHello, HSSL2ClientHello = 9, /* local convention; see devtls.c */ HCertificate = 11, HServerKeyExchange, HCertificateRequest, HServerHelloDone, HCertificateVerify, HClientKeyExchange, HFinished = 20, HMax}; // alertsenum { ECloseNotify = 0, EUnexpectedMessage = 10, EBadRecordMac = 20, EDecryptionFailed = 21, ERecordOverflow = 22, EDecompressionFailure = 30, EHandshakeFailure = 40, ENoCertificate = 41, EBadCertificate = 42, EUnsupportedCertificate = 43, ECertificateRevoked = 44, ECertificateExpired = 45, ECertificateUnknown = 46, EIllegalParameter = 47, EUnknownCa = 48, EAccessDenied = 49, EDecodeError = 50, EDecryptError = 51, EExportRestriction = 60, EProtocolVersion = 70, EInsufficientSecurity = 71, EInternalError = 80, EInappropriateFallback = 86, EUserCanceled = 90, ENoRenegotiation = 100, EUnknownPSKidentity = 115, EMax = 256}; // cipher suitesenum { TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0X000A, TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0X0016, TLS_RSA_WITH_AES_128_CBC_SHA = 0X002F, TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0X0033, TLS_RSA_WITH_AES_256_CBC_SHA = 0X0035, TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0X0039, TLS_RSA_WITH_AES_128_CBC_SHA256 = 0X003C, TLS_RSA_WITH_AES_256_CBC_SHA256 = 0X003D, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0X0067, TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F, GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC13, GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCC14, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC15, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCA8, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCCA9, TLS_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCAA, TLS_PSK_WITH_CHACHA20_POLY1305 = 0xCCAB, TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE, TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C, TLS_FALLBACK_SCSV = 0x5600,}; // compression methodsenum { CompressionNull = 0, CompressionMax}; // curvesenum { X25519 = 0x001d,}; // extensionsenum { Extsni = 0x0000, Extec = 0x000a, Extecp = 0x000b, Extsigalgs = 0x000d,}; static Algs cipherAlgs[] = { // ECDHE-ECDSA {"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305}, {"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305}, {"aes_128_gcm_aead", "clear", 2*(16+4), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, // ECDHE-RSA {"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, {"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305}, {"aes_128_gcm_aead", "clear", 2*(16+4), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, {"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, // DHE-RSA {"ccpoly96_aead", "clear", 2*(32+12), TLS_DHE_RSA_WITH_CHACHA20_POLY1305}, {"ccpoly64_aead", "clear", 2*32, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305}, {"aes_128_gcm_aead", "clear", 2*(16+4), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256}, {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, {"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, {"3des_ede_cbc","sha1", 2*(4*8+SHA1dlen), TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA}, // RSA {"aes_128_gcm_aead", "clear", 2*(16+4), TLS_RSA_WITH_AES_128_GCM_SHA256}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_RSA_WITH_AES_128_CBC_SHA256}, {"aes_256_cbc", "sha256", 2*(32+16+SHA2_256dlen), TLS_RSA_WITH_AES_256_CBC_SHA256}, {"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}, {"3des_ede_cbc","sha1", 2*(4*8+SHA1dlen), TLS_RSA_WITH_3DES_EDE_CBC_SHA}, // PSK {"ccpoly96_aead", "clear", 2*(32+12), TLS_PSK_WITH_CHACHA20_POLY1305}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_PSK_WITH_AES_128_CBC_SHA256}, {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_PSK_WITH_AES_128_CBC_SHA},}; static uchar compressors[] = { CompressionNull,}; static Namedcurve namedcurves[] = { X25519, nil, 0x0017, secp256r1, 0x0018, secp384r1,}; static uchar pointformats[] = { CompressionNull /* support of uncompressed point format is mandatory */}; static struct { DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*); int len;} hashfun[] = {/* [0x00] is reserved for MD5+SHA1 for < TLS1.2 */ [0x01] {md5, MD5dlen}, [0x02] {sha1, SHA1dlen}, [0x03] {sha2_224, SHA2_224dlen}, [0x04] {sha2_256, SHA2_256dlen}, [0x05] {sha2_384, SHA2_384dlen}, [0x06] {sha2_512, SHA2_512dlen},}; // signature algorithms (only RSA and ECDSA at the moment)static int sigalgs[] = { 0x0603, /* SHA512 ECDSA */ 0x0503, /* SHA384 ECDSA */ 0x0403, /* SHA256 ECDSA */ 0x0203, /* SHA1 ECDSA */ 0x0601, /* SHA512 RSA */ 0x0501, /* SHA384 RSA */ 0x0401, /* SHA256 RSA */ 0x0201, /* SHA1 RSA */}; static TlsConnection *tlsServer2(int ctl, int hand, uchar *cert, int certlen, char *pskid, uchar *psk, int psklen, int (*trace)(char*fmt, ...), PEMChain *chain);static TlsConnection *tlsClient2(int ctl, int hand, uchar *cert, int certlen, char *pskid, uchar *psk, int psklen, uchar *ext, int extlen, int (*trace)(char*fmt, ...));static void msgClear(Msg *m);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, ...);static int setVersion(TlsConnection *c, int version);static int setSecrets(TlsConnection *c, int isclient);static int finishedMatch(TlsConnection *c, Finished *f);static void tlsConnectionFree(TlsConnection *c); static int isDHE(int tlsid);static int isECDHE(int tlsid);static int isPSK(int tlsid);static int isECDSA(int tlsid); static int setAlgs(TlsConnection *c, int a);static int okCipher(Ints *cv, int ispsk, int canec);static int okCompression(Bytes *cv);static int initCiphers(void);static Ints* makeciphers(int ispsk); static AuthRpc* factotum_rsa_open(RSApub *rsapub);static mpint* factotum_rsa_decrypt(AuthRpc *rpc, mpint *cipher);static void factotum_rsa_close(AuthRpc *rpc); static void tlsSecInits(TlsSec *sec, int cvers, uchar *crandom);static int tlsSecRSAs(TlsSec *sec, Bytes *epm);static Bytes* tlsSecECDHEs1(TlsSec *sec);static int tlsSecECDHEs2(TlsSec *sec, Bytes *Yc);static void tlsSecInitc(TlsSec *sec, int cvers);static Bytes* tlsSecRSAc(TlsSec *sec, uchar *cert, int ncert);static Bytes* tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys);static Bytes* tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys);static void tlsSecVers(TlsSec *sec, int v);static int tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient);static void setMasterSecret(TlsSec *sec, Bytes *pm);static int digestDHparams(TlsSec *sec, Bytes *par, uchar digest[MAXdlen], int sigalg);static char* verifyDHparams(TlsSec *sec, Bytes *par, Bytes *cert, Bytes *sig, int sigalg); static Bytes* pkcs1_encrypt(Bytes* data, RSApub* key);static Bytes* pkcs1_decrypt(TlsSec *sec, Bytes *data);static Bytes* pkcs1_sign(TlsSec *sec, uchar *digest, int digestlen, int sigalg); static void* emalloc(int);static void* erealloc(void*, int);static void put32(uchar *p, u32int);static void put24(uchar *p, int);static void put16(uchar *p, int);static int get24(uchar *p);static int get16(uchar *p);static Bytes* newbytes(int len);static Bytes* makebytes(uchar* buf, int len);static Bytes* mptobytes(mpint* big, int len);static mpint* bytestomp(Bytes* bytes);static void freebytes(Bytes* b);static Ints* newints(int len);static void freeints(Ints* b);static int lookupid(Ints* b, int id); /* x509.c */extern mpint* pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype);extern int pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype);extern int asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len); //================= client/server ======================== // push TLS onto fd, returning new (application) file descriptor// or -1 if error.inttlsServer(int fd, TLSconn *conn){ char buf[8]; char dname[64]; uchar seed[2*RandomSize]; int n, data, ctl, hand; TlsConnection *tls; if(conn == nil) return -1; ctl = open("#a/tls/clone", ORDWR|OCEXEC); if(ctl < 0) return -1; n = read(ctl, buf, sizeof(buf)-1); if(n < 0){ close(ctl); return -1; } buf[n] = 0; snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf); snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); hand = open(dname, ORDWR|OCEXEC); if(hand < 0){ close(ctl); return -1; } data = -1; fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion); tls = tlsServer2(ctl, hand, conn->cert, conn->certlen, conn->pskID, conn->psk, conn->psklen, conn->trace, conn->chain); if(tls != nil){ snprint(dname, sizeof(dname), "#a/tls/%s/data", buf); data = open(dname, ORDWR); } close(hand); close(ctl); if(data < 0){ tlsConnectionFree(tls); return -1; } free(conn->cert); conn->cert = nil; // client certificates are not yet implemented conn->certlen = 0; conn->sessionIDlen = 0; conn->sessionID = nil; if(conn->sessionKey != nil && conn->sessionType != nil && strcmp(conn->sessionType, "ttls") == 0){ memmove(seed, tls->sec->crandom, RandomSize); memmove(seed+RandomSize, tls->sec->srandom, RandomSize); tls->sec->prf( conn->sessionKey, conn->sessionKeylen, tls->sec->sec, MasterSecretSize, conn->sessionConst, seed, sizeof(seed)); } tlsConnectionFree(tls); close(fd); return data;} static uchar*tlsClientExtensions(TLSconn *conn, int *plen){ uchar *b, *p; int i, n, m; p = b = nil;Lines 1–500 of 3024. Load more
#include <u.h> #include <libc.h> #include <auth.h> #include <mp.h> #include <libsec.h> // The main groups of functions are: // client/server - main handshake protocol definition // message functions - formating handshake messages // cipher choices - catalog of digest and encrypt algorithms // security functions - PKCS#1, sslHMAC, session keygen // general utility functions - malloc, serialization // The handshake protocol builds on the TLS/SSL3 record layer protocol, // which is implemented in kernel device #a. See also /lib/rfc/rfc2246. enum { TLSFinishedLen = 12, SSL3FinishedLen = MD5dlen+SHA1dlen, MaxKeyData = 160, // amount of secret we may need MAXdlen = SHA2_512dlen, RandomSize = 32, MasterSecretSize = 48, AQueue = 0, AFlush = 1, }; typedef struct Bytes{ int len; uchar data[]; } Bytes; typedef struct Ints{ int len; int data[]; } Ints; typedef struct Algs{ char *enc; char *digest; int nsecret; int tlsid; int ok; } Algs; typedef struct Namedcurve{ int tlsid; void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h); } Namedcurve; typedef struct Finished{ uchar verify[SSL3FinishedLen]; int n; } Finished; typedef struct HandshakeHash { MD5state md5; SHAstate sha1; SHA2_256state sha2_256; } HandshakeHash; typedef struct TlsSec TlsSec; struct TlsSec { RSApub *rsapub; AuthRpc *rpc; // factotum for rsa private key uchar *psk; // pre-shared key int psklen; int clientVers; // version in ClientHello uchar sec[MasterSecretSize]; // master secret uchar srandom[RandomSize]; // server random uchar crandom[RandomSize]; // client random Namedcurve *nc; // selected curve for ECDHE // diffie hellman state DHstate dh; struct { ECdomain dom; ECpriv Q; } ec; uchar X[32]; // byte generation and handshake checksum void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int); void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int); int nfin; }; typedef struct TlsConnection{ TlsSec sec[1]; // security management goo int hand, ctl; // record layer file descriptors int erred; // set when tlsError called int (*trace)(char*fmt, ...); // for debugging int version; // protocol we are speaking Bytes *cert; // server certificate; only last - no chain int cipher; int nsecret; // amount of secret data to init keys char *digest; // name of digest algorithm to use char *enc; // name of encryption algorithm to use // for finished messages HandshakeHash handhash; Finished finished; uchar *sendp; uchar buf[1<<16]; } TlsConnection; typedef struct Msg{ int tag; union { struct { int version; uchar random[RandomSize]; Bytes* sid; Ints* ciphers; Bytes* compressors; Bytes* extensions; } clientHello; struct { int version; uchar random[RandomSize]; Bytes* sid; int cipher; int compressor; Bytes* extensions; } serverHello; struct { int ncert; Bytes **certs; } certificate; struct { Bytes *types; Ints *sigalgs; int nca; Bytes **cas; } certificateRequest; struct { Bytes *pskid; Bytes *key; } clientKeyExchange; struct { Bytes *pskid; Bytes *dh_p; Bytes *dh_g; Bytes *dh_Ys; Bytes *dh_parameters; Bytes *dh_signature; int sigalg; int curve; } serverKeyExchange; struct { int sigalg; Bytes *signature; } certificateVerify; Finished finished; } u; } Msg; enum { SSL3Version = 0x0300, TLS10Version = 0x0301, TLS11Version = 0x0302, TLS12Version = 0x0303, ProtocolVersion = TLS12Version, // maximum version we speak MinProtoVersion = 0x0300, // limits on version we accept MaxProtoVersion = 0x03ff, }; // handshake type enum { HHelloRequest, HClientHello, HServerHello, HSSL2ClientHello = 9, /* local convention; see devtls.c */ HCertificate = 11, HServerKeyExchange, HCertificateRequest, HServerHelloDone, HCertificateVerify, HClientKeyExchange, HFinished = 20, HMax }; // alerts enum { ECloseNotify = 0, EUnexpectedMessage = 10, EBadRecordMac = 20, EDecryptionFailed = 21, ERecordOverflow = 22, EDecompressionFailure = 30, EHandshakeFailure = 40, ENoCertificate = 41, EBadCertificate = 42, EUnsupportedCertificate = 43, ECertificateRevoked = 44, ECertificateExpired = 45, ECertificateUnknown = 46, EIllegalParameter = 47, EUnknownCa = 48, EAccessDenied = 49, EDecodeError = 50, EDecryptError = 51, EExportRestriction = 60, EProtocolVersion = 70, EInsufficientSecurity = 71, EInternalError = 80, EInappropriateFallback = 86, EUserCanceled = 90, ENoRenegotiation = 100, EUnknownPSKidentity = 115, EMax = 256 }; // cipher suites enum { TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0X000A, TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0X0016, TLS_RSA_WITH_AES_128_CBC_SHA = 0X002F, TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0X0033, TLS_RSA_WITH_AES_256_CBC_SHA = 0X0035, TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0X0039, TLS_RSA_WITH_AES_128_CBC_SHA256 = 0X003C, TLS_RSA_WITH_AES_256_CBC_SHA256 = 0X003D, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0X0067, TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F, GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC13, GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCC14, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC15, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCA8, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCCA9, TLS_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCAA, TLS_PSK_WITH_CHACHA20_POLY1305 = 0xCCAB, TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE, TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C, TLS_FALLBACK_SCSV = 0x5600, }; // compression methods enum { CompressionNull = 0, CompressionMax }; // curves enum { X25519 = 0x001d, }; // extensions enum { Extsni = 0x0000, Extec = 0x000a, Extecp = 0x000b, Extsigalgs = 0x000d, }; static Algs cipherAlgs[] = { // ECDHE-ECDSA {"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305}, {"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305}, {"aes_128_gcm_aead", "clear", 2*(16+4), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, // ECDHE-RSA {"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, {"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305}, {"aes_128_gcm_aead", "clear", 2*(16+4), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, {"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, // DHE-RSA {"ccpoly96_aead", "clear", 2*(32+12), TLS_DHE_RSA_WITH_CHACHA20_POLY1305}, {"ccpoly64_aead", "clear", 2*32, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305}, {"aes_128_gcm_aead", "clear", 2*(16+4), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256}, {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, {"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, {"3des_ede_cbc","sha1", 2*(4*8+SHA1dlen), TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA}, // RSA {"aes_128_gcm_aead", "clear", 2*(16+4), TLS_RSA_WITH_AES_128_GCM_SHA256}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_RSA_WITH_AES_128_CBC_SHA256}, {"aes_256_cbc", "sha256", 2*(32+16+SHA2_256dlen), TLS_RSA_WITH_AES_256_CBC_SHA256}, {"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}, {"3des_ede_cbc","sha1", 2*(4*8+SHA1dlen), TLS_RSA_WITH_3DES_EDE_CBC_SHA}, // PSK {"ccpoly96_aead", "clear", 2*(32+12), TLS_PSK_WITH_CHACHA20_POLY1305}, {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_PSK_WITH_AES_128_CBC_SHA256}, {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_PSK_WITH_AES_128_CBC_SHA}, }; static uchar compressors[] = { CompressionNull, }; static Namedcurve namedcurves[] = { X25519, nil, 0x0017, secp256r1, 0x0018, secp384r1, }; static uchar pointformats[] = { CompressionNull /* support of uncompressed point format is mandatory */ }; static struct { DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*); int len; } hashfun[] = { /* [0x00] is reserved for MD5+SHA1 for < TLS1.2 */ [0x01] {md5, MD5dlen}, [0x02] {sha1, SHA1dlen}, [0x03] {sha2_224, SHA2_224dlen}, [0x04] {sha2_256, SHA2_256dlen}, [0x05] {sha2_384, SHA2_384dlen}, [0x06] {sha2_512, SHA2_512dlen}, }; // signature algorithms (only RSA and ECDSA at the moment) static int sigalgs[] = { 0x0603, /* SHA512 ECDSA */ 0x0503, /* SHA384 ECDSA */ 0x0403, /* SHA256 ECDSA */ 0x0203, /* SHA1 ECDSA */ 0x0601, /* SHA512 RSA */ 0x0501, /* SHA384 RSA */ 0x0401, /* SHA256 RSA */ 0x0201, /* SHA1 RSA */ }; static TlsConnection *tlsServer2(int ctl, int hand, uchar *cert, int certlen, char *pskid, uchar *psk, int psklen, int (*trace)(char*fmt, ...), PEMChain *chain); static TlsConnection *tlsClient2(int ctl, int hand, uchar *cert, int certlen, char *pskid, uchar *psk, int psklen, uchar *ext, int extlen, int (*trace)(char*fmt, ...)); static void msgClear(Msg *m); 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, ...); static int setVersion(TlsConnection *c, int version); static int setSecrets(TlsConnection *c, int isclient); static int finishedMatch(TlsConnection *c, Finished *f); static void tlsConnectionFree(TlsConnection *c); static int isDHE(int tlsid); static int isECDHE(int tlsid); static int isPSK(int tlsid); static int isECDSA(int tlsid); static int setAlgs(TlsConnection *c, int a); static int okCipher(Ints *cv, int ispsk, int canec); static int okCompression(Bytes *cv); static int initCiphers(void); static Ints* makeciphers(int ispsk); static AuthRpc* factotum_rsa_open(RSApub *rsapub); static mpint* factotum_rsa_decrypt(AuthRpc *rpc, mpint *cipher); static void factotum_rsa_close(AuthRpc *rpc); static void tlsSecInits(TlsSec *sec, int cvers, uchar *crandom); static int tlsSecRSAs(TlsSec *sec, Bytes *epm); static Bytes* tlsSecECDHEs1(TlsSec *sec); static int tlsSecECDHEs2(TlsSec *sec, Bytes *Yc); static void tlsSecInitc(TlsSec *sec, int cvers); static Bytes* tlsSecRSAc(TlsSec *sec, uchar *cert, int ncert); static Bytes* tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys); static Bytes* tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys); static void tlsSecVers(TlsSec *sec, int v); static int tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient); static void setMasterSecret(TlsSec *sec, Bytes *pm); static int digestDHparams(TlsSec *sec, Bytes *par, uchar digest[MAXdlen], int sigalg); static char* verifyDHparams(TlsSec *sec, Bytes *par, Bytes *cert, Bytes *sig, int sigalg); static Bytes* pkcs1_encrypt(Bytes* data, RSApub* key); static Bytes* pkcs1_decrypt(TlsSec *sec, Bytes *data); static Bytes* pkcs1_sign(TlsSec *sec, uchar *digest, int digestlen, int sigalg); static void* emalloc(int); static void* erealloc(void*, int); static void put32(uchar *p, u32int); static void put24(uchar *p, int); static void put16(uchar *p, int); static int get24(uchar *p); static int get16(uchar *p); static Bytes* newbytes(int len); static Bytes* makebytes(uchar* buf, int len); static Bytes* mptobytes(mpint* big, int len); static mpint* bytestomp(Bytes* bytes); static void freebytes(Bytes* b); static Ints* newints(int len); static void freeints(Ints* b); static int lookupid(Ints* b, int id); /* x509.c */ extern mpint* pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype); extern int pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype); extern int asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len); //================= client/server ======================== // push TLS onto fd, returning new (application) file descriptor // or -1 if error. int tlsServer(int fd, TLSconn *conn) { char buf[8]; char dname[64]; uchar seed[2*RandomSize]; int n, data, ctl, hand; TlsConnection *tls; if(conn == nil) return -1; ctl = open("#a/tls/clone", ORDWR|OCEXEC); if(ctl < 0) return -1; n = read(ctl, buf, sizeof(buf)-1); if(n < 0){ close(ctl); return -1; } buf[n] = 0; snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf); snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); hand = open(dname, ORDWR|OCEXEC); if(hand < 0){ close(ctl); return -1; } data = -1; fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion); tls = tlsServer2(ctl, hand, conn->cert, conn->certlen, conn->pskID, conn->psk, conn->psklen, conn->trace, conn->chain); if(tls != nil){ snprint(dname, sizeof(dname), "#a/tls/%s/data", buf); data = open(dname, ORDWR); } close(hand); close(ctl); if(data < 0){ tlsConnectionFree(tls); return -1; } free(conn->cert); conn->cert = nil; // client certificates are not yet implemented conn->certlen = 0; conn->sessionIDlen = 0; conn->sessionID = nil; if(conn->sessionKey != nil && conn->sessionType != nil && strcmp(conn->sessionType, "ttls") == 0){ memmove(seed, tls->sec->crandom, RandomSize); memmove(seed+RandomSize, tls->sec->srandom, RandomSize); tls->sec->prf( conn->sessionKey, conn->sessionKeylen, tls->sec->sec, MasterSecretSize, conn->sessionConst, seed, sizeof(seed)); } tlsConnectionFree(tls); close(fd); return data; } static uchar* tlsClientExtensions(TLSconn *conn, int *plen) { uchar *b, *p; int i, n, m; p = b = nil;