+int send_metakey(connection_t *cl)
+{
+ char *buffer;
+ int len, x;
+cp
+ len = RSA_size(cl->rsa_key);
+
+ /* Allocate buffers for the meta key */
+
+ buffer = xmalloc(len*2+1);
+
+ if(!cl->cipher_outkey)
+ cl->cipher_outkey = xmalloc(len);
+
+ if(!cl->cipher_outctx)
+ cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
+cp
+ /* Copy random data to the buffer */
+
+ RAND_bytes(cl->cipher_outkey, len);
+
+ cl->cipher_outkey[0] &= 0x7F; /* FIXME: Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
+
+ if(debug_lvl >= DEBUG_SCARY_THINGS)
+ {
+ bin2hex(cl->cipher_outkey, buffer, len);
+ buffer[len*2] = '\0';
+ syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
+ }
+
+ /* Encrypt the random data */
+
+ if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len) /* NO_PADDING because the message size equals the RSA key size and it is totally random */
+ {
+ syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
+ free(buffer);
+ return -1;
+ }
+cp
+ /* Convert the encrypted random data to a hexadecimal formatted string */
+
+ bin2hex(buffer, buffer, len);
+ buffer[len*2] = '\0';
+
+ /* Send the meta key */
+
+ if(cl->status.outgoing)
+ cl->allow_request = METAKEY;
+ else
+ cl->allow_request = ACK;
+
+ x = send_request(cl, "%d %s", METAKEY, buffer);
+ free(buffer);
+
+ EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(), cl->cipher_outkey, cl->cipher_outkey + EVP_bf_cfb()->key_len);
+cp
+ return x;
+}
+
+int metakey_h(connection_t *cl)
+{
+ char buffer[MAX_STRING_SIZE];
+ int len;
+cp
+ if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
+ {
+ syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
+ return -1;
+ }
+
+ len = RSA_size(myself->rsa_key);
+
+ /* Check if the length of the meta key is all right */
+
+ if(strlen(buffer) != len*2)
+ {
+ syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
+ return -1;
+ }
+
+ /* Allocate buffers for the meta key */
+
+ if(!cl->cipher_inkey)
+ cl->cipher_inkey = xmalloc(len);
+
+ if(!cl->cipher_inctx)
+ cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
+
+ /* Convert the challenge from hexadecimal back to binary */
+
+ hex2bin(buffer,buffer,len);
+
+ /* Decrypt the meta key */
+
+ if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
+ {
+ syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
+ return -1;
+ }
+
+ if(debug_lvl >= DEBUG_SCARY_THINGS)
+ {
+ bin2hex(cl->cipher_inkey, buffer, len);
+ buffer[len*2] = '\0';
+ syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
+ }
+
+ EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(), cl->cipher_inkey, cl->cipher_inkey + EVP_bf_cfb()->key_len);
+
+cp
+ if(cl->status.outgoing)
+ return send_ack(cl);
+ else
+ return send_metakey(cl);
+}
+
+int send_ack(connection_t *cl)