struct crypto_hash *csums_tfm;
struct crypto_hash *cram_hmac_tfm;
struct crypto_hash *integrity_tfm;
- void *int_dig_in;
- void *int_dig_vv;
};
static int
{
char hmac_name[CRYPTO_MAX_ALG_NAME];
enum drbd_ret_code rv;
- int hash_size;
rv = alloc_hash(&crypto->csums_tfm, new_conf->csums_alg,
ERR_CSUMS_ALG);
rv = alloc_hash(&crypto->cram_hmac_tfm, hmac_name,
ERR_AUTH_ALG);
}
- if (crypto->integrity_tfm) {
- hash_size = crypto_hash_digestsize(crypto->integrity_tfm);
- crypto->int_dig_in = kmalloc(hash_size, GFP_KERNEL);
- if (!crypto->int_dig_in)
- return ERR_NOMEM;
- crypto->int_dig_vv = kmalloc(hash_size, GFP_KERNEL);
- if (!crypto->int_dig_vv)
- return ERR_NOMEM;
- }
return rv;
}
static void free_crypto(struct crypto *crypto)
{
- kfree(crypto->int_dig_in);
- kfree(crypto->int_dig_vv);
crypto_free_hash(crypto->cram_hmac_tfm);
crypto_free_hash(crypto->integrity_tfm);
crypto_free_hash(crypto->csums_tfm);
crypto.verify_tfm = NULL;
}
- kfree(tconn->int_dig_in);
- tconn->int_dig_in = crypto.int_dig_in;
- kfree(tconn->int_dig_vv);
- tconn->int_dig_vv = crypto.int_dig_vv;
crypto_free_hash(tconn->integrity_tfm);
tconn->integrity_tfm = crypto.integrity_tfm;
if (tconn->cstate >= C_WF_REPORT_PARAMS && tconn->agreed_pro_version >= 100)
rcu_assign_pointer(tconn->net_conf, new_conf);
conn_free_crypto(tconn);
- tconn->int_dig_in = crypto.int_dig_in;
- tconn->int_dig_vv = crypto.int_dig_vv;
tconn->cram_hmac_tfm = crypto.cram_hmac_tfm;
tconn->integrity_tfm = crypto.integrity_tfm;
tconn->csums_tfm = crypto.csums_tfm;
integrity_alg[SHARED_SECRET_MAX - 1] = 0;
}
- if (pi->cmd == P_PROTOCOL_UPDATE) {
- if (integrity_alg[0]) {
- int hash_size;
-
- /*
- * We can only change the peer data integrity algorithm
- * here. Changing our own data integrity algorithm
- * requires that we send a P_PROTOCOL_UPDATE packet at
- * the same time; otherwise, the peer has no way to
- * tell between which packets the algorithm should
- * change.
- */
-
- peer_integrity_tfm = crypto_alloc_hash(integrity_alg, 0, CRYPTO_ALG_ASYNC);
- if (!peer_integrity_tfm) {
- conn_err(tconn, "peer data-integrity-alg %s not supported\n",
- integrity_alg);
- goto disconnect;
- }
-
- hash_size = crypto_hash_digestsize(peer_integrity_tfm);
- int_dig_in = kmalloc(hash_size, GFP_KERNEL);
- int_dig_vv = kmalloc(hash_size, GFP_KERNEL);
- if (!(int_dig_in && int_dig_vv)) {
- conn_err(tconn, "Allocation of buffers for data integrity checking failed\n");
- goto disconnect;
- }
- }
-
- new_net_conf = kmalloc(sizeof(struct net_conf), GFP_KERNEL);
- if (!new_net_conf) {
- conn_err(tconn, "Allocation of new net_conf failed\n");
- goto disconnect;
- }
-
- mutex_lock(&tconn->data.mutex);
- mutex_lock(&tconn->conf_update);
- old_net_conf = tconn->net_conf;
- *new_net_conf = *old_net_conf;
-
- new_net_conf->wire_protocol = p_proto;
- new_net_conf->after_sb_0p = convert_after_sb(p_after_sb_0p);
- new_net_conf->after_sb_1p = convert_after_sb(p_after_sb_1p);
- new_net_conf->after_sb_2p = convert_after_sb(p_after_sb_2p);
- new_net_conf->two_primaries = p_two_primaries;
- strcpy(new_net_conf->integrity_alg, integrity_alg);
- new_net_conf->integrity_alg_len = strlen(integrity_alg) + 1;
-
- rcu_assign_pointer(tconn->net_conf, new_net_conf);
- mutex_unlock(&tconn->conf_update);
- mutex_unlock(&tconn->data.mutex);
-
- crypto_free_hash(tconn->peer_integrity_tfm);
- kfree(tconn->int_dig_in);
- kfree(tconn->int_dig_vv);
- tconn->peer_integrity_tfm = peer_integrity_tfm;
- tconn->int_dig_in = int_dig_in;
- tconn->int_dig_vv = int_dig_vv;
-
- if (strcmp(old_net_conf->integrity_alg, integrity_alg))
- conn_info(tconn, "peer data-integrity-alg: %s\n",
- integrity_alg[0] ? integrity_alg : "(none)");
-
- synchronize_rcu();
- kfree(old_net_conf);
- } else {
+ if (pi->cmd != P_PROTOCOL_UPDATE) {
clear_bit(CONN_DRY_RUN, &tconn->flags);
if (cf & CF_DRY_RUN)
rcu_read_unlock();
}
+
+ if (integrity_alg[0]) {
+ int hash_size;
+
+ /*
+ * We can only change the peer data integrity algorithm
+ * here. Changing our own data integrity algorithm
+ * requires that we send a P_PROTOCOL_UPDATE packet at
+ * the same time; otherwise, the peer has no way to
+ * tell between which packets the algorithm should
+ * change.
+ */
+
+ peer_integrity_tfm = crypto_alloc_hash(integrity_alg, 0, CRYPTO_ALG_ASYNC);
+ if (!peer_integrity_tfm) {
+ conn_err(tconn, "peer data-integrity-alg %s not supported\n",
+ integrity_alg);
+ goto disconnect;
+ }
+
+ hash_size = crypto_hash_digestsize(peer_integrity_tfm);
+ int_dig_in = kmalloc(hash_size, GFP_KERNEL);
+ int_dig_vv = kmalloc(hash_size, GFP_KERNEL);
+ if (!(int_dig_in && int_dig_vv)) {
+ conn_err(tconn, "Allocation of buffers for data integrity checking failed\n");
+ goto disconnect;
+ }
+ }
+
+ new_net_conf = kmalloc(sizeof(struct net_conf), GFP_KERNEL);
+ if (!new_net_conf) {
+ conn_err(tconn, "Allocation of new net_conf failed\n");
+ goto disconnect;
+ }
+
+ mutex_lock(&tconn->data.mutex);
+ mutex_lock(&tconn->conf_update);
+ old_net_conf = tconn->net_conf;
+ *new_net_conf = *old_net_conf;
+
+ new_net_conf->wire_protocol = p_proto;
+ new_net_conf->after_sb_0p = convert_after_sb(p_after_sb_0p);
+ new_net_conf->after_sb_1p = convert_after_sb(p_after_sb_1p);
+ new_net_conf->after_sb_2p = convert_after_sb(p_after_sb_2p);
+ new_net_conf->two_primaries = p_two_primaries;
+
+ rcu_assign_pointer(tconn->net_conf, new_net_conf);
+ mutex_unlock(&tconn->conf_update);
+ mutex_unlock(&tconn->data.mutex);
+
+ crypto_free_hash(tconn->peer_integrity_tfm);
+ kfree(tconn->int_dig_in);
+ kfree(tconn->int_dig_vv);
+ tconn->peer_integrity_tfm = peer_integrity_tfm;
+ tconn->int_dig_in = int_dig_in;
+ tconn->int_dig_vv = int_dig_vv;
+
+ if (strcmp(old_net_conf->integrity_alg, integrity_alg))
+ conn_info(tconn, "peer data-integrity-alg: %s\n",
+ integrity_alg[0] ? integrity_alg : "(none)");
+
+ synchronize_rcu();
+ kfree(old_net_conf);
return 0;
disconnect_rcu_unlock: