File Index
Files and directories
Sign in
FILE

df_sp80090a.c

File preview with syntax highlighting.

linux-6.19.14/crypto/df_sp80090a.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3/*
  4 * NIST SP800-90A DRBG derivation function
  5 *
  6 * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
  7 */
  8
  9#include <linux/errno.h>
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/string.h>
 13#include <crypto/aes.h>
 14#include <crypto/df_sp80090a.h>
 15#include <crypto/internal/drbg.h>
 16
 17static void drbg_kcapi_symsetkey(struct crypto_aes_ctx *aesctx,
 18				 const unsigned char *key,
 19				 u8 keylen);
 20static void drbg_kcapi_symsetkey(struct crypto_aes_ctx *aesctx,
 21				 const unsigned char *key, u8 keylen)
 22{
 23	aes_expandkey(aesctx, key, keylen);
 24}
 25
 26static void drbg_kcapi_sym(struct crypto_aes_ctx *aesctx,
 27			   unsigned char *outval,
 28			   const struct drbg_string *in, u8 blocklen_bytes)
 29{
 30	/* there is only component in *in */
 31	BUG_ON(in->len < blocklen_bytes);
 32	aes_encrypt(aesctx, outval, in->buf);
 33}
 34
 35/* BCC function for CTR DRBG as defined in 10.4.3 */
 36
 37static void drbg_ctr_bcc(struct crypto_aes_ctx *aesctx,
 38			 unsigned char *out, const unsigned char *key,
 39			 struct list_head *in,
 40			 u8 blocklen_bytes,
 41			 u8 keylen)
 42{
 43	struct drbg_string *curr = NULL;
 44	struct drbg_string data;
 45	short cnt = 0;
 46
 47	drbg_string_fill(&data, out, blocklen_bytes);
 48
 49	/* 10.4.3 step 2 / 4 */
 50	drbg_kcapi_symsetkey(aesctx, key, keylen);
 51	list_for_each_entry(curr, in, list) {
 52		const unsigned char *pos = curr->buf;
 53		size_t len = curr->len;
 54		/* 10.4.3 step 4.1 */
 55		while (len) {
 56			/* 10.4.3 step 4.2 */
 57			if (blocklen_bytes == cnt) {
 58				cnt = 0;
 59				drbg_kcapi_sym(aesctx, out, &data, blocklen_bytes);
 60			}
 61			out[cnt] ^= *pos;
 62			pos++;
 63			cnt++;
 64			len--;
 65		}
 66	}
 67	/* 10.4.3 step 4.2 for last block */
 68	if (cnt)
 69		drbg_kcapi_sym(aesctx, out, &data, blocklen_bytes);
 70}
 71
 72/*
 73 * scratchpad usage: drbg_ctr_update is interlinked with crypto_drbg_ctr_df
 74 * (and drbg_ctr_bcc, but this function does not need any temporary buffers),
 75 * the scratchpad is used as follows:
 76 * drbg_ctr_update:
 77 *	temp
 78 *		start: drbg->scratchpad
 79 *		length: drbg_statelen(drbg) + drbg_blocklen(drbg)
 80 *			note: the cipher writing into this variable works
 81 *			blocklen-wise. Now, when the statelen is not a multiple
 82 *			of blocklen, the generateion loop below "spills over"
 83 *			by at most blocklen. Thus, we need to give sufficient
 84 *			memory.
 85 *	df_data
 86 *		start: drbg->scratchpad +
 87 *				drbg_statelen(drbg) + drbg_blocklen(drbg)
 88 *		length: drbg_statelen(drbg)
 89 *
 90 * crypto_drbg_ctr_df:
 91 *	pad
 92 *		start: df_data + drbg_statelen(drbg)
 93 *		length: drbg_blocklen(drbg)
 94 *	iv
 95 *		start: pad + drbg_blocklen(drbg)
 96 *		length: drbg_blocklen(drbg)
 97 *	temp
 98 *		start: iv + drbg_blocklen(drbg)
 99 *		length: drbg_satelen(drbg) + drbg_blocklen(drbg)
100 *			note: temp is the buffer that the BCC function operates
101 *			on. BCC operates blockwise. drbg_statelen(drbg)
102 *			is sufficient when the DRBG state length is a multiple
103 *			of the block size. For AES192 (and maybe other ciphers)
104 *			this is not correct and the length for temp is
105 *			insufficient (yes, that also means for such ciphers,
106 *			the final output of all BCC rounds are truncated).
107 *			Therefore, add drbg_blocklen(drbg) to cover all
108 *			possibilities.
109 * refer to crypto_drbg_ctr_df_datalen() to get required length
110 */
111
112/* Derivation Function for CTR DRBG as defined in 10.4.2 */
113int crypto_drbg_ctr_df(struct crypto_aes_ctx *aesctx,
114		       unsigned char *df_data, size_t bytes_to_return,
115		       struct list_head *seedlist,
116		       u8 blocklen_bytes,
117		       u8 statelen)
118{
119	unsigned char L_N[8];
120	/* S3 is input */
121	struct drbg_string S1, S2, S4, cipherin;
122	LIST_HEAD(bcc_list);
123	unsigned char *pad = df_data + statelen;
124	unsigned char *iv = pad + blocklen_bytes;
125	unsigned char *temp = iv + blocklen_bytes;
126	size_t padlen = 0;
127	unsigned int templen = 0;
128	/* 10.4.2 step 7 */
129	unsigned int i = 0;
130	/* 10.4.2 step 8 */
131	const unsigned char *K = (unsigned char *)
132			   "\x00\x01\x02\x03\x04\x05\x06\x07"
133			   "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
134			   "\x10\x11\x12\x13\x14\x15\x16\x17"
135			   "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
136	unsigned char *X;
137	size_t generated_len = 0;
138	size_t inputlen = 0;
139	struct drbg_string *seed = NULL;
140	u8 keylen;
141
142	memset(pad, 0, blocklen_bytes);
143	memset(iv, 0, blocklen_bytes);
144	keylen = statelen - blocklen_bytes;
145	/* 10.4.2 step 1 is implicit as we work byte-wise */
146
147	/* 10.4.2 step 2 */
148	if ((512 / 8) < bytes_to_return)
149		return -EINVAL;
150
151	/* 10.4.2 step 2 -- calculate the entire length of all input data */
152	list_for_each_entry(seed, seedlist, list)
153		inputlen += seed->len;
154	drbg_cpu_to_be32(inputlen, &L_N[0]);
155
156	/* 10.4.2 step 3 */
157	drbg_cpu_to_be32(bytes_to_return, &L_N[4]);
158
159	/* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
160	padlen = (inputlen + sizeof(L_N) + 1) % (blocklen_bytes);
161	/* wrap the padlen appropriately */
162	if (padlen)
163		padlen = blocklen_bytes - padlen;
164	/*
165	 * pad / padlen contains the 0x80 byte and the following zero bytes.
166	 * As the calculated padlen value only covers the number of zero
167	 * bytes, this value has to be incremented by one for the 0x80 byte.
168	 */
169	padlen++;
170	pad[0] = 0x80;
171
172	/* 10.4.2 step 4 -- first fill the linked list and then order it */
173	drbg_string_fill(&S1, iv, blocklen_bytes);
174	list_add_tail(&S1.list, &bcc_list);
175	drbg_string_fill(&S2, L_N, sizeof(L_N));
176	list_add_tail(&S2.list, &bcc_list);
177	list_splice_tail(seedlist, &bcc_list);
178	drbg_string_fill(&S4, pad, padlen);
179	list_add_tail(&S4.list, &bcc_list);
180
181	/* 10.4.2 step 9 */
182	while (templen < (keylen + (blocklen_bytes))) {
183		/*
184		 * 10.4.2 step 9.1 - the padding is implicit as the buffer
185		 * holds zeros after allocation -- even the increment of i
186		 * is irrelevant as the increment remains within length of i
187		 */
188		drbg_cpu_to_be32(i, iv);
189		/* 10.4.2 step 9.2 -- BCC and concatenation with temp */
190		drbg_ctr_bcc(aesctx, temp + templen, K, &bcc_list,
191			     blocklen_bytes, keylen);
192		/* 10.4.2 step 9.3 */
193		i++;
194		templen += blocklen_bytes;
195	}
196
197	/* 10.4.2 step 11 */
198	X = temp + (keylen);
199	drbg_string_fill(&cipherin, X, blocklen_bytes);
200
201	/* 10.4.2 step 12: overwriting of outval is implemented in next step */
202
203	/* 10.4.2 step 13 */
204	drbg_kcapi_symsetkey(aesctx, temp, keylen);
205	while (generated_len < bytes_to_return) {
206		short blocklen = 0;
207		/*
208		 * 10.4.2 step 13.1: the truncation of the key length is
209		 * implicit as the key is only drbg_blocklen in size based on
210		 * the implementation of the cipher function callback
211		 */
212		drbg_kcapi_sym(aesctx, X, &cipherin, blocklen_bytes);
213		blocklen = (blocklen_bytes <
214				(bytes_to_return - generated_len)) ?
215			    blocklen_bytes :
216				(bytes_to_return - generated_len);
217		/* 10.4.2 step 13.2 and 14 */
218		memcpy(df_data + generated_len, X, blocklen);
219		generated_len += blocklen;
220	}
221
222	memset(iv, 0, blocklen_bytes);
223	memset(temp, 0, statelen + blocklen_bytes);
224	memset(pad, 0, blocklen_bytes);
225	return 0;
226}
227EXPORT_SYMBOL_GPL(crypto_drbg_ctr_df);
228
229MODULE_IMPORT_NS("CRYPTO_INTERNAL");
230MODULE_LICENSE("GPL v2");
231MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
232MODULE_DESCRIPTION("Derivation Function conformant to SP800-90A");
~/ Read-only file preview.