Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

libceph: adapt ceph_x_challenge_blob hashing and msgr1 message signing

The existing approach where ceph_x_challenge_blob is encrypted with the
client's secret key and then the digest derived from the ciphertext is
used for the test doesn't work with CEPH_CRYPTO_AES256KRB5 because the
confounder randomizes the ciphertext: the client and the server get two
different ciphertexts and therefore two different digests.

msgr1 signatures are affected the same way: a digest derived from the
ciphertext for the message's "sigblock" is what becomes a signature and
the two sides disagree on the expected value.

For CEPH_CRYPTO_AES256KRB5 (and potential future encryption schemes),
switch to HMAC-SHA256 function keyed in the same way as the existing
encryption. For CEPH_CRYPTO_AES, everything is preserved as is.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

+72 -23
+43 -16
net/ceph/auth_x.c
··· 553 553 if (need & CEPH_ENTITY_TYPE_AUTH) { 554 554 struct ceph_x_authenticate *auth = (void *)(head + 1); 555 555 void *enc_buf = xi->auth_authorizer.enc_buf; 556 - struct ceph_x_challenge_blob *blob = enc_buf + 557 - ceph_x_encrypt_offset(&xi->secret); 556 + struct ceph_x_challenge_blob *blob; 558 557 u64 *u; 559 558 560 559 p = auth + 1; ··· 563 564 dout(" get_auth_session_key\n"); 564 565 head->op = cpu_to_le16(CEPHX_GET_AUTH_SESSION_KEY); 565 566 566 - /* encrypt and hash */ 567 + if (xi->secret.type == CEPH_CRYPTO_AES) { 568 + blob = enc_buf + ceph_x_encrypt_offset(&xi->secret); 569 + } else { 570 + BUILD_BUG_ON(SHA256_DIGEST_SIZE + sizeof(*blob) > 571 + CEPHX_AU_ENC_BUF_LEN); 572 + blob = enc_buf + SHA256_DIGEST_SIZE; 573 + } 574 + 567 575 get_random_bytes(&auth->client_challenge, sizeof(u64)); 568 576 blob->client_challenge = auth->client_challenge; 569 577 blob->server_challenge = cpu_to_le64(xi->server_challenge); 570 - ret = ceph_x_encrypt(&xi->secret, 0 /* dummy */, 571 - enc_buf, CEPHX_AU_ENC_BUF_LEN, 572 - sizeof(*blob)); 573 - if (ret < 0) 574 - return ret; 578 + 579 + if (xi->secret.type == CEPH_CRYPTO_AES) { 580 + ret = ceph_x_encrypt(&xi->secret, 0 /* dummy */, 581 + enc_buf, CEPHX_AU_ENC_BUF_LEN, 582 + sizeof(*blob)); 583 + if (ret < 0) 584 + return ret; 585 + } else { 586 + ceph_hmac_sha256(&xi->secret, blob, sizeof(*blob), 587 + enc_buf); 588 + ret = SHA256_DIGEST_SIZE; 589 + } 575 590 576 591 auth->struct_v = 3; /* nautilus+ */ 577 592 auth->key = 0; ··· 1066 1053 __le32 data_crc; 1067 1054 __le32 data_len; 1068 1055 __le32 seq_lower_word; 1069 - } __packed *sigblock = enc_buf; 1056 + } __packed *sigblock; 1070 1057 struct { 1071 1058 __le64 a, b, c, d; 1072 1059 } __packed *penc = enc_buf; 1073 - int ciphertext_len; 1060 + 1061 + if (au->session_key.type == CEPH_CRYPTO_AES) { 1062 + /* no leading len, no ceph_x_encrypt_header */ 1063 + sigblock = enc_buf; 1064 + } else { 1065 + BUILD_BUG_ON(SHA256_DIGEST_SIZE + sizeof(*sigblock) > 1066 + CEPHX_AU_ENC_BUF_LEN); 1067 + sigblock = enc_buf + SHA256_DIGEST_SIZE; 1068 + } 1074 1069 1075 1070 sigblock->header_crc = msg->hdr.crc; 1076 1071 sigblock->front_crc = msg->footer.front_crc; ··· 1089 1068 sigblock->data_len = msg->hdr.data_len; 1090 1069 sigblock->seq_lower_word = *(__le32 *)&msg->hdr.seq; 1091 1070 1092 - /* no leading len, no ceph_x_encrypt_header */ 1093 - ret = ceph_crypt(&au->session_key, 0 /* dummy */, 1094 - true, enc_buf, CEPHX_AU_ENC_BUF_LEN, 1095 - sizeof(*sigblock), &ciphertext_len); 1096 - if (ret) 1097 - return ret; 1071 + if (au->session_key.type == CEPH_CRYPTO_AES) { 1072 + int ciphertext_len; /* unused */ 1073 + 1074 + ret = ceph_crypt(&au->session_key, 0 /* dummy */, 1075 + true, enc_buf, CEPHX_AU_ENC_BUF_LEN, 1076 + sizeof(*sigblock), &ciphertext_len); 1077 + if (ret) 1078 + return ret; 1079 + } else { 1080 + ceph_hmac_sha256(&au->session_key, sigblock, 1081 + sizeof(*sigblock), enc_buf); 1082 + } 1098 1083 1099 1084 *psig = penc->a ^ penc->b ^ penc->c ^ penc->d; 1100 1085 }
+18
net/ceph/crypto.c
··· 84 84 case CEPH_CRYPTO_AES: 85 85 return set_aes_tfm(key); 86 86 case CEPH_CRYPTO_AES256KRB5: 87 + hmac_sha256_preparekey(&key->hmac_key, key->key, key->len); 87 88 return set_krb5_tfms(key, key_usages, key_usage_cnt); 88 89 default: 89 90 return -ENOTSUPP; ··· 179 178 key->aes_tfm = NULL; 180 179 } 181 180 } else if (key->type == CEPH_CRYPTO_AES256KRB5) { 181 + memzero_explicit(&key->hmac_key, sizeof(key->hmac_key)); 182 182 for (i = 0; i < ARRAY_SIZE(key->krb5_tfms); i++) { 183 183 if (key->krb5_tfms[i]) { 184 184 crypto_free_aead(key->krb5_tfms[i]); ··· 433 431 case CEPH_CRYPTO_AES256KRB5: 434 432 /* confounder at the beginning and 192-bit HMAC at the end */ 435 433 return AES_BLOCK_SIZE + data_len + 24; 434 + default: 435 + BUG(); 436 + } 437 + } 438 + 439 + void ceph_hmac_sha256(const struct ceph_crypto_key *key, const void *buf, 440 + int buf_len, u8 hmac[SHA256_DIGEST_SIZE]) 441 + { 442 + switch (key->type) { 443 + case CEPH_CRYPTO_NONE: 444 + case CEPH_CRYPTO_AES: 445 + memset(hmac, 0, SHA256_DIGEST_SIZE); 446 + return; 447 + case CEPH_CRYPTO_AES256KRB5: 448 + hmac_sha256(&key->hmac_key, buf, buf_len, hmac); 449 + return; 436 450 default: 437 451 BUG(); 438 452 }
+4
net/ceph/crypto.h
··· 2 2 #ifndef _FS_CEPH_CRYPTO_H 3 3 #define _FS_CEPH_CRYPTO_H 4 4 5 + #include <crypto/sha2.h> 5 6 #include <linux/ceph/types.h> 6 7 #include <linux/ceph/buffer.h> 7 8 ··· 21 20 union { 22 21 struct crypto_sync_skcipher *aes_tfm; 23 22 struct { 23 + struct hmac_sha256_key hmac_key; 24 24 const struct krb5_enctype *krb5_type; 25 25 struct crypto_aead *krb5_tfms[3]; 26 26 }; ··· 41 39 void *buf, int buf_len, int in_len, int *pout_len); 42 40 int ceph_crypt_data_offset(const struct ceph_crypto_key *key); 43 41 int ceph_crypt_buflen(const struct ceph_crypto_key *key, int data_len); 42 + void ceph_hmac_sha256(const struct ceph_crypto_key *key, const void *buf, 43 + int buf_len, u8 hmac[SHA256_DIGEST_SIZE]); 44 44 int ceph_crypto_init(void); 45 45 void ceph_crypto_shutdown(void); 46 46
+7 -7
net/ceph/messenger_v2.c
··· 779 779 return 0; /* auth_x, secure mode */ 780 780 } 781 781 782 - static void ceph_hmac_sha256(struct ceph_connection *con, 783 - const struct kvec *kvecs, int kvec_cnt, 784 - u8 hmac[SHA256_DIGEST_SIZE]) 782 + static void con_hmac_sha256(struct ceph_connection *con, 783 + const struct kvec *kvecs, int kvec_cnt, 784 + u8 hmac[SHA256_DIGEST_SIZE]) 785 785 { 786 786 struct hmac_sha256_ctx ctx; 787 787 int i; ··· 1438 1438 if (!buf) 1439 1439 return -ENOMEM; 1440 1440 1441 - ceph_hmac_sha256(con, con->v2.in_sign_kvecs, con->v2.in_sign_kvec_cnt, 1442 - CTRL_BODY(buf)); 1441 + con_hmac_sha256(con, con->v2.in_sign_kvecs, con->v2.in_sign_kvec_cnt, 1442 + CTRL_BODY(buf)); 1443 1443 1444 1444 return prepare_control(con, FRAME_TAG_AUTH_SIGNATURE, buf, 1445 1445 SHA256_DIGEST_SIZE); ··· 2436 2436 return -EINVAL; 2437 2437 } 2438 2438 2439 - ceph_hmac_sha256(con, con->v2.out_sign_kvecs, con->v2.out_sign_kvec_cnt, 2440 - hmac); 2439 + con_hmac_sha256(con, con->v2.out_sign_kvecs, con->v2.out_sign_kvec_cnt, 2440 + hmac); 2441 2441 2442 2442 ceph_decode_need(&p, end, SHA256_DIGEST_SIZE, bad); 2443 2443 if (crypto_memneq(p, hmac, SHA256_DIGEST_SIZE)) {