int send_message(std::string & type, std::string data, std::string&response_type, std::string& response_message, int sock, keyinfo & conn_info){ //Construct message std::string message(type); if (type.length() != 0) { message.append("|"); message.append(data); } //Send it and get response std::string response; int err = send_nonce(message, response, sock, conn_info); if (err != 0) { return err; } size_t sep_pos = response.find('|'); if (sep_pos == response.npos ){ return -1; } response_type = response.substr(0, sep_pos); response_message = response.substr(sep_pos+1, response.length() - sep_pos); return 0; }
int main (int argc, char *argv[]){ int sock, newsock; struct sockaddr_storage client_addr; socklen_t sin_size; char s[INET6_ADDRSTRLEN]; RSA *decrypt, *sign; decrypt = NULL; sign = NULL; int retval = SIBYL_SUCCESS; char *dir = NULL; char *ip = NULL; char *port = NULL; char *decr_namefile = NULL; char *sign_namefile = NULL; dir = (char *)calloc(_POSIX_PATH_MAX + 1, sizeof(char)); ip = (char *)calloc(17 + 1, sizeof(char)); port = (char *)calloc(10, sizeof(char)); decr_namefile = (char *)calloc(_POSIX_PATH_MAX + 1, sizeof(char)); sign_namefile = (char *)calloc(_POSIX_PATH_MAX + 1, sizeof(char)); if(dir == NULL || ip == NULL || port == NULL || decr_namefile == NULL || sign_namefile == NULL){ D("Malloc"); retval = SIBYL_OSERR; goto FREE; } strncpy(dir, SIBYL_DIR, _POSIX_PATH_MAX); strncpy(port, SIBYL_PORT, 9); strncpy(decr_namefile, SIBYL_DECR_KEY, _POSIX_PATH_MAX); strncpy(sign_namefile, SIBYL_SIGN_KEY, _POSIX_PATH_MAX); /* Read options */ int c; while((c = getopt(argc, argv, SIBYL_SRV_OPTS)) != -1){ if(optarg == NULL) c = 'h'; switch(c){ case 'd': strncpy(decr_namefile, optarg, _POSIX_PATH_MAX); break; case 's': strncpy(sign_namefile, optarg, _POSIX_PATH_MAX); break; case 'p': strncpy(port, optarg, 9); break; case 'i': strncpy(ip, optarg, _POSIX_PATH_MAX); break; case 'D': strncpy(dir, optarg, _POSIX_PATH_MAX); break; case 'h': default: printf("Usage: %s -d decrypt -s sign -i IP -p port -D dir\n" " -d decrypt: decrypt private key (default: decrypt)\n" " -s sign: sign private key (default: sign)\n" " -i IP: IP where the server will listen (default: localhost)\n" " -p port: port where the server will listen (default: 9999)\n" " -D dir: directory where the private keys are stored " "(default: /etc/sibyl)\n" " -h: shows this help text\n", argv[0]); exit(1); } } /* Read private keys */ retval = read_keys(&decrypt, decr_namefile, &sign, sign_namefile, dir); if(retval != SIBYL_SUCCESS) goto FREE; D("Private keys read"); /* Start server */ retval = start_server(&sock, ip, port); if(retval != SIBYL_SUCCESS){ goto FREE; } D("Server started\n"); while(1){ /* Accept connection */ sin_size = sizeof client_addr; newsock = accept(sock, (struct sockaddr *)&client_addr, &sin_size); if (newsock == -1){ perror("server: accept"); continue; } inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof(s)); D1("server: got connection from %s\n", s); if (!fork()){ // child process close(sock); // child doesn't need the listener char *strnonce = NULL; char *msg = NULL; char command = 0; char *token[3] = {NULL,NULL,NULL}; char *p1_data = NULL; char *p2_data = NULL; char *auth_result = NULL; /* Send the nonce */ strnonce = (char *) calloc(32, sizeof(char)); if (strnonce == NULL){ D("Malloc"); retval = SIBYL_OSERR; goto ENDCHILD; } retval = send_nonce(newsock, strnonce); if (retval != SIBYL_SUCCESS){ goto ENDCHILD; } /* Receive the client's message and parse it */ msg = (char *) calloc(SIBYL_MAX_MSG, sizeof(char)); if(msg == NULL){ D("Malloc"); retval = SIBYL_OSERR; goto ENDCHILD; } retval = receive_msg(msg, newsock, &command, token); if (retval != SIBYL_SUCCESS){ goto ENDCHILD; } D1("Received: [%s]\n", msg); D1("command: [%c]\n", command); D1("m : %s\n", token[0]); D1("p1 : %s\n", token[1]); D1("p2 : %s\n", token[2]); /* * Now there are several actions depending on the command * which is stored in command. */ /* Just send the public keys */ if(command == '-'){ retval = send_public_keys(dir, decr_namefile, sign_namefile, newsock); goto ENDCHILD; } /* Any other command requires decryption of p1 */ /* Decrypt p1 (p1 = token[1]) */ /* p1_data always includes a trailing 0 */ p1_data = (char *)calloc(RSA_size(decrypt) + 1, sizeof(u_char)); if(p1_data == NULL){ D("Malloc strnonce"); retval = SIBYL_OSERR; goto ENDCHILD; } D1("token[1]:{%s}\n", token[1]); /* this is path */ char *resp = (char *)calloc(SIBYL_MAX_MSG, sizeof(u_char)); memcpy(resp, token[1], strlen(token[1])); retval = decrypt_token(p1_data, command, resp, decrypt); if (retval != SIBYL_SUCCESS){ printf("Decryption error\n"); goto ENDCHILD; } D1("p1_data: %s\n", p1_data); /* * If command != \000 then it is '0' <= command <='9' * and translation is asked for. */ D1("token[0]:{%s}\n", token[0]); if(command != 0){ if(strncmp(strnonce, token[0], strlen(strnonce))){ D("Wrong nonce"); retval = SIBYL_NONCE_ERROR; goto ENDCHILD; } retval = translate_and_send(p1_data, command, decr_namefile, dir, newsock, sign); goto ENDCHILD; } /* * Decrypt p2 (p2 = token[2]): * only if command == verify */ p2_data = (char *)calloc(RSA_size(decrypt) + 1, sizeof(u_char)); if(p2_data == NULL){ perror("Unable to allocate memory for p2_data"); retval = SIBYL_OSERR; goto ENDCHILD; } retval = decrypt_token(p2_data, command, token[2], decrypt); if (retval != SIBYL_SUCCESS){ goto ENDCHILD; } D1("p2_data: %s\n", p2_data); /* Is the password correct */ auth_result = calloc(1, sizeof(char)); if(auth_result == NULL){ D("Unable to allocate memory for auth_result"); retval = SIBYL_OSERR; goto ENDCHILD; } retval = is_pwd_ok(p1_data, p2_data, auth_result, strnonce); if (retval != SIBYL_SUCCESS){ goto ENDCHILD; } /* Send the response to the client */ retval = send_response(&newsock, token, auth_result, sign); if (retval != SIBYL_SUCCESS){ goto ENDCHILD; } ENDCHILD: free(strnonce); free(msg); free(p1_data); free(p2_data); free(auth_result); /* Close socket */ close(newsock); retval = SIBYL_SUCCESS; goto FREE; } close(newsock); // parent doesn't need this } FREE: RSA_free(decrypt); RSA_free(sign); free(dir); free(ip); free(port); free(decr_namefile); free(sign_namefile); exit(retval); }
void symbolic_attacker(int attacker_id, struct keypair* keypair) /*@ requires [?f]world(?pub, ?key_clsfy) &*& true == bad(attacker_id) &*& principal(attacker_id, ?count) &*& keypair(keypair, attacker_id, ?id, ?info, pub); @*/ //@ ensures false; { //@ retreive_proof_obligations(); for (;;) /*@ invariant [f]world(pub, key_clsfy) &*& proof_obligations(pub) &*& principal(attacker_id, _) &*& keypair(keypair, attacker_id, id, info, pub); @*/ { struct network_status *net_stat = 0; int net_choise = random_int_(); int port = random_int_(); if (net_choise % 2 == 0) net_stat = network_bind_and_accept(port % 65536); else net_stat = network_connect("localhost", port % 65536); { int action = random_int_(); int *counter; switch (action % 13) { case 0: //@ open [f]world(pub, key_clsfy); //@ assert [_]is_key_classifier(_, pub, key_clsfy); //@ retreive_public_invariant_constraints(key_clsfy); //@ duplicate_lemma_function_pointer_chunk(key_classifier); /*@ { lemma void public_key_classifier(cryptogram key, int p, int c, bool symmetric) requires polarssl_proof_pred(pub, key_clsfy)() &*& [_]polarssl_pub(pub)(key) &*& symmetric ? key == cg_symmetric_key(p, c) : key == cg_private_key(p, c); ensures polarssl_proof_pred(pub, key_clsfy)() &*& col || true == key_clsfy(p, c, symmetric); { open [_]polarssl_pub(pub)(key); item k; if (symmetric) k = symmetric_key_item(p, c); else k = private_key_item(p, c); open polarssl_proof_pred(pub, key_clsfy)(); assert is_key_classifier(?proof, pub, key_clsfy); proof(k, p, c, symmetric); close polarssl_proof_pred(pub, key_clsfy)(); } produce_lemma_function_pointer_chunk(public_key_classifier) : public_key_classifier(polarssl_pub(pub), key_clsfy, polarssl_proof_pred(pub, key_clsfy)) (key__, p__, c__, sym__) { call(); } {duplicate_lemma_function_pointer_chunk(public_key_classifier);}; } @*/ //@ close polarssl_proof_pred(pub, key_clsfy)(); attacker(); //@ open polarssl_proof_pred(pub, key_clsfy)(); //@ close [f]world(pub, key_clsfy); //@ leak public_invariant_constraints(_, _); //@ leak is_public_key_classifier(_, _, _, _); //@ leak is_key_classifier(_, _, _); break; case 1: // Anyone can publish arbitrary data items... send_data(net_stat); break; case 2: // Anyone can create pairs of public items... send_pair_composed(net_stat); break; case 3: // Anyone can deconstruct a public pair... send_pair_decomposed(net_stat); break; case 4: // Bad principals can publish generated nonce items... send_nonce(net_stat); break; case 5: // Bad principals can increment public nonces... increment_and_send_nonce(net_stat); break; case 6: // Bad principals can leak their keys... send_keys(net_stat, keypair); break; case 7: // Anyone can hmac public payload with public key send_hmac(net_stat, keypair); break; case 8: // Anyone can symmteric encrypt public payload with public key send_symmetric_encrypted(net_stat, keypair); break; case 9: // Anyone can symmteric decrypt message with public key send_symmetric_decrypted(net_stat, keypair); break; case 10: // Anyone can asymmteric encrypt public payload with public key send_asymmetric_encrypted(net_stat, keypair); break; case 11: // Anyone can asymmteric decrypt message with public key send_asymmetric_decrypted(net_stat, keypair); break; case 12: // Anyone can asymmteric sign public payload with public key send_asymmetric_signature(net_stat, keypair); } } network_disconnect(net_stat); } //@ leak proof_obligations(pub); }