From: David Howells <dhowells@redhat.com>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: dhowells@redhat.com, Chuck Lever III <chuck.lever@oracle.com>,
Scott Mayhew <smayhew@redhat.com>,
Ard Biesheuvel <ardb@kernel.org>,
Jeff Layton <jlayton@kernel.org>,
Linux NFS Mailing List <linux-nfs@vger.kernel.org>,
"linux-crypto@vger.kernel.org" <linux-crypto@vger.kernel.org>
Subject: Re: Did the in-kernel Camellia or CMAC crypto implementation break?
Date: Fri, 14 Apr 2023 13:32:08 +0100 [thread overview]
Message-ID: <1247263.1681475528@warthog.procyon.org.uk> (raw)
In-Reply-To: <ZDkoiqPXwIRYmeF3@gondor.apana.org.au>
Herbert Xu <herbert@gondor.apana.org.au> wrote:
> Could you outline how this new interface would work?
Attached is documentation for the API as I currently have it.
David
---
.. SPDX-License-Identifier: GPL-2.0
===========================
Kerberos V Cryptography API
===========================
.. Contents:
- Overview.
- Small Buffer.
- Encoding Type.
- Key Derivation.
- PRF+ Calculation.
- Kc, Ke And Ki Derivation.
- Crypto Functions.
- Encryption Mode.
- Checksum Mode.
Overview
========
This API provides Kerberos 5-style cryptography for key derivation, encryption
and checksumming for use in network filesystems and can be used to implement
the low-level crypto that's needed for GSSAPI.
The following crypto types are supported::
KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96
KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96
KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128
KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192
KRB5_ENCTYPE_CAMELLIA128_CTS_CMAC
KRB5_ENCTYPE_CAMELLIA256_CTS_CMAC
KRB5_CKSUMTYPE_HMAC_SHA1_96_AES128
KRB5_CKSUMTYPE_HMAC_SHA1_96_AES256
KRB5_CKSUMTYPE_CMAC_CAMELLIA128
KRB5_CKSUMTYPE_CMAC_CAMELLIA256
KRB5_CKSUMTYPE_HMAC_SHA256_128_AES128
KRB5_CKSUMTYPE_HMAC_SHA384_192_AES256
The API can be included by::
#include <crypto/krb5.h>
Small Buffer
------------
To pass small pieces of data about, such as keys, a buffer structure is
defined, giving a pointer to the data and the size of that data::
struct krb5_buffer {
unsigned int len;
void *data;
};
Encoding Type
=============
The encoding type is defined by the following structure::
struct krb5_enctype {
int etype;
int ctype;
const char *name;
u16 key_bytes;
u16 key_len;
u16 Kc_len;
u16 Ke_len;
u16 Ki_len;
u16 prf_len;
u16 block_len;
u16 conf_len;
u16 cksum_len;
bool pad;
...
};
The fields of interest to the user of the API are as follows:
* ``etype`` and ``ctype`` indicate the protocol number for this encoding
type for encryption and checksumming respectively. They hold
``KRB5_ENCTYPE_*`` and ``KRB5_CKSUMTYPE_*`` constants.
* ``name`` is the formal name of the encoding.
* ``key_len`` and ``key_bytes`` are the input key length and the derived key
length. (I think they only differ for DES, which isn't supported here).
* ``Kc_len``, ``Ke_len`` and ``Ki_len`` are the sizes of the derived Kc, Ke
and Ki keys. Kc is used for in checksum mode; Ke and Ki are used in
encryption mode.
* ``prf_len`` is the size of the result from the PRF+ function calculation.
* ``block_len``, ``conf_len`` and ``cksum_len`` are the encryption block
length, confounder length and checksum length respectively. All three are
used in encryption mode, but only the checksum length is used in checksum
mode.
The encoding type is looked up by number using the following function::
const struct krb5_enctype *crypto_krb5_find_enctype(u32 enctype);
Key Derivation
==============
Once the application has selected an encryption type, the keys that will be
used to do the actual crypto can be derived from the transport key.
PRF+ Calculation
----------------
To aid in key derivation, a function to calculate the Kerberos GSSAPI
mechanism's PRF+ is provided::
int crypto_krb5_calc_PRFplus(const struct krb5_enctype *krb5,
const struct krb5_buffer *K,
unsigned int L,
const struct krb5_buffer *S,
struct krb5_buffer *result,
gfp_t gfp);
This can be used to derive the transport key from a source key plus additional
data to limit its use.
Kc, Ke And Ki Derivation
------------------------
To do actual crypto on messages, three keys can be derived: *Kc*, used in
checksum-only mode, and *Ke* and *Ki* which are used in encryption mode for
encryption and the integrity hash. Three functions are provided to derive
these keys from the transport key::
int crypto_krb5_get_Kc(const struct krb5_enctype *krb5,
const struct krb5_buffer *TK,
u32 usage,
struct krb5_buffer *key,
struct crypto_shash **_shash,
gfp_t gfp);
int crypto_krb5_get_Ke(const struct krb5_enctype *krb5,
const struct krb5_buffer *TK,
u32 usage,
struct krb5_buffer *key,
struct crypto_sync_skcipher **_ci,
gfp_t gfp);
int crypto_krb5_get_Ki(const struct krb5_enctype *krb5,
const struct krb5_buffer *TK,
u32 usage,
struct krb5_buffer *key,
struct crypto_shash **_shash,
gfp_t gfp);
In all cases, ``krb5`` is the encoding type, ``TK`` is the transport key,
``usage`` indicates the use to which the keys will be put, ``key`` is the
prepared output buffer for the raw key and ``gfp`` are flags to control any
allocation performated.
For Kc and Ki, ``_shash`` points to where the prepared and keyed hash context
should be returned and for Ke, ``_ci`` points to where the prepared and keyed
cipher should be returned. These will need to be passed into the crypto
functions.
For use with the encrypt/decrypt functions, a struct is provided to hold the
Ke skcipher and Ki shash::
struct krb5_enc_keys {
struct crypto_sync_skcipher *Ke;
struct crypto_shash *Ki;
};
and this can be cleaned up with::
void crypto_krb5_free_enc_keys(struct krb5_enc_keys *e);
Crypto Functions
================
Once the keys have been derived, crypto can be performed on the data. The
caller must leave gaps in the buffer for the storage of the confounder (if
needed) and the checksum when preparing a message for transmission. An enum
and two functions are provided to aid in this::
enum krb5_crypto_mode {
KRB5_CHECKSUM_MODE,
KRB5_ENCRYPT_MODE,
};
size_t crypto_krb5_how_much_buffer(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode, bool pad,
size_t data_size, size_t *_offset);
size_t crypto_krb5_how_much_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode, bool pad,
size_t *_buffer_size, size_t *_offset);
Both functions take the encoding type, an indication the mode of crypto
(checksum-only or full encryption) and an indication if padding is going to be
required by the application.
The first function returns how big the buffer will need to be to house a given
amount of data; the second function returns how much data will fit in a buffer
of a particular size, and adjusts down the size of the required buffer
accordingly. In both cases, the offset of the data within the buffer is also
returned.
When a message has been received, the location and size of the data can be
determined by calling::
size_t crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
size_t *_offset, size_t len);
This returns the size of the data (plus any padding) and the offset of the
data. It is up to the caller to determine how much padding there is.
Encryption Mode
---------------
A pair of functions are provided to encrypt and decrypt a message::
ssize_t crypto_krb5_encrypt(const struct krb5_enctype *krb5,
struct krb5_enc_keys *keys,
struct scatterlist *sg, unsigned int nr_sg,
size_t sg_len,
size_t data_offset, size_t data_len,
bool preconfounded);
int crypto_krb5_decrypt(const struct krb5_enctype *krb5,
struct krb5_enc_keys *keys,
struct scatterlist *sg, unsigned int nr_sg,
size_t *_offset, size_t *_len,
int *_error_code);
In both cases, the input and output buffers are indicated by the same
scatterlist.
For the encryption function, the output buffer may be larger than is needed
(the amount of output generated is returned) and the location and size of the
data are indicated (which must match the encoding). If no confounder is set,
the function will insert one.
For the decryption function, the offset and length of the message in buffer
are supplied and these are shrunk to fit the data. If a decryption failure
occurs, a kerberos 5 error code is indicated.
Checksum Mode
-------------
A pair of function are provided to generate the checksum on a message and to
verify that checksum::
ssize_t crypto_krb5_get_mic(const struct krb5_enctype *krb5,
struct crypto_shash *shash,
const struct krb5_buffer *metadata,
struct scatterlist *sg, unsigned int nr_sg,
size_t sg_len,
size_t data_offset, size_t data_len);
int crypto_krb5_verify_mic(const struct krb5_enctype *krb5,
struct crypto_shash *shash,
const struct krb5_buffer *metadata,
struct scatterlist *sg, unsigned int nr_sg,
size_t *_offset, size_t *_len,
int *_error_code);
In both cases, the input and output buffers are indicated by the same
scatterlist. Additional metadata can be passed in which will get added to the
hash before the data.
For the get_mic function, the output buffer may be larger than is needed (the
amount of output generated is returned) and the location and size of the data
are indicated (which must match the encoding).
For the verification function, the offset and length of the message in buffer
are supplied and these are shrunk to fit the data. If a verification failure
occurs, a kerberos 5 error code is indicated.
next prev parent reply other threads:[~2023-04-14 12:32 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-12 15:56 Did the in-kernel Camellia or CMAC crypto implementation break? David Howells
2023-04-12 16:57 ` Chuck Lever III
2023-04-12 17:44 ` Scott Mayhew
2023-04-12 17:50 ` David Howells
2023-04-13 6:07 ` Herbert Xu
2023-04-13 6:36 ` David Howells
2023-04-13 6:40 ` Herbert Xu
2023-04-13 8:59 ` David Howells
2023-04-13 13:55 ` David Howells
2023-04-14 2:08 ` Herbert Xu
2023-04-14 8:47 ` David Howells
2023-04-14 8:52 ` Herbert Xu
2023-04-14 10:17 ` David Howells
2023-04-14 10:18 ` Herbert Xu
2023-04-14 10:34 ` David Howells
2023-04-14 11:04 ` Herbert Xu
2023-04-14 12:32 ` David Howells [this message]
2023-05-22 21:07 ` David Howells
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1247263.1681475528@warthog.procyon.org.uk \
--to=dhowells@redhat.com \
--cc=ardb@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=herbert@gondor.apana.org.au \
--cc=jlayton@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=smayhew@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox