check in some experimental X.509 parsing code
This commit is contained in:
30
Makefile
30
Makefile
@@ -3,7 +3,7 @@
|
||||
|
||||
all: t1 t2 parse dumpidx idx2ldif addindex bindrequest tinyldap \
|
||||
tinyldap_standalone tinyldap_debug ldapclient ldapclient_str \
|
||||
md5password mysql2ldif acl dumpacls ldapdelete asn1dump # t6 # t
|
||||
md5password mysql2ldif acl dumpacls ldapdelete asn1dump tls.a x # t6 # t
|
||||
|
||||
asn1.a: fmt_asn1intpayload.o fmt_asn1length.o fmt_asn1tag.o \
|
||||
fmt_asn1int.o fmt_asn1string.o fmt_asn1transparent.o scan_asn1tag.o \
|
||||
@@ -37,6 +37,13 @@ mduptab_init.o mduptab_init_reuse.o mduptab_reset.o
|
||||
|
||||
auth.a: auth.o
|
||||
|
||||
tls.a: fmt_tls_clienthello.o init_tls_context.o \
|
||||
fmt_tls_serverhello.o fmt_tls_alert.o fmt_tls_packet.o \
|
||||
tls_cipherprio.o fmt_tls_alert_pkt.o fmt_tls_handshake_cert.o \
|
||||
fmt_tls_handshake_certs_header.o fmt_tls_serverhellodone.o \
|
||||
tls_accept.o tls_connect.o tls_doread.o tls_dowrite.o
|
||||
|
||||
|
||||
DIET=/opt/diet/bin/diet -Os
|
||||
CROSS=
|
||||
#CROSS=i686-mingw32-
|
||||
@@ -171,10 +178,31 @@ scan_asn1generic.o: scan_asn1generic.c asn1.h
|
||||
|
||||
asn1oid.o: asn1oid.c asn1.h
|
||||
|
||||
init_tls_context.o: init_tls_context.c tinytls.h
|
||||
fmt_tls_clienthello.o: fmt_tls_clienthello.c tinytls.h
|
||||
|
||||
ldap_match_sre.o: ldap_match_sre.c ldap.h
|
||||
|
||||
x: tls.a
|
||||
|
||||
privatekey.pem:
|
||||
openssl genrsa -out $@
|
||||
|
||||
windoze:
|
||||
$(MAKE) DIET= CROSS=i686-mingw32- asn1dump
|
||||
|
||||
fmt_tls_alert.o: fmt_tls_alert.c tinytls.h asn1.h
|
||||
fmt_tls_alert_pkt.o: fmt_tls_alert_pkt.c tinytls.h asn1.h
|
||||
fmt_tls_clienthello.o: fmt_tls_clienthello.c tinytls.h asn1.h
|
||||
fmt_tls_handshake_cert.o: fmt_tls_handshake_cert.c tinytls.h asn1.h
|
||||
fmt_tls_handshake_certs_header.o: fmt_tls_handshake_certs_header.c \
|
||||
tinytls.h asn1.h
|
||||
fmt_tls_packet.o: fmt_tls_packet.c tinytls.h asn1.h
|
||||
fmt_tls_serverhello.o: fmt_tls_serverhello.c tinytls.h asn1.h
|
||||
fmt_tls_serverhellodone.o: fmt_tls_serverhellodone.c tinytls.h asn1.h
|
||||
init_tls_context.o: init_tls_context.c tinytls.h asn1.h
|
||||
tls_accept.o: tls_accept.c tinytls.h asn1.h
|
||||
tls_cipherprio.o: tls_cipherprio.c
|
||||
tls_connect.o: tls_connect.c tinytls.h asn1.h
|
||||
tls_doread.o: tls_doread.c tinytls.h asn1.h
|
||||
tls_dowrite.o: tls_dowrite.c tinytls.h asn1.h
|
||||
|
||||
10
fmt_tls_alert.c
Normal file
10
fmt_tls_alert.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "tinytls.h"
|
||||
|
||||
size_t fmt_tls_alert(char* dest,enum alertlevel level,enum alerttype type) {
|
||||
if (dest) {
|
||||
dest[0]=level;
|
||||
dest[1]=type;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
11
fmt_tls_alert_pkt.c
Normal file
11
fmt_tls_alert_pkt.c
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <string.h>
|
||||
#include "tinytls.h"
|
||||
|
||||
size_t fmt_tls_alert_pkt(char* dest,enum alertlevel level,enum alerttype type) {
|
||||
if (dest) {
|
||||
memcpy(dest,"\x15\x03\x03\x00\x02",5);
|
||||
dest[5]=level;
|
||||
dest[6]=type;
|
||||
}
|
||||
return 7;
|
||||
}
|
||||
51
fmt_tls_clienthello.c
Normal file
51
fmt_tls_clienthello.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "tinytls.h"
|
||||
#include "uint16.h"
|
||||
#include "uint32.h"
|
||||
#include <time.h>
|
||||
|
||||
size_t fmt_tls_clienthello(char* dest, struct ssl_context* sc) {
|
||||
size_t hnextlen=sc->servername?strlen(sc->servername)+9:0;
|
||||
if (hnextlen>0x1000) return 0;
|
||||
if (sc->session.l>0xff) return 0;
|
||||
if (dest) {
|
||||
char* x;
|
||||
dest[0]=22; // content type: handshake
|
||||
uint16_pack_big(dest+1,0x303); // tls 1.2
|
||||
// uint16_pack_big(dest+3,length);
|
||||
dest[5]=0x01; // handshake type: client hello
|
||||
// uint16_pack_big(dest+6,length);
|
||||
uint16_pack_big(dest+9,0x0303); // tls 1.2
|
||||
uint32_pack_big(dest+11,time(0));
|
||||
memcpy(dest+15,sc->myrandom,sizeof(sc->myrandom));
|
||||
if ((dest[43]=sc->session.l))
|
||||
memcpy(dest+44,sc->session.s,sc->session.l);
|
||||
x=dest+44+sc->session.l;
|
||||
uint16_pack_big(x,6);
|
||||
uint16_pack_big(x+2,0x3d); // TLS_RSA_WITH_AES_256_CBC_SHA256
|
||||
uint16_pack_big(x+4,0x35); // TLS_RSA_WITH_AES_256_CBC_SHA
|
||||
uint16_pack_big(x+6,0xff); // "we support renegotiation"
|
||||
x+=8;
|
||||
#if 0
|
||||
memcpy(x,"\x02\x01\x00",3); // 2 compression methods, deflate and null
|
||||
x+=3;
|
||||
#else
|
||||
memcpy(x,"\x01\x00",2); // only support null compression
|
||||
x+=2;
|
||||
#endif
|
||||
uint16_pack_big(x,hnextlen);
|
||||
x+=2;
|
||||
if (hnextlen) {
|
||||
uint16_pack_big(x,0); // extension id 0 = server_name
|
||||
uint16_pack_big(x+2,hnextlen-4); // length
|
||||
uint16_pack_big(x+4,hnextlen-6); // another length
|
||||
x[6]=0; // hostname type: DNS
|
||||
uint16_pack_big(x+7,hnextlen-9); // yet another length
|
||||
memcpy(x+9,sc->servername,hnextlen-9);
|
||||
x+=hnextlen;
|
||||
}
|
||||
uint16_pack_big(dest+3,x-dest-5);
|
||||
uint16_pack_big(dest+7,x-dest-9);
|
||||
return x-dest;
|
||||
} else
|
||||
return 44+sc->session.l+8+2+2+hnextlen;
|
||||
}
|
||||
13
fmt_tls_packet.c
Normal file
13
fmt_tls_packet.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "tinytls.h"
|
||||
#include "uint16.h"
|
||||
|
||||
size_t fmt_tls_packet(char* dest,enum contenttype ct, size_t len) {
|
||||
if (len>0xffff) return 0;
|
||||
if (dest) {
|
||||
dest[0]=ct;
|
||||
dest[1]=0x03; dest[2]=0x03; // version: TLS 1.2
|
||||
dest[3]=len>>8;
|
||||
dest[4]=len&0xff;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
163
fmt_tls_serverhello.c
Normal file
163
fmt_tls_serverhello.c
Normal file
@@ -0,0 +1,163 @@
|
||||
#include "uint16.h"
|
||||
#include "uint32.h"
|
||||
#include "tinytls.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
|
||||
This function parses a client helo and writes the server helo into a
|
||||
buffer. It returns the number of bytes in the server helo message,
|
||||
so you can send it over the TCP connection. If you pass in NULL as
|
||||
the destination buffer, the function tells you how much space it
|
||||
would have needed. So the regular way to use it is to call it twice.
|
||||
|
||||
For efficiency: server helo is around 50 bytes of boilerplate plus
|
||||
the session data (which comes from the SSL context you are passing
|
||||
in, field session.l, and its length is limited to 255 bytes).
|
||||
|
||||
The function returns (size_t)-1 if the input buffer does not contain a
|
||||
full client helo message (i.e. "read more data, then try again") and
|
||||
it returns (size_t)-2 if the input buffer contained an invalid message
|
||||
("somebody is trying to hack you; drop connection").
|
||||
|
||||
If we do not support any of the ciphers or compression methods the other
|
||||
side wants, this function writes an alert message into the buffer
|
||||
(length 7). You are then supposed to send that buffer and close the
|
||||
connection.
|
||||
|
||||
Note that TLS has an encapsulation, so you get an outer message header
|
||||
and an inner message header. For both input and output we handle both
|
||||
headers.
|
||||
|
||||
*/
|
||||
|
||||
size_t fmt_tls_serverhello(char* dest,const char* clienthello,size_t len,struct ssl_context* sc) {
|
||||
size_t l,i;
|
||||
int compressionmethod=-1,hostlen=-1;
|
||||
const char* host;
|
||||
uint16_t best=0,bestprio=0x7fff;
|
||||
|
||||
/* first check if the clienthello is completely there */
|
||||
if (len<5 || len<(l=5+uint16_read_big(clienthello+3)))
|
||||
return (size_t)-1;
|
||||
|
||||
/* ok, it's complete, now check if it is valid. */
|
||||
if (l < 49 || // Minimum length with one cipher suite
|
||||
clienthello[0]!=22 || // Content Type: handshake
|
||||
clienthello[1]!=3 || // at least SSL 3.0
|
||||
clienthello[5]!=1 || // Handshake Type: Client Hello
|
||||
clienthello[6]!=0 || // inner length is 3 bytes, outer length is 2 bytes, so first byte of inner length must be 0
|
||||
uint16_read_big(clienthello+7)!=l-9) // inner length must fit into outer length
|
||||
invalid:
|
||||
return (size_t)-2;
|
||||
|
||||
i=43;
|
||||
i+=(unsigned char)clienthello[i]+1; // session length
|
||||
if (i+1>=l) goto invalid;
|
||||
{
|
||||
uint16 ciphers=uint16_read_big(clienthello+i);
|
||||
uint16_t* c;
|
||||
size_t j;
|
||||
if (ciphers&1) goto invalid; // must be multiple of two
|
||||
if (ciphers==0) goto invalid; // must support at least one cipher suite
|
||||
c=(uint16_t*)(clienthello+i+2);
|
||||
if (i+ciphers+2>=l) goto invalid; // do the ciphers fit in the packet?
|
||||
for (j=0; j<ciphers; j+=2) {
|
||||
uint16_t cur;
|
||||
int p=tls_cipherprio((cur=uint16_read_big((char*)(c+j))));
|
||||
// printf("peer supports tls cipher %x\n",cur);
|
||||
if (p<0) continue;
|
||||
if (p<bestprio) {
|
||||
best=cur;
|
||||
bestprio=p;
|
||||
}
|
||||
}
|
||||
i+=ciphers+2; // skip cipher suites
|
||||
}
|
||||
{
|
||||
size_t j,n=(unsigned char)clienthello[i];
|
||||
const char* x=clienthello+i+1;
|
||||
if (i+1+clienthello[i]+2>l) goto invalid; // do the compression methods fit in the packet?
|
||||
for (j=0; j<n; ++j)
|
||||
if (x[i]==0) compressionmethod=0; // for now only support method 0 (no compression)
|
||||
}
|
||||
i+=clienthello[i]+1; // compression methods
|
||||
if (i+uint16_read_big(clienthello+i)+2 != l) // extensions
|
||||
goto invalid;
|
||||
i+=2;
|
||||
while (i<l) {
|
||||
if (i+4>l)
|
||||
goto invalid;
|
||||
if (clienthello[i]==0 && clienthello[i+1]==0) { /* server_name extension */
|
||||
hostlen=uint16_read_big(clienthello+i+2);
|
||||
host=clienthello+i+4;
|
||||
}
|
||||
if ((i+=4+uint16_read_big(clienthello+i+2))>l)
|
||||
goto invalid;
|
||||
}
|
||||
/* The client hello validated OK; we can generate a reply now. */
|
||||
|
||||
/* do we support any of the ciphers and compression methods? */
|
||||
if (bestprio==0x7fff || compressionmethod==-1) { /* nope */
|
||||
return dest?
|
||||
fmt_tls_alert_pkt(dest,FATAL,HANDSHAKE_FAILURE) :
|
||||
7;
|
||||
}
|
||||
|
||||
if (!sc->servername) {
|
||||
/* We have not yet copied the data out of the client hello.
|
||||
* Do so now. */
|
||||
memcpy(sc->theirrandom,clienthello+15,sizeof(sc->theirrandom));
|
||||
sc->cipher=best;
|
||||
sc->compressionmethod=0;
|
||||
if (hostlen!=-1) {
|
||||
char* sn;
|
||||
if (!(sn=malloc(hostlen+1))) {
|
||||
memcpy(sn,host,hostlen);
|
||||
sn[hostlen]=0;
|
||||
sc->servername=sn;
|
||||
}
|
||||
}
|
||||
sc->timestamp=time(0);
|
||||
}
|
||||
|
||||
if (sc->session.l>0xff) return 0;
|
||||
|
||||
if (dest) {
|
||||
char* x;
|
||||
fmt_tls_packet(dest,HANDSHAKE,1+3+2+4+28+1+sc->session.l+2+1+2+5);
|
||||
dest+=5;
|
||||
dest[0]=2; // type 2 = server hello
|
||||
dest[1]=0;
|
||||
uint16_pack_big(dest+2,2+4+28+1+sc->session.l+2+1+2+5);
|
||||
uint16_pack_big(dest+4,0x0303); // version: TLS 1.2
|
||||
uint32_pack_big(dest+6,sc->timestamp);
|
||||
memcpy(dest+10,sc->myrandom,28);
|
||||
x=dest+38;
|
||||
*x=sc->session.l;
|
||||
memcpy(x+1,sc->session.s,sc->session.l);
|
||||
x+=sc->session.l+1;
|
||||
uint16_pack_big(x,sc->cipher);
|
||||
x[2]=sc->compressionmethod;
|
||||
x+=3;
|
||||
memcpy(x,"\x00\x05\xff\x01\x00\x01\x00",7); // this is the renegotiation extension
|
||||
}
|
||||
return 5+1+3+2+4+28+1+sc->session.l+2+1+2+5;
|
||||
#if 0
|
||||
char type = 2;
|
||||
char length[3]; // big endian
|
||||
char version[2]; // 0x03, 0x03
|
||||
uint32_t gmt_unix_time; // big endian
|
||||
char random[28];
|
||||
char session_id_length;
|
||||
char session_id[session_id_length];
|
||||
char cipher_id[2];
|
||||
char compression; // 0 - none, 1 - deflate
|
||||
char extensions_length[2]; // \x00\x05
|
||||
char renegotiation_extension[5]; // \xff\x01\x00\x01\x00
|
||||
#endif
|
||||
|
||||
}
|
||||
19
init_tls_context.c
Normal file
19
init_tls_context.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "tinytls.h"
|
||||
#include "open.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void init_tls_context_norandom(struct ssl_context* sc, const char* servername) {
|
||||
memset(sc,0,sizeof *sc);
|
||||
sc->servername=servername;
|
||||
}
|
||||
|
||||
int init_tls_context(struct ssl_context* sc, const char* servername) {
|
||||
int fd=open_read("/dev/urandom");
|
||||
int r;
|
||||
if (fd==-1) return -1;
|
||||
init_tls_context_norandom(sc,servername);
|
||||
r=read(fd,sc->myrandom,sizeof(sc->myrandom));
|
||||
close(fd);
|
||||
if (r!=sizeof(sc->myrandom)) return -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -32,6 +32,9 @@ struct rsaprivatekey {
|
||||
size_t* freewhendone;
|
||||
};
|
||||
|
||||
struct dsaprivatekey {
|
||||
};
|
||||
|
||||
void printasn1(const char* buf,const char* max);
|
||||
|
||||
static int findindn(struct string* dn,enum x509_oid id,struct string* dest) {
|
||||
@@ -379,7 +382,7 @@ int main(int argc,char* argv[]) {
|
||||
printf("failed to parse certificate\n");
|
||||
free(freewhendone);
|
||||
|
||||
buf=mmap_read(argc>1?argv[1]:"privatekey.pem",&l);
|
||||
buf=mmap_read(argc>2?argv[2]:"privatekey.pem",&l);
|
||||
if (!buf) { puts("privatekey.pem not found"); return 1; }
|
||||
|
||||
n=scan_rsaprivatekey(buf,l,&k,&freewhendone);
|
||||
|
||||
166
tinytls.h
Normal file
166
tinytls.h
Normal file
@@ -0,0 +1,166 @@
|
||||
#ifndef _TINYTLS_H
|
||||
#define _TINYTLS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* for struct string: */
|
||||
#include "asn1.h"
|
||||
|
||||
typedef enum {
|
||||
NONE,
|
||||
FAIL, // protocol failure, refuse all operations
|
||||
|
||||
READ_CLIENTHELLO, // tls_accept called, trying to read client hello
|
||||
WRITE_ALERTFAIL, // got something bad, write alert and fail
|
||||
WRITE_SERVERHELLO, // got client hello, trying to write server hello
|
||||
|
||||
WRITE_CLIENTHELLO, // tls_connect called, trying to write client hello
|
||||
READ_SERVERHELLO, // trying to read server hello
|
||||
READ_CERT, // read server hello, trying to read cert
|
||||
READ_SERVERHELLODONE, // read server hello + cert, trying to read server hello done
|
||||
} tls_state;
|
||||
|
||||
enum { MAXCERT=4 };
|
||||
|
||||
struct ssl_context {
|
||||
tls_state state;
|
||||
char myrandom[28];
|
||||
char theirrandom[28];
|
||||
time_t timestamp; /* so we can age out old sessions from the session id cache */
|
||||
const char* servername;
|
||||
struct string session; // a cookie sent during the handshake, so if a client comes back later, we can save work
|
||||
struct string mycert[MAXCERT]; // my own cert, maybe an intermediate cert, and a ca cert; sent during handshake
|
||||
struct string theircert[MAXCERT];
|
||||
struct string message; // the packet we are currently trying to read or write
|
||||
size_t ofsinmessage;
|
||||
char scratch[2048];
|
||||
ssize_t (*_read)(uintptr_t handle,char* buf,size_t len);
|
||||
ssize_t (*_write)(uintptr_t handle,const char* buf,size_t len);
|
||||
int (*_close)(uintptr_t handle);
|
||||
int (*readcert)(struct ssl_context* sc); // use sc->servername to read cert into sc->mycert
|
||||
// return 0 for success, enum alerttype otherwise
|
||||
uint16_t cipher,compressionmethod;
|
||||
};
|
||||
|
||||
/* Put servername into ssl_context, set empty session. */
|
||||
void init_tls_context_norandom(struct ssl_context* sc, const char* servername);
|
||||
|
||||
/* Put servername into ssl_context, and fill random bytes from
|
||||
* /dev/urandom. Return 0 if OK, -1 if /dev/urandom failed */
|
||||
int init_tls_context(struct ssl_context* sc, const char* servername);
|
||||
|
||||
/* Generate a client hello inside a handshake packet using the
|
||||
* servername and session data from the context, return number of bytes
|
||||
* written to dest. Call with dest=NULL to get needed buffer size. */
|
||||
size_t fmt_tls_clienthello(char* dest, struct ssl_context* sc);
|
||||
|
||||
/* The response to a client hello consists of several packets:
|
||||
1. server hello
|
||||
2. certificate
|
||||
[3. server key exchange for a DHE cipher suite]
|
||||
4. server hello done */
|
||||
|
||||
/* Generate a server hello from a client hello that came in, return
|
||||
* number of bytes written to dest.
|
||||
* Call with dest=NULL to get needed buffer size.
|
||||
* Returns (size_t)-1 if the client hello is not complete,
|
||||
* (size_t)-2 if the client hello is invalid
|
||||
* if the client helo is valid but has no common ciphers, write an alert
|
||||
* and return length of alert (7) */
|
||||
size_t fmt_tls_serverhello(char* dest,const char* clienthelo,size_t len,struct ssl_context* sc);
|
||||
|
||||
/*
|
||||
* Allocate a buffer that can hold all the X.509 certificates plus 3
|
||||
* bytes per certificate plus 12 bytes for the headers. Write the
|
||||
* certificates to buf+12 using fmt_tls_handshake_cert. Then write
|
||||
* the header to buf using fmt_tls_handshake_certs_header; give it the
|
||||
* sum of the return values of fmt_tls_handshake_cert as len.
|
||||
*/
|
||||
size_t fmt_tls_handshake_cert(char* dest,const char* cert,size_t len);
|
||||
size_t fmt_tls_handshake_certs_header(char* dest,size_t len_of_certs);
|
||||
|
||||
size_t fmt_tls_serverhellodone(char* dest);
|
||||
|
||||
size_t scan_tls_serverhello(const char* buf,size_t len,struct ssl_context* sc);
|
||||
|
||||
enum alertlevel {
|
||||
WARNING=1,
|
||||
FATAL=2
|
||||
};
|
||||
|
||||
enum alerttype {
|
||||
CLOSE_NOTIFY=0,
|
||||
UNEXPECTED_MESSAGE=10,
|
||||
BAD_RECORD_MAC=20,
|
||||
DECRYPTION_FAILED=21,
|
||||
RECORD_OVERFLOW=22,
|
||||
DECOMPRESSION_FAILURE=30,
|
||||
HANDSHAKE_FAILURE=40,
|
||||
NO_CERT=41,
|
||||
BAD_CERT=42,
|
||||
UNSUPPORTED_CERT=43,
|
||||
CERT_REVOKED=44,
|
||||
CERT_EXPIRED=45,
|
||||
CERT_UNKNOWN=46,
|
||||
ILLEGAL_PARAMETER=47,
|
||||
UNKNOWN_CA=48,
|
||||
ACCESS_DENIED=49,
|
||||
DECODE_ERROR=50,
|
||||
DECRYPT_ERROR=51,
|
||||
EXPORT_RESTRICTION=60,
|
||||
PROTOCOL_VERSION=70,
|
||||
INSUFFICIENT_SECURITY=71,
|
||||
INTERNAL_ERROR=80,
|
||||
USER_CANCELED=90,
|
||||
NO_RENEGOTIATION=100,
|
||||
UNSUPPORTED_EXT=110
|
||||
};
|
||||
|
||||
/* Generate a TLS alert (only the alert!) */
|
||||
size_t fmt_tls_alert(char* dest,enum alertlevel level,enum alerttype type);
|
||||
|
||||
/* Generate a TLS alert with outer header */
|
||||
size_t fmt_tls_alert_pkt(char* dest,enum alertlevel level,enum alerttype type);
|
||||
|
||||
enum contenttype {
|
||||
CHANGE_CIPHER_SPEC=20,
|
||||
ALERT=21,
|
||||
HANDSHAKE=22,
|
||||
APPLICATION_DATA=23
|
||||
};
|
||||
|
||||
size_t fmt_tls_packet(char* dest,enum contenttype ct, size_t len);
|
||||
|
||||
enum ciphers {
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA256=0x3d,
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA=0x35,
|
||||
};
|
||||
|
||||
/* return the desirability of a cipher (number >= 0)
|
||||
* or -1 if the cipher is not supported
|
||||
* the higher the number, the less desirable is the cipher */
|
||||
int tls_cipherprio(uint16_t cipher);
|
||||
|
||||
typedef enum {
|
||||
OK=0,
|
||||
IOFAIL=-1, // I/O error
|
||||
WANTREAD=-2, // socket was non-blocking; wait for read event
|
||||
WANTWRITE=-3, // socket was non-blocking; wait for write event
|
||||
OOM=-4, // out of memory
|
||||
PROTOCOLFAIL=-5, // received invalid packets
|
||||
NEGOTIATIONFAIL=-6, // no common ciphers / compression methods
|
||||
CRYPTOFAIL=-7, // cryptographic failure (weak key detected or so)
|
||||
CERTFAIL=-8, // certificate validation failed
|
||||
YOUSUCK=-42, // user-supplied callbacks violated protocol
|
||||
} tls_error_code;
|
||||
|
||||
tls_error_code tls_connect(uintptr_t fd,struct ssl_context* sc);
|
||||
tls_error_code tls_accept(uintptr_t fd,struct ssl_context* sc);
|
||||
|
||||
/* these are internal helpers */
|
||||
tls_error_code tls_dowrite(uintptr_t fd,struct ssl_context* sc);
|
||||
tls_error_code tls_doread(uintptr_t fd,struct ssl_context* sc);
|
||||
tls_error_code tls_checkalert(struct ssl_context* sc);
|
||||
|
||||
#endif
|
||||
13
tls_cipherprio.c
Normal file
13
tls_cipherprio.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <tinytls.h>
|
||||
|
||||
static uint16_t ciphers[] = {
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
};
|
||||
|
||||
int tls_cipherprio(uint16_t cipher) {
|
||||
size_t i;
|
||||
for (i=0; i<sizeof(ciphers)/sizeof(ciphers[0]); ++i)
|
||||
if (ciphers[i]==cipher) return i;
|
||||
return -1;
|
||||
}
|
||||
56
x.c
Normal file
56
x.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "tinytls.h"
|
||||
#include "errmsg.h"
|
||||
#include "ip4.h"
|
||||
#include "socket.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
char pkt[]=
|
||||
"\x16\x03\x01\x01\x4e\x01\x00\x01\x4a\x03\x03\x4f\x93\x81\xfb\x57"
|
||||
"\x72\x4b\x79\x31\x35\x0f\x4e\xb6\xd5\x47\xb7\x0d\xb5\x54\x0e\xd1"
|
||||
"\x71\xc1\xb6\x9b\x9f\xdb\xa5\xf0\xe4\x43\xac\x00\x00\xa0\xc0\x30"
|
||||
"\xc0\x2c\xc0\x28\xc0\x24\xc0\x14\xc0\x0a\xc0\x22\xc0\x21\x00\xa3"
|
||||
"\x00\x9f\x00\x6b\x00\x6a\x00\x39\x00\x38\x00\x88\x00\x87\xc0\x32"
|
||||
"\xc0\x2e\xc0\x2a\xc0\x26\xc0\x0f\xc0\x05\x00\x9d\x00\x3d\x00\x35"
|
||||
"\x00\x84\xc0\x12\xc0\x08\xc0\x1c\xc0\x1b\x00\x16\x00\x13\xc0\x0d"
|
||||
"\xc0\x03\x00\x0a\xc0\x2f\xc0\x2b\xc0\x27\xc0\x23\xc0\x13\xc0\x09"
|
||||
"\xc0\x1f\xc0\x1e\x00\xa2\x00\x9e\x00\x67\x00\x40\x00\x33\x00\x32"
|
||||
"\x00\x9a\x00\x99\x00\x45\x00\x44\xc0\x31\xc0\x2d\xc0\x29\xc0\x25"
|
||||
"\xc0\x0e\xc0\x04\x00\x9c\x00\x3c\x00\x2f\x00\x96\x00\x41\x00\x07"
|
||||
"\xc0\x11\xc0\x07\xc0\x0c\xc0\x02\x00\x05\x00\x04\x00\x15\x00\x12"
|
||||
"\x00\x09\x00\x14\x00\x11\x00\x08\x00\x06\x00\x03\x00\xff\x02\x01"
|
||||
"\x00\x00\x80\x00\x00\x00\x11\x00\x0f\x00\x00\x0c\x62\x6c\x6f\x67"
|
||||
"\x2e\x66\x65\x66\x65\x2e\x64\x65\x00\x0b\x00\x04\x03\x00\x01\x02"
|
||||
"\x00\x0a\x00\x34\x00\x32\x00\x0e\x00\x0d\x00\x19\x00\x0b\x00\x0c"
|
||||
"\x00\x18\x00\x09\x00\x0a\x00\x16\x00\x17\x00\x08\x00\x06\x00\x07"
|
||||
"\x00\x14\x00\x15\x00\x04\x00\x05\x00\x12\x00\x13\x00\x01\x00\x02"
|
||||
"\x00\x03\x00\x0f\x00\x10\x00\x11\x00\x0d\x00\x22\x00\x20\x06\x01"
|
||||
"\x06\x02\x06\x03\x05\x01\x05\x02\x05\x03\x04\x01\x04\x02\x04\x03"
|
||||
"\x03\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02\x03\x01\x01\x00\x0f"
|
||||
"\x00\x01\x01\x15\x03\x03\x00\x02\x02\x30";
|
||||
|
||||
int main() {
|
||||
char buf[200];
|
||||
size_t l;
|
||||
struct ssl_context sc;
|
||||
int fd;
|
||||
|
||||
fd=socket_tcp4b();
|
||||
if (fd==-1)
|
||||
diesys(1,"socket");
|
||||
if (socket_connect4(fd,ip4loopback,443)==-1)
|
||||
if (socket_connect4(fd,ip4loopback,4433)==-1)
|
||||
diesys(1,"connect");
|
||||
|
||||
#if 0
|
||||
init_tls_context_norandom(&sc,NULL);
|
||||
printf("%zu\n",fmt_tls_serverhello(NULL,pkt,sizeof(pkt),&sc));
|
||||
init_tls_context_norandom(&sc,"blog.fefe.de");
|
||||
l=fmt_tls_clienthello(buf,&sc);
|
||||
printf("%zu\n",fmt_tls_serverhello(NULL,buf,l,&sc));
|
||||
#endif
|
||||
|
||||
init_tls_context(&sc,"localhost");
|
||||
tls_connect(fd,&sc);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user