////////////////////////////////////////////////// // Bakalarska praca // // Meno studenta: Tomas Lukac // // Veduci BP: prof. Ing. Milos Drutarovsky CSc. // // Skola: KEMT FEI TUKE // // Datum poslednej upravy: 5.6.2020 // ////////////////////////////////////////////////// #include #include #include #include #include #include #ifdef _WIN32 #include #include #include #define O_NOCTTY 0x8000 #define O_NDELAY 0x4000 #else #include #endif #include "../../kniznica/kryptografia.h" #include "../../kniznica/komunikacia.h" #define RSA_VELKOST 2048 #define ECC_VELKOST 32 #define RSA_EXPONENT 65537 //cesty ku suborom #define RSA_KLUC "../../certifikaty/server/server_rsa.key" #define RSA_CERTIFIKAT "../../certifikaty/server/server_rsa.pem" #define ECC_KLUC "../../certifikaty/server/server_ecc.key" #define ECC_CERTIFIKAT "../../certifikaty/server/server_ecc.pem" #define VYGENEROVANY_KLUC "../../certifikaty/server/vygenerovany_kluc.key" #define VYGENEROVANY_CERTIFIKAT "../../certifikaty/server/vygenerovany_certifikat.pem" #define KOMUNIKACNY_SUBOR "server.txt" //subor do ktoreho sa zapisuje komunikacia int k_subor; int cislo_rozhrania = 0; //velkost dat ktore sa prave nachadzaju v seriovom bufferi //a cakaju na nacitanie do buffera pre desifrovanie int aktualne_data = 0; //mnozstvo dat ktore boli nacitane do buffera pre desifrovanie //pri zavolani funkcie rs232_citanie() int nacitane_data = 0; int rs232_citanie(WOLFSSL *ssl, char *buf, int sz, void *ctx) { //ziskanie dat zo serioveho rozhrania if(aktualne_data == 0) { aktualne_data = rs232_prijat_spravu(cislo_rozhrania, KOMUNIKACNY_SUBOR); if(aktualne_data <= 0) { fprintf(stderr, "Nastala chyba pri prijati spravy\n"); return -1; } } //nacitanie dat zo suboru do buffera pre desifrovanie nacitane_data = 0; while(nacitane_data <= 0) nacitane_data = read(k_subor, buf, sz); aktualne_data -= nacitane_data; return nacitane_data; } int rs232_zapis(WOLFSSL *ssl, char *buf, int sz, void *ctx) { int uspech = 0; int odoslane_data = 0; //poslanie dat na seriove rozhranie odoslane_data = rs232_odoslat_spravu(cislo_rozhrania, buf, sz); if(odoslane_data <= 0) { fprintf(stderr, "Nastala chyba pri posielani dat\n"); return -1; } return odoslane_data; } int main(int argc, char const *argv[]) { //nastavenie rezimu rezhrania //8 -> pocet bitov, N -> no parity, 1 -> jeden stopbit char rezim[]={'8','N','1', 0}; //nastavenie rychlosti rozhrania v baudoch int rychlost = 128000; WOLFSSL *ssl; WOLFSSL_CTX *ctx = NULL; int autentizacia = 0; int zadane_rozhranie = 0; int generovanie_certifikatu = 0; int nacitanie_zo_suboru = 0; nastavenia_aplikacie nastavenia; k_subor = open(KOMUNIKACNY_SUBOR, O_RDWR | O_NOCTTY | O_NDELAY); int uspech; if((ctx = nastavit_ctx_server()) == NULL) { return -1; } else { printf("---------------\n| Certifikaty |\n---------------\n"); for(int i = 0; i < argc; i++) { if( (!strcmp(argv[i], "-port")) ) { zadane_rozhranie = 1; if((argv[i+1] == NULL)) { printf("Nezadali ste cislo serioveho rozhrania\n"); return -1; } else { cislo_rozhrania = atoi(argv[i+1]); if(rs232_otvorit_rozhranie(cislo_rozhrania, rychlost, rezim, 1)) { return -1; } } } else if( (!strcmp(argv[i], "-cert-aut")) ) { if((argv[i+1] == NULL) || (i == argc-1)) { printf("Nezadali ste typ certifikatu autority ktory chcete nacitat\n"); return -1; } else if(!strcmp(argv[i+1], "rsa")) { wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); autentizacia = 1; } else if(!strcmp(argv[i+1], "ecc")) { wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); autentizacia = 1; } else { printf("Zadali ste nespravny typ certifikatu\n"); return -1; } } else if( (!strcmp(argv[i], "-cert")) ) { nacitanie_zo_suboru = 1; if(generovanie_certifikatu) { fprintf(stderr, "Nie je mozne zvolit obidve metody nacitania certifikatov naraz\n"); return -1; } if((argv[i+1] == NULL) || (i == argc-1)) { printf("Nezadali ste typ certifikatu ktory chcete nacitat zo suboru\n"); return -1; } else if(!strcmp(argv[i+1], "rsa")) { if(nacitat_certifikaty(ctx, RSA_CERTIFIKAT, RSA_KLUC) == -1) return -1; } else if(!strcmp(argv[i+1], "ecc")) { if(nacitat_certifikaty(ctx, ECC_CERTIFIKAT, ECC_KLUC) == -1) return -1; } else { printf("Zadali ste nespravny typ certifikatu\n"); return -1; } } else if( (!strcmp(argv[i], "-cert-gen")) ) { generovanie_certifikatu = 1; if(nacitanie_zo_suboru) { fprintf(stderr, "Nie je mozne zvolit obidve metody nacitania certifikatov naraz\n"); return -1; } if((argv[i+1] == NULL) || (i == argc-1)) { printf("Nezadali ste typ certifikatu ktory chcete vygenerovat\n"); return -1; } else if(!strcmp(argv[i+1], "rsa")) { if(generovat_rsa_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; } else if(!strcmp(argv[i+1], "ecc")) { if(generovat_ecc_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; } else { printf("Zadali ste nespravny typ certifikatu\n"); return -1; } } } } //vypis upozornenia o autentizacii if(!autentizacia) { printf("Nebol nacitany certifikat autority, takze nebude vykonana autentizacia druhej strany\n"); } if(!zadane_rozhranie) { fprintf(stderr, "Nebol urcene seriove rozhranie\n"); return -1; } else if(!generovanie_certifikatu && !nacitanie_zo_suboru) { fprintf(stderr, "Nebola zvolena metoda nacitania certifikatov\n"); printf("Zadajde prepinac -g (generovanie), alebo -n (nacitanie_zo_suboru) s parametrom rsa alebo ecc\n"); return -1; } //nastav_sifry(ctx, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); //nastavenie vlastnych I/O funkcii wolfSSL_SetIOSend(ctx, rs232_zapis); wolfSSL_SetIORecv(ctx, rs232_citanie); //pokus o vytvorenie novej wolfSSL relacie if ((ssl = wolfSSL_new(ctx)) == NULL) { printf("Nepodarilo sa vytvorit ssl relaciu\n"); wolfSSL_CTX_free(ctx); return -1; } //priradenie file descriptora suboru ako I/O pre TLS spojenie wolfSSL_set_fd(ssl, k_subor); wolfSSL_set_using_nonblock(ssl, k_subor); //cakanie na inicializaciu TLS handshaku klientom printf("-----------------\n| TLS Handshake |\n-----------------\n"); printf("Inicializacia TLS spojenia\n"); uspech = wolfSSL_accept(ssl); if(uspech != SSL_SUCCESS) { char* popis_chyby = calloc(100, sizeof(char)); int chyba = wolfSSL_get_error(ssl, 0); wolfSSL_ERR_error_string(chyba, popis_chyby); fprintf(stderr, "Nastala chyba v spojeni.\nCislo chyby: %d\nDovod chyby: %s\n", chyba, popis_chyby); printf("Skontrolujte certifikaty.\n"); fclose(fopen(KOMUNIKACNY_SUBOR, "wb")); free(popis_chyby); return -1; } printf("Podarilo sa vytvorit TLS spojenie\n"); zobraz_sifru(ssl); printf("----------------------------\n| Informacie o certifikate |\n----------------------------\n"); zobraz_certifikat(ssl); //nastavenie funkcie pre vypocet kontrolneho suctu //nastavime typ "crc" alebo "hash" a nazov funkcie, nazov druhej funkcie nastavime na NULL nastav_funkciu(&nastavenia, "crc", (hashovacia_funkcia)NULL, funkcia_CRC32); //vypocet casu prenosu suboru printf("-------------------\n| Prijatie suboru |\n-------------------\n"); clock_t cas; cas = clock(); if(prijat_subor(ssl, ctx, &nastavenia, 4096) == -1) return -1; cas = clock() - cas; printf("Cas prenosu suboru: %f sekund\n", (double)cas/CLOCKS_PER_SEC); printf("----------------------\n| Ukoncenie spojenia |\n----------------------\n"); //ukoncenie spojenia, vymazanie komunikacneho suboru //a vycistenie serioveho buffera ukoncit_spojenie(ssl, ctx); rs232_zatvorit_rozhranie(cislo_rozhrania); close(k_subor); fclose(fopen(KOMUNIKACNY_SUBOR, "wb")); return 0; }