void verifySignature(int sock,const byte *msg){ EVP_PKEY *skey = NULL, *vkey = NULL; int rc = make_keys(&skey, &vkey); assert(rc == 0); if(rc != 0) exit(1); assert(skey != NULL); if(skey == NULL) exit(1); assert(vkey != NULL); if(vkey == NULL) exit(1); byte* sig = NULL; size_t slen = 0; /* Using the skey or signing key */ rc = sign_it(msg, sizeof(msg), &sig, &slen, skey); assert(rc == 0); if(rc == 0) { printf("Created signature with length %d\n",(int)slen); } else { printf("Failed to create signature, return code %d\n", rc); exit(1); /* Should cleanup here */ } sendMsg(sock,"SendSignature"); while(strstr(recvMsg(sock),"SendSignature")==NULL){} sendMsg(sock,sig); byte* sig2 = NULL; sig2=recvMsg(sock); rc = verify_it(msg, sizeof(msg), sig2, sizeof(sig2), vkey); if(rc == 0) { printf("Verified signature. the length of sig is %d\n",(int)slen); } else { printf("length of recived signature is %d",(int)slen); printf("Failed to verify signature, return code %d\n", rc); } }
int main() { EVP_PKEY * priv_key = 0; EVP_PKEY * pub_key = 0; char * data = "Hello World"; int data_len = strlen(data); unsigned char * sig = 0; int sig_len = 0; gen_keys( "priv.pem", "pub.pem" ); priv_key = load_private_key( "priv.pem" ); pub_key = load_public_key2( "pub.pem" ); if (!priv_key || !pub_key) { printf("failed to load keys\n"); return 1; } sig = sign_it( priv_key, EVP_sha1(), data, data_len, &sig_len ); if (!sig) { printf("Failed to generate signature\n"); return 1; } if ( verify_sig( pub_key, EVP_sha1(), data, data_len, sig, sig_len ) ) printf("Signature matches!!\n"); else printf("*** SIG FAILED ***\n"); free(sig); EVP_PKEY_free (priv_key); EVP_PKEY_free (pub_key); return 0; }
int gs_pair(const char* address, const char* pin) { int ret = GS_OK; char url[4096]; unsigned char salt_data[16]; char salt_hex[33]; RAND_bytes(salt_data, 16); bytes_to_hex(salt_data, salt_hex, 16); sprintf(url, "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", address, g_UniqueId, salt_hex, g_CertHex); PHTTP_DATA data = http_create_data(); if (data == NULL) return GS_OUT_OF_MEMORY; else if ((ret = http_request(url, data)) != GS_OK) goto cleanup; unsigned char salt_pin[20]; unsigned char aes_key_hash[20]; AES_KEY enc_key, dec_key; memcpy(salt_pin, salt_data, 16); memcpy(salt_pin+16, pin, 4); SHA1(salt_pin, 20, aes_key_hash); AES_set_encrypt_key((unsigned char *)aes_key_hash, 128, &enc_key); AES_set_decrypt_key((unsigned char *)aes_key_hash, 128, &dec_key); unsigned char challenge_data[16]; unsigned char challenge_enc[16]; char challenge_hex[33]; RAND_bytes(challenge_data, 16); AES_encrypt(challenge_data, challenge_enc, &enc_key); bytes_to_hex(challenge_enc, challenge_hex, 16); sprintf(url, "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&clientchallenge=%s", address, g_UniqueId, challenge_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; char *result; if (xml_search(data->memory, data->size, "challengeresponse", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } unsigned char challenge_response_data_enc[48]; unsigned char challenge_response_data[48]; for (int count = 0; count < strlen(result); count += 2) { sscanf(&result[count], "%2hhx", &challenge_response_data_enc[count / 2]); } free(result); for (int i = 0; i < 48; i += 16) { AES_decrypt(&challenge_response_data_enc[i], &challenge_response_data[i], &dec_key); } unsigned char client_secret_data[16]; RAND_bytes(client_secret_data, 16); unsigned char challenge_response[16 + 256 + 16]; unsigned char challenge_response_hash[32]; unsigned char challenge_response_hash_enc[32]; char challenge_response_hex[65]; memcpy(challenge_response, challenge_response_data + 20, 16); memcpy(challenge_response + 16, g_Cert->signature->data, 256); memcpy(challenge_response + 16 + 256, client_secret_data, 16); SHA1(challenge_response, 16 + 256 + 16, challenge_response_hash); for (int i = 0; i < 32; i += 16) { AES_encrypt(&challenge_response_hash[i], &challenge_response_hash_enc[i], &enc_key); } bytes_to_hex(challenge_response_hash_enc, challenge_response_hex, 32); sprintf(url, "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&serverchallengeresp=%s", address, g_UniqueId, challenge_response_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; if (xml_search(data->memory, data->size, "pairingsecret", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } unsigned char *signature = NULL; size_t s_len; if (sign_it(client_secret_data, 16, &signature, &s_len, g_PrivateKey) != GS_OK) { gs_error = "Failed to sign data"; ret = GS_FAILED; goto cleanup; } unsigned char client_pairing_secret[16 + 256]; char client_pairing_secret_hex[(16 + 256) * 2 + 1]; memcpy(client_pairing_secret, client_secret_data, 16); memcpy(client_pairing_secret + 16, signature, 256); bytes_to_hex(client_pairing_secret, client_pairing_secret_hex, 16 + 256); sprintf(url, "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", address, g_UniqueId, client_pairing_secret_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; sprintf(url, "https://%s:47984/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=pairchallenge", address, g_UniqueId); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; cleanup: http_free_data(data); return ret; }
int gs_pair(PSERVER_DATA server, char* pin) { int ret = GS_OK; char url[4096]; uuid_t uuid; char uuid_str[37]; if (server->paired) { gs_error = "Already paired"; return GS_WRONG_STATE; } if (server->currentGame != 0) { gs_error = "The computer is currently in a game. You must close the game before pairing"; return GS_WRONG_STATE; } unsigned char salt_data[16]; char salt_hex[33]; RAND_bytes(salt_data, 16); bytes_to_hex(salt_data, salt_hex, 16); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", server->address, unique_id, uuid_str, salt_hex, cert_hex); PHTTP_DATA data = http_create_data(); if (data == NULL) return GS_OUT_OF_MEMORY; else if ((ret = http_request(url, data)) != GS_OK) goto cleanup; unsigned char salt_pin[20]; unsigned char aes_key_hash[20]; AES_KEY aes_key; memcpy(salt_pin, salt_data, 16); memcpy(salt_pin+16, salt_pin, 4); SHA1(salt_pin, 20, aes_key_hash); AES_set_encrypt_key((unsigned char *)aes_key_hash, 128, &aes_key); unsigned char challenge_data[16]; unsigned char challenge_enc[16]; char challenge_hex[33]; RAND_bytes(challenge_data, 16); AES_encrypt(challenge_data, challenge_enc, &aes_key); bytes_to_hex(challenge_enc, challenge_hex, 16); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientchallenge=%s", server->address, unique_id, uuid_str, challenge_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; char *result; if (xml_search(data->memory, data->size, "challengeresponse", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } char challenge_response_data_enc[48]; char challenge_response_data[48]; for (int count = 0; count < strlen(result); count++) { sscanf(&result[count], "%2hhx", &challenge_response_data_enc[count / 2]); } free(result); for (int i = 0; i < 48; i += 16) { AES_decrypt(&challenge_response_data_enc[i], &challenge_response_data[i], &aes_key); } char client_secret_data[16]; RAND_bytes(client_secret_data, 16); char challenge_response[16 + 256 + 16]; char challenge_response_hash[32]; char challenge_response_hash_enc[32]; char challenge_response_hex[33]; memcpy(challenge_response, challenge_response_data + 20, 16); memcpy(challenge_response + 16, cert->signature->data, 256); memcpy(challenge_response + 16 + 256, client_secret_data, 16); SHA1(challenge_response, 16 + 256 + 16, challenge_response_hash); for (int i = 0; i < 32; i += 16) { AES_encrypt(&challenge_response_hash[i], &challenge_response_hash_enc[i], &aes_key); } bytes_to_hex(challenge_response_hash_enc, challenge_response_hex, 32); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&serverchallengeresp=%s", server->address, unique_id, uuid_str, challenge_response_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; if (xml_search(data->memory, data->size, "pairingsecret", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } unsigned char *signature = NULL; size_t s_len; if (sign_it(client_secret_data, 16, &signature, &s_len, privateKey) != GS_OK) { gs_error = "Failed to sign data"; ret = GS_FAILED; goto cleanup; } char client_pairing_secret[16 + 256]; char client_pairing_secret_hex[(16 + 256) * 2 + 1]; memcpy(client_pairing_secret, client_secret_data, 16); memcpy(client_pairing_secret + 16, signature, 256); bytes_to_hex(client_pairing_secret, client_pairing_secret_hex, 16 + 256); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", server->address, unique_id, uuid_str, client_pairing_secret_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "https://%s:47984/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=pairchallenge", server->address, unique_id, uuid_str); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; server->paired = true; cleanup: http_free_data(data); return ret; }
int gs_pair(PSERVER_DATA server, char* pin) { int ret = GS_OK; char* result = NULL; char url[4096]; uuid_t uuid; char uuid_str[37]; if (server->paired) { gs_error = "Already paired"; return GS_WRONG_STATE; } if (server->currentGame != 0) { gs_error = "The computer is currently in a game. You must close the game before pairing"; return GS_WRONG_STATE; } unsigned char salt_data[16]; char salt_hex[33]; RAND_bytes(salt_data, 16); bytes_to_hex(salt_data, salt_hex, 16); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", server->address, unique_id, uuid_str, salt_hex, cert_hex); PHTTP_DATA data = http_create_data(); if (data == NULL) return GS_OUT_OF_MEMORY; else if ((ret = http_request(url, data)) != GS_OK) goto cleanup; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "plaincert", &result)) != GS_OK) goto cleanup; if (strlen(result)/2 > 8191) { gs_error = "Server certificate too big"; ret = GS_FAILED; goto cleanup; } char plaincert[8192]; for (int count = 0; count < strlen(result); count += 2) { sscanf(&result[count], "%2hhx", &plaincert[count / 2]); } plaincert[strlen(result)/2] = '\0'; printf("%d / %d\n", strlen(result)/2, strlen(plaincert)); unsigned char salt_pin[20]; unsigned char aes_key_hash[32]; AES_KEY enc_key, dec_key; memcpy(salt_pin, salt_data, 16); memcpy(salt_pin+16, pin, 4); int hash_length = server->serverMajorVersion >= 7 ? 32 : 20; if (server->serverMajorVersion >= 7) SHA256(salt_pin, 20, aes_key_hash); else SHA1(salt_pin, 20, aes_key_hash); AES_set_encrypt_key((unsigned char *)aes_key_hash, 128, &enc_key); AES_set_decrypt_key((unsigned char *)aes_key_hash, 128, &dec_key); unsigned char challenge_data[16]; unsigned char challenge_enc[16]; char challenge_hex[33]; RAND_bytes(challenge_data, 16); AES_encrypt(challenge_data, challenge_enc, &enc_key); bytes_to_hex(challenge_enc, challenge_hex, 16); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientchallenge=%s", server->address, unique_id, uuid_str, challenge_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } free(result); result = NULL; if (xml_search(data->memory, data->size, "challengeresponse", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } char challenge_response_data_enc[48]; char challenge_response_data[48]; for (int count = 0; count < strlen(result); count += 2) { sscanf(&result[count], "%2hhx", &challenge_response_data_enc[count / 2]); } for (int i = 0; i < 48; i += 16) { AES_decrypt(&challenge_response_data_enc[i], &challenge_response_data[i], &dec_key); } char client_secret_data[16]; RAND_bytes(client_secret_data, 16); char challenge_response[16 + 256 + 16]; char challenge_response_hash[32]; char challenge_response_hash_enc[32]; char challenge_response_hex[65]; memcpy(challenge_response, challenge_response_data + hash_length, 16); memcpy(challenge_response + 16, cert->signature->data, 256); memcpy(challenge_response + 16 + 256, client_secret_data, 16); if (server->serverMajorVersion >= 7) SHA256(challenge_response, 16 + 256 + 16, challenge_response_hash); else SHA1(challenge_response, 16 + 256 + 16, challenge_response_hash); for (int i = 0; i < 32; i += 16) { AES_encrypt(&challenge_response_hash[i], &challenge_response_hash_enc[i], &enc_key); } bytes_to_hex(challenge_response_hash_enc, challenge_response_hex, 32); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&serverchallengeresp=%s", server->address, unique_id, uuid_str, challenge_response_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } free(result); result = NULL; if (xml_search(data->memory, data->size, "pairingsecret", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } char pairing_secret[16 + 256]; for (int count = 0; count < strlen(result); count += 2) { sscanf(&result[count], "%2hhx", &pairing_secret[count / 2]); } if (!verifySignature(pairing_secret, 16, pairing_secret+16, 256, plaincert)) { gs_error = "MITM attack detected"; ret = GS_FAILED; goto cleanup; } unsigned char *signature = NULL; size_t s_len; if (sign_it(client_secret_data, 16, &signature, &s_len, privateKey) != GS_OK) { gs_error = "Failed to sign data"; ret = GS_FAILED; goto cleanup; } char client_pairing_secret[16 + 256]; char client_pairing_secret_hex[(16 + 256) * 2 + 1]; memcpy(client_pairing_secret, client_secret_data, 16); memcpy(client_pairing_secret + 16, signature, 256); bytes_to_hex(client_pairing_secret, client_pairing_secret_hex, 16 + 256); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", server->address, unique_id, uuid_str, client_pairing_secret_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "https://%s:47984/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=pairchallenge", server->address, unique_id, uuid_str); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } server->paired = true; cleanup: if (ret != GS_OK) gs_unpair(server); if (result != NULL) free(result); http_free_data(data); return ret; }