/* * Certificate info: * - id: requester identification * - cname: common name * - time: date on which the certificate has been generated * - valid: date up to the certificate is valid * - auth_key: key used in mutual authentication (SMQV) * - token_key: key used to sign access token (MSS) * - signature: signature under issuer's key * */ void generate_certificate(const unsigned char csr[CSR_MAX_SIZE], const char valid[TIME_BUFFER_SIZE], const unsigned char ca_skey[ECDSA_SKEY_SIZE], unsigned char certificate[CERTIFICATE_MAX_SIZE]) { unsigned int id; char cname[CNAME_MAX_SIZE], time[TIME_BUFFER_SIZE]; unsigned char auth_key[SMQV_PKEY_SIZE], token_key[MSS_PKEY_SIZE], cert_signature[ECDSA_SIGNATURE_SIZE], csr_signature[MSS_SIGNATURE_SIZE]; unsigned char buffer[CERTIFICATE_MAX_SIZE]; memset(buffer, 0, CERTIFICATE_MAX_SIZE); now(&time); if(compare_dates(valid, time) == -1 && read_csr(&id, cname, time, auth_key, token_key, csr_signature, csr)) { unsigned int index = 0; index += cert_append_info(buffer, id, cname, time, valid, auth_key, token_key); unsigned char cert_digest[2 * MSS_SEC_LVL]; sponge_hash(buffer, index, cert_digest, 2 * MSS_SEC_LVL); ecdsa_sign(ca_skey, cert_digest, cert_signature); memcpy(buffer + index, cert_signature, ECDSA_SIGNATURE_SIZE); index += ECDSA_SIGNATURE_SIZE; base64encode(buffer, index, certificate, CSR_MAX_SIZE); } else{ certificate[0] = '\0'; if( compare_dates(valid, time) != -1) printf("Authentication ERROR: !(valid > t_now)\n"); else printf("Authentication ERROR: !mss_verify\n"); } }
// read and verify whether the csr's signature is valid. Returns 1 if it is, otherwise 0. unsigned char read_csr(unsigned int *id, char *cname, char time[TIME_BUFFER_SIZE], unsigned char auth_key[SMQV_PKEY_SIZE], unsigned char token_key[MSS_PKEY_SIZE], unsigned char csr_signature[MSS_SIGNATURE_SIZE], char csr[CSR_MAX_SIZE]) { unsigned int index = 0; int csr_size = CSR_MAX_SIZE; unsigned char buffer[CSR_MAX_SIZE]; memset(buffer, 0, CSR_MAX_SIZE); char t_now[TIME_BUFFER_SIZE]; now(&t_now); base64decode(csr, strlen(csr), buffer, &csr_size); csr_split_info(buffer, id, cname, time, auth_key, token_key, csr_signature); unsigned char digest[2 * MSS_SEC_LVL]; index = csr_append_info(buffer, *id, cname, time, auth_key, token_key); sponge_hash(buffer, index, digest, 2 * MSS_SEC_LVL); // verify [(id || cname || time || auth_key || token_key), csr_signature, token_key] return mss_verify(csr_signature, token_key, digest) && compare_dates(time, t_now) != -1; }
// return 1 if certificate is valid, 0 otherwise unsigned char read_certificate(unsigned int *id, char *cname, char time[TIME_BUFFER_SIZE], char valid[TIME_BUFFER_SIZE], unsigned char auth_key[SMQV_PKEY_SIZE], unsigned char token_key[MSS_PKEY_SIZE], unsigned char cert_signature[ECDSA_SIGNATURE_SIZE], const unsigned char ca_pkey[ECDSA_PKEY_SIZE], const unsigned char certificate[CERTIFICATE_MAX_SIZE]) { unsigned int index = 0; int certificate_size = CERTIFICATE_MAX_SIZE; unsigned char buffer[CERTIFICATE_MAX_SIZE]; char t_now[TIME_BUFFER_SIZE]; now(&t_now); memset(buffer, 0, CERTIFICATE_MAX_SIZE); base64decode(certificate, strlen(certificate), buffer, &certificate_size); cert_split_info(buffer, id, cname, time, valid, auth_key, token_key, cert_signature); unsigned char cert_digest[2 * MSS_SEC_LVL]; index = cert_append_info(buffer, *id, cname, time, valid, auth_key, token_key); sponge_hash(buffer, index, cert_digest, 2 * MSS_SEC_LVL); // verify [(id || cname || time || valid || auth_key || token_key), csr_signature, token_key] return compare_dates(t_now, time) <= 0 && compare_dates(t_now, valid) >= 0 && ecdsa_verify(ca_pkey, cert_digest, cert_signature); }
/* * CSR stands for certificate request, which is sent by the client (or gateway) in order to provide the info needed by the AAAS to generate the certificate. * * CSR info: * - id: requester identification * - cname: common name * - time: date on which the csr has been generated * - auth_key: key used in mutual authentication (SMQV) * - token_key: key used to sign access token (MSS) * - csr_signature: CSR signature under token_key * */ void generate_csr(unsigned int id, char *cname, unsigned char auth_key[SMQV_PKEY_SIZE], unsigned char token_key[MSS_PKEY_SIZE], unsigned char mss_skey[MSS_SKEY_SIZE], char csr[CSR_MAX_SIZE]) { // append byte array of (id || cname || time || auth_key || token_key) unsigned int index = 0; unsigned char buffer[CSR_MAX_SIZE]; memset(buffer, 0, CSR_MAX_SIZE); memset(csr, 0, CSR_MAX_SIZE); char time[TIME_BUFFER_SIZE]; now(&time); index += csr_append_info(buffer, id, cname, time, auth_key, token_key); // sign (id || cname || time || auth_key || token_key) sponge_state sponge; unsigned char digest[2 * MSS_SEC_LVL]; sponge_hash(buffer, index, digest, 2 * MSS_SEC_LVL); memcpy(buffer + index, mss_sign(mss_skey, digest), MSS_SIGNATURE_SIZE); index += MSS_SIGNATURE_SIZE; base64encode(buffer, index, csr, CSR_MAX_SIZE); }
int main(int argc, char ** argv) { int ec_fifo, ce_fifo, es_fifo, se_fifo; FILE* fp; ssize_t msg_size; uint8_t *buff; char client_nm[NM_LENGTH], client_nm_tmp[NM_LENGTH]; uint8_t rsa_tmp[RSA_LENGTH], rsa_tmp2[RSA_LENGTH]; BIGNUM /**bn_n, *bn_d,*/ *bn_client_e, *bn_client_n, *bn_r; char client_cipher_suite; uint8_t sym_id, hash_id, public_id; uint8_t k[K_SIZE] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; int i, done; int k_len, c_hex_len, c_len; uint8_t g[HASH_LENGTH], g1[HASH_LENGTH]; uint8_t c[MSG_SIZE_MAX]; unsigned int tmp; assert(K_SIZE == 8); bn_client_e = BN_new(); bn_client_n = BN_new(); bn_r = BN_new(); /* Mandatory arguments */ if (!argv[1] || !argv[2] || !argv[3] || !argv[4] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) { fprintf(stderr, "%s [server->eve fifo] [eve->server fifo] [eve->client fifo] [client->eve fifo]\n", argv[0]); exit(1); } se_fifo = open_channel(argv[1]); es_fifo = open_channel(argv[2]); ec_fifo = open_fifo(argv[3]); ce_fifo = open_fifo(argv[4]); /* wait real client to connect */ fprintf(stderr,"(E) Waiting connection...\n"); if (wait_connection(ce_fifo) < 0) { fprintf(stderr,"(E) Communication error...\n"); goto next; } /* connect to server */ write_msg(es_fifo, (const u_int8_t *)CONNECTION_STRING, strlen(CONNECTION_STRING)); forward_string(se_fifo, ec_fifo, OK_STRING); /* Server authentication */ /* client challange */ forward_msg(ce_fifo, es_fifo); /* server response to challange */ forward_msg(se_fifo, ec_fifo); /* Client authentication */ /* Client name */ msg_size = forward_msg_read(ce_fifo, es_fifo, &buff); /* vvvv copy-paste from server vvvv */ buff[msg_size] = '\0'; strncpy((char *)client_nm, (const char *) buff, NM_LENGTH); /* EXTRACT from (names[],c_puk[],n[]) the pair (c_puk[i],n[i]) where names[i] = nm */ if ((fp = fopen("server_folder/clients_rsa64_public_keys.txt", "r")) == NULL) { fprintf(stderr, "Error while getting clients RSA public keys...\n"); goto next; } done = 0; while (!feof(fp)) { fscanf(fp, "%129s %129s %129s", client_nm_tmp, rsa_tmp, rsa_tmp2); if (strcmp(client_nm_tmp, client_nm) == 0) { done = 1; break; } } if (done == 0) { fprintf(stderr, "Error: unrecognized client\n"); goto next; } fclose(fp); BN_hex2bn(&bn_client_n, (const char *) rsa_tmp); BN_hex2bn(&bn_client_e, (const char *) rsa_tmp2); /* ^^^^ copy-paste from server ^^^^ */ /* now I know client name and pub key */ /* server challange */ forward_msg(se_fifo, ec_fifo); /* client response */ forward_msg(ce_fifo, es_fifo); /* Negotiation of the cipher suite */ /* cipher suite c -> s */ forward_msg_read(ce_fifo, es_fifo, &buff); /* vvvv copy-paste from server vvvv */ client_cipher_suite = buff[0]; cipher_suite_table(client_cipher_suite, &sym_id, &hash_id, &public_id); /* ^^^^ copy-paste from server ^^^^ */ /* Negotiation of the private key */ /* k already set as an arbitrary key */ /* vvvv copy-paste from server vvvv */ if (sym_id == 1) { k_len = 3; } else { k_len = K_SIZE; } BN_bin2bn(k, k_len, bn_r); /* If we're using RSA512 read the correct key (we have the 64bit one) */ if (public_id == 6) { if ((fp = fopen("server_folder/clients_rsa512_public_keys.txt", "r")) == NULL) { fprintf(stderr, "Error while getting clients RSA public keys...\n"); goto next; } done = 0; while (!feof(fp)) { fscanf(fp, "%129s %129s %129s", client_nm_tmp, rsa_tmp, rsa_tmp2); if (strcmp(client_nm_tmp, client_nm) == 0) { done = 1; break; } } if (done == 0) { fprintf(stderr, "Error: unrecognized client\n"); goto next; } fclose(fp); BN_hex2bn(&bn_client_n, (const char *) rsa_tmp); BN_hex2bn(&bn_client_e, (const char *) rsa_tmp2); } /* ENCRYPT key */ rsa_encrypt(bn_r, bn_client_e, bn_client_n); /* WRITE encrypted k to C */ buff = (uint8_t *) BN_bn2hex(bn_r); if ((write_msg(ec_fifo, buff, strlen((char *) buff))) < 0) { fprintf(stderr, "Error while sending C to the client...\n"); goto next; } OPENSSL_free(buff); /* Encrypted communication */ if ((msg_size = read_msg(ce_fifo,&buff)) < 0) { fprintf(stderr, "Error while reading message from the client...\n"); goto next; } c_hex_len = msg_size - HASH_LENGTH * 2; if (c_hex_len <= 0) { fprintf(stderr, "Error, malformed message...\n"); goto next; } c_len = c_hex_len / 2; for (i=0; i<msg_size; i+=2) { if (i < c_hex_len) { sscanf((char *) (buff+i), "%02x", &tmp); c[i/2] = (uint8_t) tmp; } else { sscanf((char *) (buff+i), "%02x", &tmp); g[(i - c_hex_len) / 2] = (uint8_t) tmp; } } /* Decrypt C */ decrypt(sym_id, c, c_len, k); /* COMPUTE G' = H(M) */ sponge_hash(c, c_len, g1); c[c_len] = '\0'; /* CHECK G' = G */ done = 1; for (i=0; i<HASH_LENGTH; i++) { if (g[i] != g1[i]) { done = 0; } } /* If the check fails print error message */ if (done == 0) { if ((write_msg(ec_fifo, (uint8_t *) CORRUPTED_STRING, strlen(CORRUPTED_STRING))) < 0) { fprintf(stderr, "Error while writing to the client...\n"); goto next; } } /* PUT M' on a file */ if ((fp = fopen("eve_folder/received_messages.txt", "a+")) == NULL) { fprintf(stderr, "Error while saving message...\n"); fclose(fp); goto next; } fprintf(fp, "%s", c); fflush(stdout); fprintf(stdout, "MESSAGGIO SEGRETO >>>%s<<< FINE MESSAGGIO SEGRETO\n", c); fflush(stdout); fclose(fp); /* WRITE ok message to C */ if ((write_msg(ec_fifo, (uint8_t *) DECRYPTED_STRING, strlen(DECRYPTED_STRING))) < 0) { fprintf(stderr, "Error while writing C to the client...\n"); goto next; } /* ^^^^ copy-paste from server ^^^^ */ next: /*close_channels ...!*/ BN_free(bn_client_n); BN_free(bn_client_e); BN_free(bn_r); exit(0); }