////////////////////////////////////////////////// // Bakalarska praca // // Meno studenta: Tomas Lukac // // Veduci BP: prof. Ing. Milos Drutarovsky CSc. // // Skola: KEMT FEI TUKE // // Datum poslednej upravy: 15.4.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" #include "../../kniznica/rs232.h" #define RSA_VELKOST 2048 #define ECC_VELKOST 32 #define RSA_EXPONENT 65537 //cesty ku suborom #define RSA_KLUC "../../certifikaty/klient/klient_rsa.key" #define RSA_CERTIFIKAT "../../certifikaty/klient/klient_rsa.pem" #define ECC_KLUC "../../certifikaty/klient/klient_ecc.key" #define ECC_CERTIFIKAT "../../certifikaty/klient/klient_ecc.pem" #define VYGENEROVANY_KLUC "../../certifikaty/klient/vygenerovany_kluc.key" #define VYGENEROVANY_CERTIFIKAT "../../certifikaty/klient/vygenerovany_certifikat.pem" #define KOMUNIKACNY_SUBOR "klient.txt" int rs232_prijat; int cislo_rozhrania = 0; int aktualne_data = 0; int rs232_citanie(WOLFSSL *ssl, char *buf, int sz, void *ctx) { int uspech = 0; int prebieha_nacitanie = 0; int prebieha_nacitanie_velkosti_spravy = 0; unsigned char znak; //ziskanie dat zo serioveho rozhrania if(aktualne_data == 0) { //otvorenie suboru do ktoreho sa zapisuju prijate binarne data //ktore sa nasledne nacitaju do buffera (buf) pre desifrovanie FILE* f = fopen(KOMUNIKACNY_SUBOR, "ab+"); //mnozstvo nacitanych dat int nacitane_data = 0; //velkost spravy, ktora sa bude prijmat int velkost_spravy = 0; //urcuje kolko bajtov z informacie o velkosti spravy //uz bolo prijatych z celkoveho poctu (4) int velkost_spravy_bajt = 0; int velkost_spravy_pocet_bajtov = 4; //kontrolne vzory, ktore jednoznacne identifikuju zaciatok a koniec spravy unsigned char zaciatok_spravy[] = {0xAA, 0xAA, 0xAA, 0xAA}; int zaciatok_spravy_pozicia = 0; //aktualna pozicia v kontrolnom vzore unsigned char koniec_spravy[] = {0xBB, 0xBB, 0xBB, 0xBB}; int koniec_spravy_pozicia = 0; //aktualna pozicia v kontrolnom vzore int velkost_kontrolneho_vzoru = sizeof(zaciatok_spravy)/sizeof(zaciatok_spravy[0]); while(1) { uspech = RS232_PollComport(cislo_rozhrania, &znak, 1); if(uspech > 0) { //ak nacitanie spravy este nezacalo, ale bol najdeny bajt, ktory je sucastou kontrolneho vzoru, //ktory urcuje zaciatok spravy, posun sa v kontrolnom vzore o jednu poziciu a cakaj ci nebudu //prichadzat dalsie bajty z tohto kontrolneho vzoru if(!prebieha_nacitanie && (znak == zaciatok_spravy[zaciatok_spravy_pozicia]) && (zaciatok_spravy_pozicia < velkost_kontrolneho_vzoru - 1)) { zaciatok_spravy_pozicia++; } //ak prebehlo nacitanie vsetkych bajtov, ktore su sucastou kontrolneho vzoru urcujuceho zaciatok spravy //ocakavaj prichod bajtov, ktore budu niest informaciu o velkosti spravy else if(!prebieha_nacitanie && (znak == zaciatok_spravy[zaciatok_spravy_pozicia]) && (zaciatok_spravy_pozicia == velkost_kontrolneho_vzoru - 1)) { prebieha_nacitanie_velkosti_spravy = 1; zaciatok_spravy_pozicia = 0; } //pokracuj v nacitavani bajtov urcujucich velkost spravy, dokym nie su vsetky nacitane //a po nacitani vsetkych bajtov moze zacat nacitanie spravy else if(!prebieha_nacitanie && prebieha_nacitanie_velkosti_spravy) { velkost_spravy_bajt++; if(velkost_spravy_bajt == velkost_spravy_pocet_bajtov) { prebieha_nacitanie = 1; prebieha_nacitanie_velkosti_spravy = 0; } } //ak prebieha nacitanie a bol najdeny bajt, ktory je sucastou kontrolneho vzoru, ktory urcuje koniec spravy, //posun sa v kontrolnom vzore o jednu poziciu a cakaj ci nebudu prichadzat dalsie bajty z tohto kontrolneho vzoru else if((prebieha_nacitanie && (znak == koniec_spravy[koniec_spravy_pozicia]) && (koniec_spravy_pozicia == 0)) || (!prebieha_nacitanie && (znak == koniec_spravy[koniec_spravy_pozicia]) && (koniec_spravy_pozicia < velkost_kontrolneho_vzoru - 1))) { koniec_spravy_pozicia++; prebieha_nacitanie = 0; } //v pripade ak zacalo nacitanie kontrolneho vzoru, ktory urcuje koniec spravy, ale nebol najdeny posledny znak z tohto vzoru //nacitaj do suboru docasne nezapisane znaky, ktore su sucastou kontrolneho vzoru a zaroven nacitaj aktualny znak else if(!prebieha_nacitanie_velkosti_spravy && !prebieha_nacitanie && znak != koniec_spravy[koniec_spravy_pozicia]) { for(int i = 0; i < koniec_spravy_pozicia; i++) { fwrite((char*)&koniec_spravy[i], 1, uspech, f); nacitane_data += uspech; } fwrite((char*)&znak, 1, uspech, f); nacitane_data += uspech; koniec_spravy_pozicia = 0; prebieha_nacitanie = 1; } //ak prebehlo nacitanie vsetkych bajtov, ktore su sucastou kontrolneho vzoru urcujuceho koniec spravy //ukonci nacitanie spravy else if(!prebieha_nacitanie_velkosti_spravy && !prebieha_nacitanie && (znak == koniec_spravy[0]) && (koniec_spravy_pozicia == 3)) { prebieha_nacitanie = 0; koniec_spravy_pozicia = 0; break; } //inak prebieha nacitanie, cize zapis aktualny znak (bajt) do suboru else { if(prebieha_nacitanie && !prebieha_nacitanie_velkosti_spravy) { fwrite((char*)&znak, 1, uspech, f); nacitane_data += uspech; } } } } aktualne_data = nacitane_data; nacitane_data = 0; fclose(f); } //nacitanie dat zo suboru do buffera pre desifrovanie uspech = 0; while(uspech <= 0) uspech = read(rs232_prijat, buf, sz); aktualne_data -= uspech; return uspech; } int rs232_zapis(WOLFSSL *ssl, char *buf, int sz, void *ctx) { int uspech = 0; //kontrolne vzory, ktore jednoznacne identifikuju zaciatok a koniec spravy unsigned char zaciatok_spravy[] = {0xAA, 0xAA, 0xAA, 0xAA}; unsigned char koniec_spravy[] = {0xBB, 0xBB, 0xBB, 0xBB}; //vytvorenie bajtov ktore budu niest informaciu o velkosti posielanej spravy unsigned char* velkost_spravy = calloc(4, sizeof(unsigned char)); velkost_spravy[0] = (sz >> 24) & 0xFF; velkost_spravy[1] = (sz >> 16) & 0xFF; velkost_spravy[2] = (sz >> 8) & 0xFF; velkost_spravy[3] = sz & 0xFF; //odoslanie kontrolnych vzorov, bajtov s velkostou spravy a samotnych dat na seriove rozhranie RS232_SendBuf(cislo_rozhrania, (unsigned char*)zaciatok_spravy, sizeof(zaciatok_spravy)); RS232_SendBuf(cislo_rozhrania, (unsigned char*)velkost_spravy, 4); uspech = (int)RS232_SendBuf(cislo_rozhrania, (unsigned char*)buf, sz); RS232_SendBuf(cislo_rozhrania, (unsigned char*)koniec_spravy, sizeof(koniec_spravy)); free(velkost_spravy); return uspech; } int main(int argc, char const *argv[]) { char rezim[]={'8','N','1', 0}; int rychlost = 9600; WOLFSSL *ssl; WOLFSSL_CTX *ctx = NULL; const char* subor = NULL; int zadane_rozhranie = 0; int uvedeny_subor = 0; int nacitanie_zo_suboru = 0; int generovanie_certifikatu = 0; nastavenia_aplikacie nastavenia; RS232_flushRXTX(cislo_rozhrania); rs232_prijat = open(KOMUNIKACNY_SUBOR, O_RDWR | O_NOCTTY | O_NDELAY); int uspech; if((ctx = nastavit_ctx_klient()) == NULL) { return -1; } else { for(int i = 0; i < argc; i++) { if( (!strcmp(argv[i], "-s")) ) { uvedeny_subor = 1; if((argv[i+1] == NULL) ) { printf("Nezadali ste cestu ku suboru\n"); return -1; } else { subor = argv[i+1]; } } 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_OpenComport(cislo_rozhrania, rychlost, rezim, 1)) { fprintf(stderr, "Nebolo mozne otvorit seriove rozhranie\n"); return -1; } } } else if( (!strcmp(argv[i], "-n")) ) { 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")) { wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); if(nacitat_certifikaty(ctx, RSA_CERTIFIKAT, RSA_KLUC) == -1) return -1; wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); } else if(!strcmp(argv[i+1], "ecc")) { wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); if(nacitat_certifikaty(ctx, ECC_CERTIFIKAT, ECC_KLUC) == -1) return -1; wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); } else { printf("Zadali ste nespravny typ certifikatu\n"); return -1; } } else if( (!strcmp(argv[i], "-g")) ) { 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")) { wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); if(generovat_rsa_certifikat(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; wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); } else if(!strcmp(argv[i+1], "ecc")) { wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); if(generovat_ecc_certifikat(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; wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); } else { printf("Zadali ste nespravny typ certifikatu\n"); return -1; } } } } 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; } else if(!uvedeny_subor) { fprintf(stderr, "Nebola uvedena cesta ku suboru na odoslanie\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, rs232_prijat); wolfSSL_set_using_nonblock(ssl, rs232_prijat); //pokus o inizicalizaciu TLS handshaku so serverom uspech = wolfSSL_connect(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"); free(popis_chyby); return -1; } zobraz_sifru(ssl); zobraz_certifikat(ssl); nastav_funkciu(&nastavenia, "crc", ziadna); poslat_subor(ssl, ctx, subor, &nastavenia); //ukoncenie spojenia, vymazanie komunikacneho suboru //a vycistenie serioveho buffera ukoncit_spojenie(ssl, ctx); RS232_flushRXTX(cislo_rozhrania); RS232_CloseComport(cislo_rozhrania); close(rs232_prijat); fclose(fopen(KOMUNIKACNY_SUBOR, "wb")); return 0; }