1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* Common bits for GSSAPI-based RxRPC security. 3 * 4 * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <crypto/krb5.h> 9 #include <crypto/skcipher.h> 10 #include <crypto/hash.h> 11 12 /* 13 * Per-key number context. This is replaced when the connection is rekeyed. 14 */ 15 struct rxgk_context { 16 refcount_t usage; 17 unsigned int key_number; /* Rekeying number (goes in the rx header) */ 18 unsigned long flags; 19 #define RXGK_TK_NEEDS_REKEY 0 /* Set if this needs rekeying */ 20 unsigned long expiry; /* Expiration time of this key */ 21 long long bytes_remaining; /* Remaining Tx lifetime of this key */ 22 const struct krb5_enctype *krb5; /* RxGK encryption type */ 23 const struct rxgk_key *key; 24 25 /* We need up to 7 keys derived from the transport key, but we don't 26 * actually need the transport key. Each key is derived by 27 * DK(TK,constant). 28 */ 29 struct crypto_aead *tx_enc; /* Transmission key */ 30 struct crypto_aead *rx_enc; /* Reception key */ 31 struct crypto_shash *tx_Kc; /* Transmission checksum key */ 32 struct crypto_shash *rx_Kc; /* Reception checksum key */ 33 struct crypto_aead *resp_enc; /* Response packet enc key */ 34 }; 35 36 #define xdr_round_up(x) (round_up((x), sizeof(__be32))) 37 #define xdr_object_len(x) (4 + xdr_round_up(x)) 38 39 /* 40 * rxgk_app.c 41 */ 42 int rxgk_yfs_decode_ticket(struct rxrpc_connection *conn, struct sk_buff *skb, 43 unsigned int ticket_offset, unsigned int ticket_len, 44 struct key **_key); 45 int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb, 46 unsigned int token_offset, unsigned int token_len, 47 struct key **_key); 48 49 /* 50 * rxgk_kdf.c 51 */ 52 void rxgk_put(struct rxgk_context *gk); 53 struct rxgk_context *rxgk_generate_transport_key(struct rxrpc_connection *conn, 54 const struct rxgk_key *key, 55 unsigned int key_number, 56 gfp_t gfp); 57 int rxgk_set_up_token_cipher(const struct krb5_buffer *server_key, 58 struct crypto_aead **token_key, 59 unsigned int enctype, 60 const struct krb5_enctype **_krb5, 61 gfp_t gfp); 62 63 /* 64 * Apply decryption and checksumming functions to part of an skbuff. The 65 * offset and length are updated to reflect the actual content of the encrypted 66 * region. 67 */ 68 static inline 69 int rxgk_decrypt_skb(const struct krb5_enctype *krb5, 70 struct crypto_aead *aead, 71 struct sk_buff *skb, 72 unsigned int *_offset, unsigned int *_len, 73 int *_error_code) 74 { 75 struct scatterlist sg[16]; 76 size_t offset = 0, len = *_len; 77 int nr_sg, ret; 78 79 sg_init_table(sg, ARRAY_SIZE(sg)); 80 nr_sg = skb_to_sgvec(skb, sg, *_offset, len); 81 if (unlikely(nr_sg < 0)) 82 return nr_sg; 83 84 ret = crypto_krb5_decrypt(krb5, aead, sg, nr_sg, 85 &offset, &len); 86 switch (ret) { 87 case 0: 88 *_offset += offset; 89 *_len = len; 90 break; 91 case -EBADMSG: /* Checksum mismatch. */ 92 case -EPROTO: 93 *_error_code = RXGK_SEALEDINCON; 94 break; 95 case -EMSGSIZE: 96 *_error_code = RXGK_PACKETSHORT; 97 break; 98 case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */ 99 default: 100 *_error_code = RXGK_INCONSISTENCY; 101 break; 102 } 103 104 return ret; 105 } 106 107 /* 108 * Check the MIC on a region of an skbuff. The offset and length are updated 109 * to reflect the actual content of the secure region. 110 */ 111 static inline 112 int rxgk_verify_mic_skb(const struct krb5_enctype *krb5, 113 struct crypto_shash *shash, 114 const struct krb5_buffer *metadata, 115 struct sk_buff *skb, 116 unsigned int *_offset, unsigned int *_len, 117 u32 *_error_code) 118 { 119 struct scatterlist sg[16]; 120 size_t offset = 0, len = *_len; 121 int nr_sg, ret; 122 123 sg_init_table(sg, ARRAY_SIZE(sg)); 124 nr_sg = skb_to_sgvec(skb, sg, *_offset, len); 125 if (unlikely(nr_sg < 0)) 126 return nr_sg; 127 128 ret = crypto_krb5_verify_mic(krb5, shash, metadata, sg, nr_sg, 129 &offset, &len); 130 switch (ret) { 131 case 0: 132 *_offset += offset; 133 *_len = len; 134 break; 135 case -EBADMSG: /* Checksum mismatch */ 136 case -EPROTO: 137 *_error_code = RXGK_SEALEDINCON; 138 break; 139 case -EMSGSIZE: 140 *_error_code = RXGK_PACKETSHORT; 141 break; 142 case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */ 143 default: 144 *_error_code = RXGK_INCONSISTENCY; 145 break; 146 } 147 148 return ret; 149 } 150