Created
March 28, 2014 20:13
-
-
Save roxlu/9841988 to your computer and use it in GitHub Desktop.
DTLS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "krx_dtls.h" | |
int krx_dtls_init() { | |
SSL_library_init(); | |
SSL_load_error_strings(); | |
ERR_load_BIO_strings(); | |
OpenSSL_add_all_algorithms(); | |
return 0; | |
} | |
int krx_dtls_shutdown() { | |
ERR_remove_state(0); | |
ENGINE_cleanup(); | |
CONF_modules_unload(1); | |
ERR_free_strings(); | |
EVP_cleanup(); | |
sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); | |
CRYPTO_cleanup_all_ex_data(); | |
return 0; | |
} | |
int krx_dtls_create(krx_dtls_t* k) { | |
int r = 0; | |
r = krx_dtls_ssl_ctx_create(k); | |
if(r < 0) { | |
return r; | |
} | |
r = krx_dtls_ssl_create(k); | |
if(r < 0) { | |
return r; | |
} | |
return 0; | |
} | |
int krx_dtls_ssl_ctx_create(krx_dtls_t* k) { | |
int r = 0; | |
/* set default state */ | |
k->state = KRX_DTLS_STATE_NONE; | |
/* create a new context using DTLS */ | |
k->ctx = SSL_CTX_new(DTLSv1_method()); | |
if(!k->ctx) { | |
printf("Error: cannot create SSL_CTX.\n"); | |
ERR_print_errors_fp(stderr); | |
return -1; | |
} | |
/* set our supported ciphers */ | |
r = SSL_CTX_set_cipher_list(k->ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); | |
if(r != 1) { | |
printf("Error: cannot set the cipher list.\n"); | |
ERR_print_errors_fp(stderr); | |
return -2; | |
} | |
/* the client doesn't have to send it's certificate */ | |
SSL_CTX_set_verify(k->ctx, SSL_VERIFY_PEER, krx_dtls_ssl_verify_peer); | |
/* enable srtp */ | |
r = SSL_CTX_set_tlsext_use_srtp(k->ctx, "SRTP_AES128_CM_SHA1_80"); | |
if(r != 0) { | |
printf("Error: cannot setup srtp.\n"); | |
ERR_print_errors_fp(stderr); | |
return -3; | |
} | |
/* certificate file; contains also the public key */ | |
r = SSL_CTX_use_certificate_file(k->ctx, "./server-cert.pem", SSL_FILETYPE_PEM); | |
if(r != 1) { | |
printf("Error: cannot load certificate file.\n"); | |
ERR_print_errors_fp(stderr); | |
return -4; | |
} | |
/* load private key */ | |
r = SSL_CTX_use_PrivateKey_file(k->ctx, "./server-key.pem", SSL_FILETYPE_PEM); | |
if(r != 1) { | |
printf("Error: cannot load private key file.\n"); | |
ERR_print_errors_fp(stderr); | |
return -5; | |
} | |
/* check if the private key is valid */ | |
r = SSL_CTX_check_private_key(k->ctx); | |
if(r != 1) { | |
printf("Error: checking the private key failed. \n"); | |
ERR_print_errors_fp(stderr); | |
return -6; | |
} | |
return 0; | |
} | |
int krx_dtls_ssl_create(krx_dtls_t* k) { | |
/* create SSL* */ | |
k->ssl = SSL_new(k->ctx); | |
if(!k->ssl) { | |
printf("Error: cannot create new SSL*.\n"); | |
return -1; | |
} | |
/* info callback */ | |
SSL_set_info_callback(k->ssl, krx_dtls_ssl_info_callback); | |
/* bios */ | |
k->in_bio = BIO_new(BIO_s_mem()); | |
if(k->in_bio == NULL) { | |
printf("Error: cannot allocate read bio.\n"); | |
return -2; | |
} | |
BIO_set_mem_eof_return(k->in_bio, -1); /* see: https://www.openssl.org/docs/crypto/BIO_s_mem.html */ | |
k->out_bio = BIO_new(BIO_s_mem()); | |
if(k->out_bio == NULL) { | |
printf("Error: cannot allocate write bio.\n"); | |
return -3; | |
} | |
BIO_set_mem_eof_return(k->out_bio, -1); /* see: https://www.openssl.org/docs/crypto/BIO_s_mem.html */ | |
SSL_set_bio(k->ssl, k->in_bio, k->out_bio); | |
/* either use the server or client part of the protocol */ | |
if(k->type == KRX_DTLS_TYPE_SERVER) { | |
SSL_set_accept_state(k->ssl); | |
} | |
else { | |
SSL_set_connect_state(k->ssl); | |
} | |
return 0; | |
} | |
void krx_dtls_ssl_info_callback(const SSL* ssl, int where, int ret) { | |
if(ret == 0) { | |
printf("-- krx_ssl_info_callback: error occured.\n"); | |
return; | |
} | |
SSL_WHERE_INFO(ssl, where, SSL_CB_LOOP, "LOOP"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_EXIT, "EXIT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_READ, "READ"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_WRITE, "WRITE"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_ALERT, "ALERT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_READ_ALERT, "READ ALERT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_WRITE_ALERT, "WRITE ALERT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_ACCEPT_LOOP, "ACCEPT LOOP"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_ACCEPT_EXIT, "ACCEPT EXIT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_CONNECT_LOOP, "CONNECT LOOP"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_CONNECT_EXIT, "CONNECT EXIT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE"); | |
} | |
int krx_dtls_ssl_verify_peer(int ok, X509_STORE_CTX* ctx) { | |
return 1; | |
} | |
int krx_dtls_destroy(krx_dtls_t* k) { | |
if(!k) { | |
return -1; | |
} | |
if(k->ctx) { | |
SSL_CTX_free(k->ctx); | |
k->ctx = NULL; | |
} | |
if(k->ssl) { | |
SSL_free(k->ssl); | |
k->ssl = NULL; | |
} | |
return 0; | |
} | |
int krx_dtls_is_handshake_done(krx_dtls_t* k) { | |
return (k->state & KRX_DTLS_STATE_HANDSHAKE_DONE) ? 1 : -1; | |
} | |
int krx_dtls_handle_traffic(krx_dtls_t* k, uint8_t* data, int len) { | |
if(k->type != KRX_DTLS_TYPE_SERVER) { | |
printf("Warning: only handling server types now.\n"); | |
return -1; | |
} | |
int written = BIO_write(k->in_bio, data, len); | |
if(written > 0) { | |
/* not yet ready with the handshake? */ | |
if(!(k->state & KRX_DTLS_STATE_HANDSHAKE_DONE) | |
&& !SSL_is_init_finished(k->ssl)) | |
{ | |
SSL_do_handshake(k->ssl); | |
return krx_dtls_ssl_check_output_buffer(k); | |
} | |
else { | |
k->state |= KRX_DTLS_STATE_HANDSHAKE_DONE; | |
printf("===================================== FINISHED =================================\n"); | |
} | |
} | |
/* | |
// Did SSL write something into the out buffer | |
char outbuf[4096]; | |
int written = 0; | |
int read = 0; | |
int pending = BIO_ctrl_pending(k->out_bio); | |
if(pending > 0) { | |
read = BIO_read(from->out_bio, outbuf, sizeof(outbuf)); | |
} | |
printf("%s Pending %d, and read: %d\n", from->name, pending, read); | |
if(read > 0) { | |
written = BIO_write(to->in_bio, outbuf, read); | |
} | |
if(written > 0) { | |
if(!SSL_is_init_finished(to->ssl)) { | |
SSL_do_handshake(to->ssl); | |
} | |
else { | |
read = SSL_read(to->ssl, outbuf, sizeof(outbuf)); | |
printf("%s read: %s\n", to->name, outbuf); | |
} | |
} | |
*/ | |
return 0; | |
} | |
int krx_dtls_ssl_check_output_buffer(krx_dtls_t* k) { | |
int pending = BIO_ctrl_pending(k->out_bio); | |
if(pending > 0) { | |
printf("+ Pending bytes in out buffer: %d\n", pending); | |
uint8_t buffer[pending]; | |
int nread = BIO_read(k->out_bio, buffer, sizeof(buffer)); | |
int nsend = k->send(k, buffer, nread); | |
if(nsend != nread) { | |
printf("Error: not yet handling a case where we didn't send everything directly.\n"); | |
exit(EXIT_FAILURE); | |
} | |
return nsend; | |
} | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
krx_dtls | |
-------- | |
Experimental wrapper around openSSL. To use this library make sure you call | |
`krx_dtls_init()` at least once before calling any of the other functions. When | |
you shutdown your application make sure to call `krx_dtls_shutdown()`. | |
````c | |
krx_dtls_init(); // at the start of your app. | |
krx_dtls_t k; | |
if(krx_dtls_create(&k) < 0) { | |
return -1; | |
} | |
if(krx_dtls_destroy(&k)) { | |
} | |
krx_dtls_shutdown(); // at the end of your app. | |
```` | |
Create server/client self-signed certificate/key (self signed, DONT ADD PASSWORD) | |
openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout client-key.pem -out client-cert.pem | |
openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-cert.pem | |
*/ | |
#ifndef ROXLU_KRX_DTLS_H | |
#define ROXLU_KRX_DTLS_H | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <openssl/err.h> | |
#include <openssl/dh.h> | |
#include <openssl/ssl.h> | |
#include <openssl/conf.h> | |
#include <openssl/engine.h> | |
/* SSL debug */ | |
#define SSL_WHERE_INFO(ssl, w, flag, msg) { \ | |
if(w & flag) { \ | |
printf("----- "); \ | |
printf("%20.20s", msg); \ | |
printf(" - %30.30s ", SSL_state_string_long(ssl)); \ | |
printf(" - %5.10s ", SSL_state_string(ssl)); \ | |
printf("\n"); \ | |
} \ | |
} | |
typedef struct krx_dtls krx_dtls_t; | |
typedef int(*krx_dtls_data_callback)(krx_dtls_t* k, uint8_t* buf, int len); | |
typedef enum { | |
KRX_DTLS_TYPE_CLIENT = 0, | |
KRX_DTLS_TYPE_SERVER = 1 | |
} krx_dtls_type_t; | |
typedef enum { | |
KRX_DTLS_STATE_NONE = 0x00, | |
KRX_DTLS_STATE_HANDSHAKE_DONE = 0x01 | |
} krx_dtls_state_t; | |
struct krx_dtls { | |
SSL_CTX* ctx; /* main ssl context */ | |
SSL* ssl; /* the SSL* which represents a "connection" */ | |
BIO* in_bio; /* we use memory read bios */ | |
BIO* out_bio; /* we use memory write bios */ | |
krx_dtls_data_callback send; /* the send callback; is called when you need to send data to the other endpoint */ | |
krx_dtls_type_t type; /* is this a server or client? */ | |
void* user; /* user pointer */ | |
krx_dtls_state_t state; /* state; simply used to check if the handshake has been done. */ | |
}; | |
/* public API */ | |
int krx_dtls_init(); /* initialize; startup SSL/DTLS */ | |
int krx_dtls_shutdown(); /* shutdown; destroy SSL/DTLS */ | |
int krx_dtls_create(krx_dtls_t* k); /* create the krx_dtls_t object. setups up a complete SSL context */ | |
int krx_dtls_destroy(krx_dtls_t* k); /* cleans up everything which has been created by krx_dtls_create(). */ | |
int krx_dtls_handle_traffic(krx_dtls_t* k, uint8_t* data, int len); /* call this whenever you receive data; data is the encrypted data you received. */ | |
int krx_dtls_is_handshake_done(krx_dtls_t* k); /* returns -1 when the handshake has been done, else 1 */ | |
/* used internally */ | |
int krx_dtls_ssl_ctx_create(krx_dtls_t* k); /* initializes the SSL_CTX */ | |
int krx_dtls_ssl_create(krx_dtls_t* k); /* creates a SSL* object */ | |
void krx_dtls_ssl_info_callback(const SSL* ssl, int where, int ret); /* prints some debug info */ | |
int krx_dtls_ssl_verify_peer(int ok, X509_STORE_CTX* ctx); /* we use VERIFY_PEER to get the client certificate */ | |
int krx_dtls_ssl_check_output_buffer(krx_dtls_t* k); | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
1) Open index.html in your browser (e.g. start local webserver) | |
cd projects/html | |
python -m SimpleHTTPServer | |
2) Open http://localhost:8000/ in a browser | |
3) Execute this application (run ./release from the build dir.) | |
4) Press the START button. | |
5) Press the >> button | |
Repeat 2-5 if you want to test new code. | |
-- | |
Create server/client self-signed certificate/key: | |
openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout client-key.pem -out client-cert.pem | |
openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-cert.pem | |
References: | |
----------- | |
- Old version of this file: https://gist.github.com/roxlu/aaef70ee7954e41c8b3e | |
*/ | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netdb.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <signal.h> | |
#include <unistd.h> | |
#include <stun5389.h> | |
#include <openssl/err.h> | |
#include <openssl/dh.h> | |
#include <openssl/ssl.h> | |
#include <openssl/conf.h> | |
#include <openssl/engine.h> | |
#include "krx_dtls.h" | |
#include <srtp.h> | |
#define KRX_UDP_BUF_LEN 512 | |
#define HTTPD_BUF_LEN 4096 | |
/* See RFC 3711 - see strp.h*/ | |
#define KRX_SRTP_MASTER_KEY_LEN 16 | |
#define KRX_SRTP_MASTER_SALT_LEN 14 | |
#define KRX_SRTP_MASTER_LEN (KRX_SRTP_MASTER_KEY_LEN + KRX_SRTP_MASTER_SALT_LEN) | |
enum { | |
KRX_STATE_NONE, | |
KRX_STATE_SSL_INIT_READY | |
}; | |
typedef struct { | |
SSL* ssl; | |
SSL_CTX* ctx; | |
X509* client_cert; | |
BIO* in; | |
BIO* out; | |
bool conn_initialized; | |
uint8_t* in_buf; | |
int in_pos; | |
int in_len; | |
uint8_t* out_buf; | |
int out_pos; | |
int out_len; | |
void* user; /* udp_conn */ | |
} krx_ssl; | |
typedef struct { | |
srtp_t session; | |
srtp_stream_t stream; | |
srtp_policy_t policy; | |
} krx_srtp; | |
typedef struct { | |
/* general */ | |
int state; /* just a tiny helper we use for this experimental code to keep track of state */ | |
/* initial networking */ | |
int sock; | |
int port; | |
struct sockaddr_in saddr; | |
unsigned char buf[KRX_UDP_BUF_LEN]; | |
struct sockaddr_in client; | |
/* stun based listening */ | |
int stun_fd; | |
int stun_port; | |
struct sockaddr_in stun_saddr; | |
struct sockaddr_in stun_raddr; | |
/* stun */ | |
StunAgent agent; | |
StunMessage request; | |
StunMessage response; | |
char stun_pw[512] ; | |
/* ssl */ | |
krx_ssl ssl; | |
/* srtp */ | |
krx_srtp srtp; | |
krx_dtls_t dtls; | |
} udp_conn; | |
/* accepting http requests for the password from the signaling */ | |
typedef struct { | |
/* networking */ | |
int fd; | |
int port; | |
struct sockaddr_in saddr; | |
unsigned char buf[HTTPD_BUF_LEN]; | |
} httpd_conn; | |
/* WebRTC */ | |
bool must_run = true; | |
void krx_udp_sighandler(int num); | |
int krx_udp_init(udp_conn* c); | |
int krx_udp_bind(udp_conn* c); | |
int krx_udp_receive(udp_conn* c); | |
int krx_udp_send(udp_conn* c, uint8_t* buf, size_t len); | |
void print_buffer(uint8_t *buf, size_t len); | |
void print_stun_validation_status(StunValidationStatus s); | |
void print_stun_class(StunClass c); | |
void print_stun_method(StunMethod m); | |
void print_stun_message_return(StunMessageReturn r); | |
int handle_stun(udp_conn* c, uint8_t *packet, size_t len); | |
/* Signaling */ | |
int krx_httpd_init(httpd_conn* c); | |
void krx_httpd_receive(httpd_conn* c); | |
/* SSL<>DTLS */ | |
void krx_ssl_info_callback(const SSL* ssl, int where, int ret); | |
int krx_ssl_init(krx_ssl* k); | |
int krx_ssl_conn_init(krx_ssl* k); | |
int krx_ssl_bio_create(BIO* b); | |
int krx_ssl_bio_destroy(BIO* b); | |
int krx_ssl_bio_read(BIO* b, char* buf, int len); | |
int krx_ssl_bio_write(BIO* b, const char* buf, int len); | |
long krx_ssl_bio_ctrl(BIO* b, int cmd, long num, void* ptr); | |
int krx_ssl_verify(int ok, X509_STORE_CTX* ctx); | |
int krx_ssl_print_fingerprint(krx_ssl* k); | |
int krx_ssl_encrypt(krx_ssl* k, uint8_t* out, int max, uint8_t* in, int len); | |
int krx_ssl_decrypt(krx_ssl* k, uint8_t* out, int max, uint8_t* in, int len); | |
/* SRTP */ | |
int krx_init_srtp(krx_srtp* s); | |
/* KRX_DTLS (experimental) */ | |
int krx_send_to_browser(krx_dtls_t* k, uint8_t* data, int len); | |
static struct bio_method_st krx_bio = { | |
BIO_TYPE_SOURCE_SINK, | |
"krx_bio", | |
krx_ssl_bio_write, | |
krx_ssl_bio_read, | |
0, | |
0, | |
krx_ssl_bio_ctrl, | |
krx_ssl_bio_create, | |
krx_ssl_bio_destroy, | |
0 | |
}; | |
/* Globals .. */ | |
httpd_conn* hcon_ptr = NULL; | |
udp_conn* ucon_ptr = NULL; | |
int main() { | |
printf("udp.\n"); | |
udp_conn ucon; | |
ucon.dtls.user = &ucon; | |
ucon.dtls.type = KRX_DTLS_TYPE_SERVER; | |
ucon.dtls.send = krx_send_to_browser; | |
if(krx_dtls_init() < 0) { | |
exit(EXIT_FAILURE); | |
} | |
if(krx_dtls_create(&ucon.dtls) < 0) { | |
exit(EXIT_FAILURE); | |
} | |
/* WebRTC */ | |
ucon.port = 2233; | |
ucon.ssl.user = &ucon; | |
ucon_ptr = &ucon; | |
/* SSL */ | |
if(krx_ssl_init(&ucon.ssl) < 0) { | |
exit(EXIT_FAILURE); | |
} | |
/* SRTP */ | |
if(krx_init_srtp(&ucon.srtp) < 0) { | |
exit(EXIT_FAILURE); | |
} | |
/* HTTP for signaling */ | |
httpd_conn hcon; | |
hcon_ptr = &hcon; | |
hcon.port = 3333; | |
if(krx_httpd_init(&hcon) < 0) { | |
exit(EXIT_FAILURE); | |
} | |
if(krx_udp_init(&ucon) < 0) { | |
exit(EXIT_FAILURE); | |
} | |
if(krx_udp_bind(&ucon) < 0) { | |
exit(EXIT_FAILURE); | |
} | |
signal(SIGINT, krx_udp_sighandler); | |
while(must_run) { | |
//printf("..\n"); | |
krx_udp_receive(&ucon); | |
//sleep(1); | |
} | |
krx_dtls_shutdown(); | |
} | |
void krx_udp_sighandler(int signum) { | |
printf("Verbose: handled sig.\n"); | |
must_run = false; | |
exit(EXIT_FAILURE); | |
} | |
int krx_udp_init(udp_conn* c) { | |
c->sock = socket(AF_INET, SOCK_DGRAM, 0); | |
if(c->sock == -1) { | |
printf("Error: cannot create socket.\n"); | |
return -1; | |
} | |
struct sockaddr_in saddr; | |
c->saddr.sin_family = AF_INET; | |
c->saddr.sin_addr.s_addr = htonl(INADDR_ANY); | |
c->saddr.sin_port = htons(c->port); | |
c->state = KRX_STATE_NONE; | |
return 1; | |
} | |
int krx_udp_bind(udp_conn* c) { | |
int r = bind(c->sock, (struct sockaddr*)&c->saddr, sizeof(c->saddr)); | |
if(r == 0) { | |
return 0; | |
} | |
printf("Error: cannot bind sock.\n"); | |
return -1; | |
} | |
void print_buffer(uint8_t *buf, size_t len) { | |
int i; | |
for(i = 0; i < len; ++i) { | |
printf("%02X ", (unsigned char)buf[i]); | |
if(i > 0 && i % 40 == 0) { | |
printf("\n"); | |
} | |
} | |
printf("\n-\n"); | |
} | |
int handle_stun(udp_conn* c, uint8_t *packet, size_t len) { | |
StunAgent agent; | |
StunValidationStatus status; | |
StunAgentUsageFlags flags; | |
StunMessage request; | |
StunMessage response; | |
int ret; | |
size_t output_size; | |
uint8_t output[1024]; | |
flags = STUN_AGENT_USAGE_IGNORE_CREDENTIALS; // | STUN_AGENT_USAGE_USE_FINGERPRINT; | |
static const uint16_t attr[] = { | |
STUN_ATTRIBUTE_MAPPED_ADDRESS, | |
STUN_ATTRIBUTE_RESPONSE_ADDRESS, | |
STUN_ATTRIBUTE_CHANGE_REQUEST, | |
STUN_ATTRIBUTE_SOURCE_ADDRESS, | |
STUN_ATTRIBUTE_CHANGED_ADDRESS, | |
STUN_ATTRIBUTE_USERNAME, | |
STUN_ATTRIBUTE_PASSWORD, | |
STUN_ATTRIBUTE_MESSAGE_INTEGRITY, | |
STUN_ATTRIBUTE_ERROR_CODE, | |
STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES, | |
STUN_ATTRIBUTE_REFLECTED_FROM, | |
STUN_ATTRIBUTE_CHANNEL_NUMBER, | |
STUN_ATTRIBUTE_LIFETIME, | |
STUN_ATTRIBUTE_MS_ALTERNATE_SERVER, | |
STUN_ATTRIBUTE_MAGIC_COOKIE, | |
STUN_ATTRIBUTE_BANDWIDTH, | |
STUN_ATTRIBUTE_DESTINATION_ADDRESS, | |
STUN_ATTRIBUTE_REMOTE_ADDRESS, | |
STUN_ATTRIBUTE_PEER_ADDRESS, | |
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, | |
STUN_ATTRIBUTE_DATA, | |
STUN_ATTRIBUTE_REALM, | |
STUN_ATTRIBUTE_NONCE, | |
STUN_ATTRIBUTE_RELAY_ADDRESS, | |
STUN_ATTRIBUTE_RELAYED_ADDRESS, | |
STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, | |
STUN_ATTRIBUTE_REQUESTED_ADDRESS_TYPE, | |
STUN_ATTRIBUTE_REQUESTED_PORT_PROPS, | |
STUN_ATTRIBUTE_REQUESTED_PROPS, | |
STUN_ATTRIBUTE_EVEN_PORT, | |
STUN_ATTRIBUTE_REQUESTED_TRANSPORT, | |
STUN_ATTRIBUTE_DONT_FRAGMENT, | |
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, | |
STUN_ATTRIBUTE_TIMER_VAL, | |
STUN_ATTRIBUTE_REQUESTED_IP, | |
STUN_ATTRIBUTE_RESERVATION_TOKEN, | |
STUN_ATTRIBUTE_CONNECT_STAT, | |
STUN_ATTRIBUTE_PRIORITY, | |
STUN_ATTRIBUTE_USE_CANDIDATE, | |
STUN_ATTRIBUTE_OPTIONS, | |
STUN_ATTRIBUTE_MS_VERSION, | |
STUN_ATTRIBUTE_SOFTWARE, | |
STUN_ATTRIBUTE_ALTERNATE_SERVER, | |
STUN_ATTRIBUTE_FINGERPRINT, | |
STUN_ATTRIBUTE_ICE_CONTROLLED, | |
STUN_ATTRIBUTE_ICE_CONTROLLING, | |
STUN_ATTRIBUTE_MS_SEQUENCE_NUMBER, | |
STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER | |
}; | |
/* initialize our agent to be compatible with RFC5389 (= with TLS support) */ | |
output_size = 0; | |
memset(output, 0, sizeof(output)); | |
stun_agent_init(&agent, attr, STUN_COMPATIBILITY_RFC5389, flags); | |
/* validate the request */ | |
status = stun_agent_validate(&agent, &request, packet, len, NULL, NULL); | |
print_stun_validation_status(status); | |
/* check the class */ | |
StunClass request_class = stun_message_get_class(&request); | |
print_stun_class(request_class); | |
if(request_class == STUN_ERROR) { | |
printf("Error: request stun class failed.\n"); | |
exit(0); | |
} | |
/* what stun method? */ | |
StunMethod request_method = stun_message_get_method(&request); | |
print_stun_method(request_method); | |
/* initialize the response */ | |
ret = stun_agent_init_response(&agent, &response, output, 1024, &request); | |
printf("Stun agent_init_response ret: %d\n", ret); | |
/* add xor-mapped-address */ | |
uint32_t magic_cookie = 0; | |
uint8_t* cookie_ptr = NULL; | |
StunTransactionId transid; | |
socklen_t sock_len = 0; | |
char client_ip[16] = { 0 } ; | |
StunMessageReturn stun_ret = STUN_MESSAGE_RETURN_INVALID; | |
stun_message_id(&response, transid); | |
magic_cookie = *((uint32_t*)transid); | |
sock_len = sizeof(c->client); | |
cookie_ptr = (uint8_t*) &magic_cookie; | |
inet_ntop(AF_INET, &c->client.sin_addr.s_addr, client_ip, sizeof(client_ip)); | |
stun_ret = stun_message_append_xor_addr(&response, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, (const struct sockaddr*)&c->client, sock_len); | |
print_stun_message_return(stun_ret); | |
printf("Received data from: %s\n", client_ip); | |
printf("Magic cookie: %02X %02X %02X %02X\n", cookie_ptr[0], cookie_ptr[1], cookie_ptr[2], cookie_ptr[3]); | |
// username | |
// -------- | |
const char* username = NULL; | |
uint16_t username_len = 0; | |
username = (const char*)stun_message_find(&request, STUN_ATTRIBUTE_USERNAME, &username_len); | |
printf("Username: %s, len: %d\n", username, (int)username_len); | |
#if 0 | |
if(username) { | |
StunMessageReturn username_res = stun_message_append_bytes(&response, STUN_ATTRIBUTE_USERNAME, username, username_len); | |
print_stun_message_return(username_res); | |
} | |
uint32_t fingerprint = 0; | |
if(stun_message_find32(&request, STUN_ATTRIBUTE_FINGERPRINT, &fingerprint) == STUN_MESSAGE_RETURN_SUCCESS) { | |
printf("Got fingerprint: %d\n", fingerprint); | |
if(stun_message_append32(&response, STUN_ATTRIBUTE_FINGERPRINT, fingerprint) != STUN_MESSAGE_RETURN_SUCCESS) { | |
printf("Error while adding the fingerprint.\n"); | |
} | |
} | |
#endif | |
// password | |
const char* password = ucon_ptr->stun_pw; // "94ccca06d14fb48c135bdaff30560c4d"; | |
uint16_t password_len = strlen(password) + 1; | |
output_size = stun_agent_finish_message(&agent, &response, (const uint8_t*) password, password_len); | |
// answer to the connection | |
krx_udp_send(c, output, output_size); | |
print_buffer(output, output_size); | |
return 0; | |
} | |
int krx_udp_receive(udp_conn* c) { | |
socklen_t len = sizeof(c->client); | |
int r = recvfrom(c->sock, c->buf, KRX_UDP_BUF_LEN, 0, (struct sockaddr*)&c->client, &len); | |
if(r < 0) { | |
printf("Error: cannot receive.\n"); | |
return -1; | |
} | |
//printf("Got some data:\n"); | |
//print_buffer(c->buf, r); | |
if(r < 2) { | |
printf("Only received 2 bytes?\n"); | |
return 0; | |
} | |
if((c->buf[0] == 0x00 || c->buf[0] == 0x01) && (c->buf[1] == 0x00 || c->buf[1] == 0x01) ) { | |
handle_stun(c, c->buf, r); | |
} | |
else { | |
if(krx_dtls_is_handshake_done(&c->dtls) > 0) { | |
// when done, we pass on the data libsrtp | |
printf("DONE!.\n"); | |
} | |
else { | |
krx_dtls_handle_traffic(&c->dtls, c->buf, r); | |
} | |
} | |
return 0; | |
} | |
int krx_udp_send(udp_conn* c, uint8_t* buf, size_t len) { | |
int r = sendto(c->sock, buf, len, 0, (struct sockaddr*)&c->client, sizeof(c->client)); | |
printf("Sending data on connection: %d, sock: %d\n", r, c->sock); | |
return r; | |
} | |
void print_stun_validation_status(StunValidationStatus s) { | |
switch(s) { | |
case STUN_VALIDATION_SUCCESS: printf("StunValidationStatus: STUN_VALIDATION_SUCCESS\n"); break; | |
case STUN_VALIDATION_NOT_STUN: printf("StunValidationStatus: STUN_VALIDATION_NOT_STUN\n"); break; | |
case STUN_VALIDATION_INCOMPLETE_STUN: printf("StunValidationStatus: STUN_VALIDATION_INCOMPLETE_STUN\n"); break; | |
case STUN_VALIDATION_BAD_REQUEST: printf("StunValidationStatus: STUN_VALIDATION_BAD_REQUEST\n"); break; | |
case STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST: printf("StunValidationStatus: STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST\n"); break; | |
case STUN_VALIDATION_UNAUTHORIZED: printf("StunValidationStatus: STUN_VALIDATION_UNAUTHORIZED\n"); break; | |
case STUN_VALIDATION_UNMATCHED_RESPONSE: printf("StunValidationStatus: STUN_VALIDATION_UNMATCHED_RESPONSE\n"); break; | |
case STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE: printf("StunValidationStatus: STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE\n"); break; | |
case STUN_VALIDATION_UNKNOWN_ATTRIBUTE: printf("StunValidationStatus: STUN_VALIDATION_UNKNOWN_ATTRIBUTE\n"); break; | |
default: printf("StunValidationStatus: unknown status.\n"); break; | |
} | |
} | |
void print_stun_class(StunClass c) { | |
switch(c) { | |
case STUN_REQUEST: printf("StunClass: STUN_REQUEST.\n"); break; | |
case STUN_INDICATION: printf("StunClass: STUN_INDICATION.\n"); break; | |
case STUN_RESPONSE: printf("StunClass: STUN_RESPONSE.\n"); break; | |
case STUN_ERROR: printf("StunClass: STUN_ERROR.\n"); break; | |
default: printf("StunClass: unknown.\n"); break; | |
} | |
} | |
void print_stun_method(StunMethod m) { | |
switch(m) { | |
case STUN_BINDING: printf("StunMethod: STUN_BINDING.\n"); break; | |
case STUN_SHARED_SECRET: printf("StunMethod: STUN_SHARED_SECRET.\n"); break; | |
case STUN_ALLOCATE: printf("StunMethod: STUN_ALLOCATE.\n"); break; | |
case STUN_REFRESH: printf("StunMethod: STUN_REFRESH or STUN_SET_ACTIVE_DST or STUN_SEND.\n"); break; | |
case STUN_CONNECT: printf("StunMethod: STUN_CONNECT.\n"); break; | |
case STUN_IND_SEND: printf("StunMethod: STUN_IND_SEND or STUN_OLD_SET_ACTIVE_DST.\n"); break; | |
case STUN_IND_DATA: printf("StunMethod: STUN_IND_DATA.\n"); break; | |
case STUN_CREATEPERMISSION: printf("StunMethod: STUN_CREATEPERMISSION or STUN_IND_CONNECT_STATUS.\n"); break; | |
case STUN_CHANNELBIND: printf("StunMethod: STUN_CHANNELBIND.\n"); break; | |
default: printf("StunMethod: unkown.\n"); break; | |
} | |
} | |
void print_stun_message_return(StunMessageReturn r) { | |
switch(r) { | |
case STUN_MESSAGE_RETURN_SUCCESS: printf("StunMessageReturn: STUN_MESSAGE_RETURN_SUCCESS.\n"); break; | |
case STUN_MESSAGE_RETURN_NOT_FOUND: printf("StunMessageReturn: STUN_MESSAGE_RETURN_NOT_FOUND.\n"); break; | |
case STUN_MESSAGE_RETURN_INVALID: printf("StunMessageReturn: STUN_MESSAGE_RETURN_INVALID.\n"); break; | |
case STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE: printf("StunMessageReturn: STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE.\n"); break; | |
case STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS: printf("StunMessageReturn: STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS.\n"); break; | |
default: printf("StunMessageReturn: unknown.\n"); break; | |
} | |
} | |
/* HTTP */ | |
/* ----------------------------------------------------------------------------- */ | |
int krx_httpd_init(httpd_conn* c) { | |
c->fd = socket(AF_INET, SOCK_STREAM, 0); | |
if(c->fd < 0) { | |
printf("Error: cannot setup httpd listener.\n"); | |
return -1; | |
} | |
/* reuse */ | |
int val = 1; | |
int r = 0; | |
r = setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); | |
if(r < 0) { | |
printf("Error: cannot set REUSEADDR.\n"); | |
return -2; | |
} | |
c->saddr.sin_family = AF_INET; | |
c->saddr.sin_addr.s_addr = INADDR_ANY; | |
c->saddr.sin_port = htons(c->port); | |
r = bind(c->fd, (struct sockaddr*)&c->saddr, sizeof(c->saddr)); | |
if(r < 0) { | |
printf("Error: cannot bind the httpd socket.\n"); | |
return -2; | |
} | |
printf("Initialize http listener.\n"); | |
r = listen(c->fd, 5); | |
if(r < 0) { | |
printf("Error: cannot listen on the httpd socket.\n"); | |
return -3; | |
} | |
krx_httpd_receive((void*)c); | |
return 0; | |
} | |
/* | |
Extracts the password get variable that it receives from the index.html (see projects). | |
We receive the ice-pwd value that we use in our stun response. | |
*/ | |
void krx_httpd_receive(httpd_conn *c) { | |
httpd_conn* con = c; | |
printf("httpd, start listening on: %d.\n", con->port); | |
bool run = true; | |
while(run) { | |
/* accept new connection */ | |
struct sockaddr_in raddr; | |
socklen_t raddr_len = sizeof(raddr); | |
int fd = accept(con->fd, (struct sockaddr*) &raddr, &raddr_len); | |
if(fd < 0) { | |
printf("Error: while accepting on httpd.\n"); | |
exit(EXIT_FAILURE); | |
} | |
int nread = read(fd, con->buf, HTTPD_BUF_LEN); | |
unsigned char* b = con->buf; | |
for(int i = 0; i < nread - 3; ++i) { | |
/* extract the passwd variable: /?passwd=[THE PASSWORD] */ | |
if(b[i+0] == 'G' && b[i+1] == 'E' && b[i+2] == 'T' && nread > 100) { | |
bool must_copy = false; | |
int copy_pos = 0; | |
for(int j = i; j < nread; ++j) { | |
if(b[j] == '=') { | |
must_copy = true; | |
continue; | |
} | |
if(must_copy && b[j] == ' ') { | |
printf("Got password: '%s'\n", ucon_ptr->stun_pw); | |
run = false; | |
must_copy = false; | |
close(fd); | |
fd = -1; | |
break; | |
} | |
if(must_copy) { | |
ucon_ptr->stun_pw[copy_pos++] = b[j]; | |
} | |
} | |
} | |
} | |
} | |
close(con->fd); | |
printf("Closed httpd socket.\n"); | |
} | |
/* S S L // D T L S */ | |
/* -------------------------------------------------------------------------------- */ | |
int krx_ssl_init(krx_ssl* k) { | |
int r = 0; | |
SSL_library_init(); | |
SSL_load_error_strings(); | |
ERR_load_BIO_strings(); | |
OpenSSL_add_all_algorithms(); | |
/* create a new context using DTLS */ | |
k->ctx = SSL_CTX_new(DTLSv1_method()); | |
if(!k->ctx) { | |
printf("Error: cannot create SSL_CTX.\n"); | |
ERR_print_errors_fp(stderr); | |
return -1; | |
} | |
/* set our supported ciphers */ | |
//r = SSL_CTX_set_cipher_list(k->ctx, "DHE-RSA-AES128-GCM-SHA:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"); | |
//r = SSL_CTX_set_cipher_list(k->ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); | |
//r = SSL_CTX_set_cipher_list(k->ctx, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); | |
r = SSL_CTX_set_cipher_list(k->ctx, "RSA:kDHE"); | |
if(r <= 0) { | |
printf("Error: cannot set the cipher list.\n"); | |
ERR_print_errors_fp(stderr); | |
return -2; | |
} | |
/* the client doesn't have to send it's certificate */ | |
SSL_CTX_set_verify(k->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, krx_ssl_verify); | |
//SSL_CTX_set_session_cache_mode(k->ctx, SSL_SESS_CACHE_OFF); | |
//SSL_CTX_set_verify_depth(k->ctx, 4); | |
SSL_CTX_set_mode(k->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); | |
/* enable srtp */ | |
r = SSL_CTX_set_tlsext_use_srtp(k->ctx, "SRTP_AES128_CM_SHA1_80"); | |
if(r != 0) { | |
printf("Error: cannot setup srtp.\n"); | |
ERR_print_errors_fp(stderr); | |
return -3; | |
} | |
/* load certificate and key */ | |
r = SSL_CTX_use_certificate_file(k->ctx, "./server-cert.pem", SSL_FILETYPE_PEM); | |
if(r <= 0) { | |
printf("Error: cannot load certificate file.\n"); | |
ERR_print_errors_fp(stderr); | |
return -4; | |
} | |
r = SSL_CTX_use_PrivateKey_file(k->ctx, "./server-key.pem", SSL_FILETYPE_PEM); | |
if(r <= 0) { | |
printf("Error: cannot load private key file.\n"); | |
ERR_print_errors_fp(stderr); | |
return -5; | |
} | |
r = SSL_CTX_check_private_key(k->ctx); | |
if(r == 0) { | |
printf("Error: checking the private key failed.\n"); | |
return -6; | |
} | |
k->conn_initialized = false; | |
k->in_pos = 0; | |
k->in_len = 0; | |
k->in_buf = NULL; | |
k->out_pos = 0; | |
k->out_len = 0; | |
k->out_buf = NULL; | |
return 0; | |
} | |
int krx_ssl_bio_create(BIO* b) { | |
b->init = 1; | |
b->num = 0; | |
b->ptr = NULL; | |
b->flags = 0; | |
return 1; | |
} | |
int krx_ssl_bio_destroy(BIO* b) { | |
if(b == NULL) { | |
return 0; | |
} | |
b->ptr = NULL; | |
b->init = 0; | |
b->flags = 0; | |
return 1; | |
} | |
int krx_ssl_bio_read(BIO* b, char* buf, int len) { | |
printf("----- krx_ssl_bio_read() called with %d bytes.\n", len); | |
int r = 0; | |
int avail = 0; | |
krx_ssl* krx = (krx_ssl*)b->ptr; | |
avail = (krx->in_len - krx->in_pos); | |
if(avail == 0) { | |
printf("----- Error: avail is 0.\n"); | |
errno = EAGAIN; | |
return -1; | |
} | |
if(len > avail) { | |
r = avail; | |
} | |
else { | |
r = len; | |
} | |
memcpy(buf, krx->in_buf + krx->in_pos, r); | |
krx->in_pos += r; | |
printf("----- krx_ssl_bio_read(), avail: %d\n", avail); | |
return r; | |
} | |
int krx_ssl_bio_write(BIO* b, const char* buf, int len) { | |
printf("----- krx_ssl_bio_write() called with %d bytes.\n", len); | |
int w = 0; | |
int avail = 0; | |
krx_ssl* krx = (krx_ssl*)b->ptr; | |
printf("----- krx_ssl_bio_write() krx->out_len: %d, krx->out_pos: %d.\n", krx->out_len, krx->out_pos); | |
avail = (krx->out_len - krx->out_pos); | |
if(avail == 0) { | |
errno = EAGAIN; | |
printf("----- Error: avail is 0.\n"); | |
return -1; | |
} | |
if(len > avail) { | |
w = avail; | |
} | |
else { | |
w = len; | |
} | |
memcpy(krx->out_buf + krx->out_pos, buf, w); | |
krx->out_pos += w; | |
return w; | |
} | |
long krx_ssl_bio_ctrl(BIO* b, int cmd, long num, void* ptr) { | |
krx_ssl* krx = (krx_ssl*)b->ptr; | |
switch (cmd) { | |
case BIO_CTRL_FLUSH: { | |
printf("----- DTLS: BIO_CTRL_FLUSH.\n"); | |
//int krx_udp_send(udp_conn* c, uint8_t* buf, size_t len); | |
//printf("out_pos: %d\n", krx->out_pos); | |
//krx_udp_send((udp_conn*)krx->user, krx->out_buf, 1120); /* just a hardcoded test; sends back serverhello */ | |
return 1; | |
} | |
case BIO_CTRL_WPENDING: { | |
printf("----- DTLS: BIO_CTRL_WPENDING: %ld.\n", num); | |
return 0; | |
} | |
case BIO_CTRL_DGRAM_QUERY_MTU: { | |
return 1472; | |
} | |
case BIO_CTRL_GET: { | |
return BIO_TYPE_SOURCE_SINK; | |
} | |
default: { | |
printf("----- DTLS: unhandled bio_ctrl: %d num: %ld\n", cmd, num); | |
break; | |
} | |
} | |
return 0; | |
} | |
/* initialize a new connection; @todo cleanup + free on failure */ | |
int krx_ssl_conn_init(krx_ssl* k) { | |
printf("------------ start initialize ssl_con -----------\n"); | |
if(k->conn_initialized) { | |
printf("Error: already initialize the ssl connection.\n"); | |
return -1; | |
} | |
k->ssl = SSL_new(k->ctx); | |
if(k->ssl == NULL) { | |
printf("Error: cannot create the SSL object.\n"); | |
ERR_print_errors_fp(stderr); | |
return -2; | |
} | |
k->in = BIO_new(&krx_bio); | |
if(k->in == NULL) { | |
printf("Error: cannot create the in BIO.\n"); | |
SSL_free(k->ssl); | |
return -3; | |
} | |
k->out = BIO_new(&krx_bio); | |
if(k->out == NULL) { | |
BIO_free(k->in); | |
SSL_free(k->ssl); | |
return -4; | |
} | |
k->in->ptr = k; | |
k->out->ptr = k; | |
SSL_set_bio(k->ssl, k->in, k->out); | |
SSL_set_accept_state(k->ssl); /* set to accept state so it we act like we're a server */ | |
SSL_CTX_set_info_callback(k->ctx, krx_ssl_info_callback); | |
k->conn_initialized = true; | |
printf("------------ end initialize ssl_con -----------\n"); | |
return 0; | |
} | |
void krx_ssl_info_callback(const SSL* ssl, int where, int ret) { | |
if(ret == 0) { | |
printf("-- krx_ssl_info_callback: error occured.\n"); | |
return; | |
} | |
SSL_WHERE_INFO(ssl, where, SSL_CB_LOOP, "LOOP"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_EXIT, "EXIT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_READ, "READ"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_WRITE, "WRITE"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_ALERT, "ALERT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_READ_ALERT, "READ ALERT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_WRITE_ALERT, "WRITE ALERT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_ACCEPT_LOOP, "ACCEPT LOOP"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_ACCEPT_EXIT, "ACCEPT EXIT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_CONNECT_LOOP, "CONNECT LOOP"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_CONNECT_EXIT, "CONNECT EXIT"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START"); | |
SSL_WHERE_INFO(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE"); | |
} | |
int krx_ssl_encrypt(krx_ssl* k, uint8_t* out, int max, uint8_t* in, int len) { | |
if(k == NULL) { | |
printf("Error: `krx_ssl` in krx_ssl_encrypt is NULL.\n"); | |
return -1; | |
} | |
if(out == NULL) { | |
printf("Error: `out` in krx_ssl_encrypt is NULL.\n"); | |
return -2; | |
} | |
if(in == NULL) { | |
printf("Error: `in` in krx_ssl_encrypt is NULL.\n"); | |
return -3; | |
} | |
if(max < 0) { | |
printf("Error: `max` in krx_ssl_encrypt is < 0.\n"); | |
return -4; | |
} | |
if(len < 0) { | |
printf("Error: `len` in krx_ssl_encrypt is < 0.\n"); | |
return -5; | |
} | |
k->out_buf = out; | |
k->out_len = max; // not len? | |
k->out_pos = 0; | |
int r = SSL_write(k->ssl, in, len); | |
if(r < 0) { | |
printf("Error: cannot encrypt.\n"); | |
ERR_print_errors_fp(stderr); | |
return -6; | |
} | |
return r; | |
} | |
int krx_ssl_decrypt(krx_ssl* k, uint8_t* out, int max, uint8_t* in, int len) { | |
if(k == NULL) { | |
printf("Error: krx_ssl in krx_ssl_decrypt is NULL.\n"); | |
return -1; | |
} | |
if(in == NULL) { | |
printf("Error: `in` in krx_ssl_decrypt is NULL.\n"); | |
return -2; | |
} | |
if(out == NULL) { | |
printf("Error: `out` in krx_ssl_decrypt is NULL.\n"); | |
return -3; | |
} | |
if(len < 1) { | |
printf("Error: `len` in krx_ssl_decrypt < 0. \n"); | |
return -4; | |
} | |
if(max < 1) { | |
printf("Error: `max` in krx_ssl_decrypt < 0. \n"); | |
return -5; | |
} | |
printf("krx_ssl_decrypt, max: %d, len: %d\n", max, len); | |
k->in_buf = in; | |
k->in_len = len; | |
k->in_pos = 0; | |
int r = SSL_read(k->ssl, out, max); | |
if(r < 0) { | |
printf("Error: cannot decrypt.\n"); | |
ERR_print_errors_fp(stderr); | |
return -6; | |
} | |
return r; | |
} | |
int krx_ssl_verify(int ok, X509_STORE_CTX* ctx) { | |
printf("krx_ssl_verify: ok: %d\n", ok); | |
return 1; | |
} | |
// @todo(roxlu): implement | |
int krx_ssl_print_fingerprint(krx_ssl* k) { | |
uint8_t fp[4096] = { 0 } ; | |
uint8_t fp_string[4096] = { 0 }; | |
uint32_t fp_len = 4096; | |
int r = 0; | |
/* | |
ret = X509_digest(cert, EVP_sha256(), fingerprint, &fingerprint_len); | |
if (ret != 1) { | |
printke("X509_digest"); | |
exit(1); | |
} | |
for (i = 0; i < fingerprint_len; i++) { | |
if (i > 0) { | |
pos += snprintf(fingerprint_string + pos, TEST_SZ - pos, ":"); | |
} | |
pos += snprintf(fingerprint_string + pos, TEST_SZ - pos, "%02X", fingerprint[i]); | |
} | |
printk("%s", str); | |
printk("a=fingerprint:sha-256 %s", fingerprint_string); | |
*/ | |
return 0; | |
} | |
/* S R T P */ | |
/* -------------------------------------------------------------------------------- */ | |
int krx_init_srtp(krx_srtp* s) { | |
printf("Setting up srtp.\n"); | |
/* initialize */ | |
err_status_t err = err_status_ok; | |
err = srtp_init(); | |
if(err != err_status_ok) { | |
printf("error, code: %d\n", err); | |
return -1; | |
} | |
crypto_policy_set_rtp_default(&s->policy.rtp); | |
crypto_policy_set_rtcp_default(&s->policy.rtcp); | |
s->policy.ssrc.type = ssrc_any_inbound; | |
s->policy.key = calloc(1, KRX_SRTP_MASTER_LEN); // @todo(roxlu): make sure to free somewhere | |
s->policy.window_size = 128; | |
s->policy.allow_repeat_tx = 0; | |
s->policy.next = NULL; | |
if(s->policy.key == NULL) { | |
printf("Error: cannot allocate the policy key.\n"); | |
return -1; | |
} | |
return 0; | |
} | |
/* K R X _ D T L S */ | |
/* -------------------------------------------------------------------------------- */ | |
int krx_send_to_browser(krx_dtls_t* k, uint8_t* data, int len) { | |
printf("Must send something to browser: %d\n", len); | |
udp_conn* c = (udp_conn*)k->user; | |
return krx_udp_send(c, data, len); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment