162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * SunRPC GSS Kerberos 5 mechanism internal definitions
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2022 Oracle and/or its affiliates.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H
962306a36Sopenharmony_ci#define _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * The RFCs often specify payload lengths in bits. This helper
1362306a36Sopenharmony_ci * converts a specified bit-length to the number of octets/bytes.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci#define BITS2OCTETS(x)	((x) / 8)
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistruct krb5_ctx;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct gss_krb5_enctype {
2062306a36Sopenharmony_ci	const u32		etype;		/* encryption (key) type */
2162306a36Sopenharmony_ci	const u32		ctype;		/* checksum type */
2262306a36Sopenharmony_ci	const char		*name;		/* "friendly" name */
2362306a36Sopenharmony_ci	const char		*encrypt_name;	/* crypto encrypt name */
2462306a36Sopenharmony_ci	const char		*aux_cipher;	/* aux encrypt cipher name */
2562306a36Sopenharmony_ci	const char		*cksum_name;	/* crypto checksum name */
2662306a36Sopenharmony_ci	const u16		signalg;	/* signing algorithm */
2762306a36Sopenharmony_ci	const u16		sealalg;	/* sealing algorithm */
2862306a36Sopenharmony_ci	const u32		cksumlength;	/* checksum length */
2962306a36Sopenharmony_ci	const u32		keyed_cksum;	/* is it a keyed cksum? */
3062306a36Sopenharmony_ci	const u32		keybytes;	/* raw key len, in bytes */
3162306a36Sopenharmony_ci	const u32		keylength;	/* protocol key length, in octets */
3262306a36Sopenharmony_ci	const u32		Kc_length;	/* checksum subkey length, in octets */
3362306a36Sopenharmony_ci	const u32		Ke_length;	/* encryption subkey length, in octets */
3462306a36Sopenharmony_ci	const u32		Ki_length;	/* integrity subkey length, in octets */
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	int (*derive_key)(const struct gss_krb5_enctype *gk5e,
3762306a36Sopenharmony_ci			  const struct xdr_netobj *in,
3862306a36Sopenharmony_ci			  struct xdr_netobj *out,
3962306a36Sopenharmony_ci			  const struct xdr_netobj *label,
4062306a36Sopenharmony_ci			  gfp_t gfp_mask);
4162306a36Sopenharmony_ci	u32 (*encrypt)(struct krb5_ctx *kctx, u32 offset,
4262306a36Sopenharmony_ci		       struct xdr_buf *buf, struct page **pages);
4362306a36Sopenharmony_ci	u32 (*decrypt)(struct krb5_ctx *kctx, u32 offset, u32 len,
4462306a36Sopenharmony_ci		       struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
4562306a36Sopenharmony_ci	u32 (*get_mic)(struct krb5_ctx *kctx, struct xdr_buf *text,
4662306a36Sopenharmony_ci		       struct xdr_netobj *token);
4762306a36Sopenharmony_ci	u32 (*verify_mic)(struct krb5_ctx *kctx, struct xdr_buf *message_buffer,
4862306a36Sopenharmony_ci			  struct xdr_netobj *read_token);
4962306a36Sopenharmony_ci	u32 (*wrap)(struct krb5_ctx *kctx, int offset,
5062306a36Sopenharmony_ci		    struct xdr_buf *buf, struct page **pages);
5162306a36Sopenharmony_ci	u32 (*unwrap)(struct krb5_ctx *kctx, int offset, int len,
5262306a36Sopenharmony_ci		      struct xdr_buf *buf, unsigned int *slack,
5362306a36Sopenharmony_ci		      unsigned int *align);
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* krb5_ctx flags definitions */
5762306a36Sopenharmony_ci#define KRB5_CTX_FLAG_INITIATOR         0x00000001
5862306a36Sopenharmony_ci#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct krb5_ctx {
6162306a36Sopenharmony_ci	int			initiate; /* 1 = initiating, 0 = accepting */
6262306a36Sopenharmony_ci	u32			enctype;
6362306a36Sopenharmony_ci	u32			flags;
6462306a36Sopenharmony_ci	const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
6562306a36Sopenharmony_ci	struct crypto_sync_skcipher *enc;
6662306a36Sopenharmony_ci	struct crypto_sync_skcipher *seq;
6762306a36Sopenharmony_ci	struct crypto_sync_skcipher *acceptor_enc;
6862306a36Sopenharmony_ci	struct crypto_sync_skcipher *initiator_enc;
6962306a36Sopenharmony_ci	struct crypto_sync_skcipher *acceptor_enc_aux;
7062306a36Sopenharmony_ci	struct crypto_sync_skcipher *initiator_enc_aux;
7162306a36Sopenharmony_ci	struct crypto_ahash	*acceptor_sign;
7262306a36Sopenharmony_ci	struct crypto_ahash	*initiator_sign;
7362306a36Sopenharmony_ci	struct crypto_ahash	*initiator_integ;
7462306a36Sopenharmony_ci	struct crypto_ahash	*acceptor_integ;
7562306a36Sopenharmony_ci	u8			Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */
7662306a36Sopenharmony_ci	u8			cksum[GSS_KRB5_MAX_KEYLEN];
7762306a36Sopenharmony_ci	atomic_t		seq_send;
7862306a36Sopenharmony_ci	atomic64_t		seq_send64;
7962306a36Sopenharmony_ci	time64_t		endtime;
8062306a36Sopenharmony_ci	struct xdr_netobj	mech_used;
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/*
8462306a36Sopenharmony_ci * GSS Kerberos 5 mechanism Per-Message calls.
8562306a36Sopenharmony_ci */
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ciu32 gss_krb5_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,
8862306a36Sopenharmony_ci			struct xdr_netobj *token);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ciu32 gss_krb5_verify_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *message_buffer,
9162306a36Sopenharmony_ci			   struct xdr_netobj *read_token);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ciu32 gss_krb5_wrap_v2(struct krb5_ctx *kctx, int offset,
9462306a36Sopenharmony_ci		     struct xdr_buf *buf, struct page **pages);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ciu32 gss_krb5_unwrap_v2(struct krb5_ctx *kctx, int offset, int len,
9762306a36Sopenharmony_ci		       struct xdr_buf *buf, unsigned int *slack,
9862306a36Sopenharmony_ci		       unsigned int *align);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/*
10162306a36Sopenharmony_ci * Implementation internal functions
10262306a36Sopenharmony_ci */
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/* Key Derivation Functions */
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ciint krb5_derive_key_v2(const struct gss_krb5_enctype *gk5e,
10762306a36Sopenharmony_ci		       const struct xdr_netobj *inkey,
10862306a36Sopenharmony_ci		       struct xdr_netobj *outkey,
10962306a36Sopenharmony_ci		       const struct xdr_netobj *label,
11062306a36Sopenharmony_ci		       gfp_t gfp_mask);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ciint krb5_kdf_hmac_sha2(const struct gss_krb5_enctype *gk5e,
11362306a36Sopenharmony_ci		       const struct xdr_netobj *inkey,
11462306a36Sopenharmony_ci		       struct xdr_netobj *outkey,
11562306a36Sopenharmony_ci		       const struct xdr_netobj *in_constant,
11662306a36Sopenharmony_ci		       gfp_t gfp_mask);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ciint krb5_kdf_feedback_cmac(const struct gss_krb5_enctype *gk5e,
11962306a36Sopenharmony_ci			   const struct xdr_netobj *inkey,
12062306a36Sopenharmony_ci			   struct xdr_netobj *outkey,
12162306a36Sopenharmony_ci			   const struct xdr_netobj *in_constant,
12262306a36Sopenharmony_ci			   gfp_t gfp_mask);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci/**
12562306a36Sopenharmony_ci * krb5_derive_key - Derive a subkey from a protocol key
12662306a36Sopenharmony_ci * @kctx: Kerberos 5 context
12762306a36Sopenharmony_ci * @inkey: base protocol key
12862306a36Sopenharmony_ci * @outkey: OUT: derived key
12962306a36Sopenharmony_ci * @usage: key usage value
13062306a36Sopenharmony_ci * @seed: key usage seed (one octet)
13162306a36Sopenharmony_ci * @gfp_mask: memory allocation control flags
13262306a36Sopenharmony_ci *
13362306a36Sopenharmony_ci * Caller sets @outkey->len to the desired length of the derived key.
13462306a36Sopenharmony_ci *
13562306a36Sopenharmony_ci * On success, returns 0 and fills in @outkey. A negative errno value
13662306a36Sopenharmony_ci * is returned on failure.
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_cistatic inline int krb5_derive_key(struct krb5_ctx *kctx,
13962306a36Sopenharmony_ci				  const struct xdr_netobj *inkey,
14062306a36Sopenharmony_ci				  struct xdr_netobj *outkey,
14162306a36Sopenharmony_ci				  u32 usage, u8 seed, gfp_t gfp_mask)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	const struct gss_krb5_enctype *gk5e = kctx->gk5e;
14462306a36Sopenharmony_ci	u8 label_data[GSS_KRB5_K5CLENGTH];
14562306a36Sopenharmony_ci	struct xdr_netobj label = {
14662306a36Sopenharmony_ci		.len	= sizeof(label_data),
14762306a36Sopenharmony_ci		.data	= label_data,
14862306a36Sopenharmony_ci	};
14962306a36Sopenharmony_ci	__be32 *p = (__be32 *)label_data;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	*p = cpu_to_be32(usage);
15262306a36Sopenharmony_ci	label_data[4] = seed;
15362306a36Sopenharmony_ci	return gk5e->derive_key(gk5e, inkey, outkey, &label, gfp_mask);
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_civoid krb5_make_confounder(u8 *p, int conflen);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ciu32 make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
15962306a36Sopenharmony_ci		  struct xdr_buf *body, int body_offset, u8 *cksumkey,
16062306a36Sopenharmony_ci		  unsigned int usage, struct xdr_netobj *cksumout);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ciu32 gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen,
16362306a36Sopenharmony_ci		      const struct xdr_buf *body, int body_offset,
16462306a36Sopenharmony_ci		      struct xdr_netobj *cksumout);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ciu32 krb5_encrypt(struct crypto_sync_skcipher *key, void *iv, void *in,
16762306a36Sopenharmony_ci		 void *out, int length);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ciu32 krb5_decrypt(struct crypto_sync_skcipher *key, void *iv, void *in,
17062306a36Sopenharmony_ci		 void *out, int length);
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ciint xdr_extend_head(struct xdr_buf *buf, unsigned int base,
17362306a36Sopenharmony_ci		    unsigned int shiftlen);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciint gss_encrypt_xdr_buf(struct crypto_sync_skcipher *tfm,
17662306a36Sopenharmony_ci			struct xdr_buf *outbuf, int offset,
17762306a36Sopenharmony_ci			struct page **pages);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ciint gss_decrypt_xdr_buf(struct crypto_sync_skcipher *tfm,
18062306a36Sopenharmony_ci			struct xdr_buf *inbuf, int offset);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ciu32 gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
18362306a36Sopenharmony_ci			 struct xdr_buf *buf, struct page **pages);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ciu32 gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
18662306a36Sopenharmony_ci			 struct xdr_buf *buf, u32 *plainoffset, u32 *plainlen);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ciu32 krb5_etm_encrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
18962306a36Sopenharmony_ci		     struct page **pages);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ciu32 krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
19262306a36Sopenharmony_ci		     struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_KUNIT)
19562306a36Sopenharmony_civoid krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out);
19662306a36Sopenharmony_ciconst struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype);
19762306a36Sopenharmony_ciint krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
19862306a36Sopenharmony_ci			 struct crypto_sync_skcipher *cbc_tfm, u32 offset,
19962306a36Sopenharmony_ci			 struct xdr_buf *buf, struct page **pages,
20062306a36Sopenharmony_ci			 u8 *iv, unsigned int ivsize);
20162306a36Sopenharmony_ciint krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
20262306a36Sopenharmony_ci			 struct crypto_sync_skcipher *cbc_tfm,
20362306a36Sopenharmony_ci			 u32 offset, struct xdr_buf *buf);
20462306a36Sopenharmony_ciu32 krb5_etm_checksum(struct crypto_sync_skcipher *cipher,
20562306a36Sopenharmony_ci		      struct crypto_ahash *tfm, const struct xdr_buf *body,
20662306a36Sopenharmony_ci		      int body_offset, struct xdr_netobj *cksumout);
20762306a36Sopenharmony_ci#endif
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci#endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */
210