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

crypto: dh - split out deserialization code from crypto_dh_decode()

A subsequent commit will introduce "dh" wrapping templates of the form
"ffdhe2048(dh)", "ffdhe3072(dh)" and so on in order to provide built-in
support for the well-known safe-prime ffdhe group parameters specified in
RFC 7919.

Those templates' ->set_secret() will wrap the inner "dh" implementation's
->set_secret() and set the ->p and ->g group parameters as appropriate on
the way inwards. More specifically,
- A ffdheXYZ(dh) user would call crypto_dh_encode() on a struct dh instance
having ->p == ->g == NULL as well as ->p_size == ->g_size == 0 and pass
the resulting buffer to the outer ->set_secret().
- This outer ->set_secret() would then decode the struct dh via
crypto_dh_decode_key(), set ->p, ->g, ->p_size as well as ->g_size as
appropriate for the group in question and encode the struct dh again
before passing it further down to the inner "dh"'s ->set_secret().

The problem is that crypto_dh_decode_key() implements some basic checks
which would reject parameter sets with ->p_size == 0 and thus, the ffdheXYZ
templates' ->set_secret() cannot use it as-is for decoding the passed
buffer. As the inner "dh"'s ->set_secret() will eventually conduct said
checks on the final parameter set anyway, the outer ->set_secret() really
only needs the decoding functionality.

Split out the pure struct dh decoding part from crypto_dh_decode_key() into
the new __crypto_dh_decode_key().

__crypto_dh_decode_key() gets defined in crypto/dh_helper.c, but will have
to get called from crypto/dh.c and thus, its declaration must be somehow
made available to the latter. Strictly speaking, __crypto_dh_decode_key()
is internal to the dh_generic module, yet it would be a bit over the top
to introduce a new header like e.g. include/crypto/internal/dh.h
containing just a single prototype. Add the __crypto_dh_decode_key()
declaration to include/crypto/dh.h instead.

Provide a proper kernel-doc annotation, even though
__crypto_dh_decode_key() is purposedly not on the function list specified
in Documentation/crypto/api-kpp.rst.

Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Nicolai Stange and committed by
Herbert Xu
fae19893 215bebc8

+35 -8
+19 -8
crypto/dh_helper.c
··· 63 63 } 64 64 EXPORT_SYMBOL_GPL(crypto_dh_encode_key); 65 65 66 - int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params) 66 + int __crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params) 67 67 { 68 68 const u8 *ptr = buf; 69 69 struct kpp_secret secret; ··· 81 81 if (secret.len != crypto_dh_key_len(params)) 82 82 return -EINVAL; 83 83 84 + /* Don't allocate memory. Set pointers to data within 85 + * the given buffer 86 + */ 87 + params->key = (void *)ptr; 88 + params->p = (void *)(ptr + params->key_size); 89 + params->g = (void *)(ptr + params->key_size + params->p_size); 90 + 91 + return 0; 92 + } 93 + 94 + int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params) 95 + { 96 + int err; 97 + 98 + err = __crypto_dh_decode_key(buf, len, params); 99 + if (err) 100 + return err; 101 + 84 102 /* 85 103 * Don't permit the buffer for 'key' or 'g' to be larger than 'p', since 86 104 * some drivers assume otherwise. ··· 106 88 if (params->key_size > params->p_size || 107 89 params->g_size > params->p_size) 108 90 return -EINVAL; 109 - 110 - /* Don't allocate memory. Set pointers to data within 111 - * the given buffer 112 - */ 113 - params->key = (void *)ptr; 114 - params->p = (void *)(ptr + params->key_size); 115 - params->g = (void *)(ptr + params->key_size + params->p_size); 116 91 117 92 /* 118 93 * Don't permit 'p' to be 0. It's not a prime number, and it's subject
+16
include/crypto/dh.h
··· 79 79 */ 80 80 int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params); 81 81 82 + /** 83 + * __crypto_dh_decode_key() - decode a private key without parameter checks 84 + * @buf: Buffer holding a packet key that should be decoded 85 + * @len: Length of the packet private key buffer 86 + * @params: Buffer allocated by the caller that is filled with the 87 + * unpacked DH private key. 88 + * 89 + * Internal function providing the same services as the exported 90 + * crypto_dh_decode_key(), but without any of those basic parameter 91 + * checks conducted by the latter. 92 + * 93 + * Return: -EINVAL if buffer has insufficient size, 0 on success 94 + */ 95 + int __crypto_dh_decode_key(const char *buf, unsigned int len, 96 + struct dh *params); 97 + 82 98 #endif