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

Configure Feed

Select the types of activity you want to include in your feed.

crypto: shash - Handle partial blocks in API

Provide an option to handle the partial blocks in the shash API.
Almost every hash algorithm has a block size and are only able
to hash partial blocks on finalisation.

Rather than duplicating the partial block handling many times,
add this functionality to the shash API.

It is optional (e.g., hmac would never need this by relying on
the partial block handling of the underlying hash), and to enable
it set the bit CRYPTO_AHASH_ALG_BLOCK_ONLY.

The export format is always that of the underlying hash export,
plus the partial block buffer, followed by a single-byte for the
partial block length.

Set the bit CRYPTO_AHASH_ALG_FINAL_NONZERO to withhold an extra
byte in the partial block. This will come in handy when this
is extended to ahash where hardware often can't deal with a
zero-length final.

It will also be used for algorithms requiring an extra block for
finalisation (e.g., cmac).

As an optimisation, set the bit CRYPTO_AHASH_ALG_FINUP_MAX if
the algorithm wishes to get as much data as possible instead of
just the last partial block.

The descriptor will be zeroed after finalisation.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+271 -79
+190 -39
crypto/shash.c
··· 16 16 17 17 #include "hash.h" 18 18 19 + static inline bool crypto_shash_block_only(struct crypto_shash *tfm) 20 + { 21 + return crypto_shash_alg(tfm)->base.cra_flags & 22 + CRYPTO_AHASH_ALG_BLOCK_ONLY; 23 + } 24 + 25 + static inline bool crypto_shash_final_nonzero(struct crypto_shash *tfm) 26 + { 27 + return crypto_shash_alg(tfm)->base.cra_flags & 28 + CRYPTO_AHASH_ALG_FINAL_NONZERO; 29 + } 30 + 31 + static inline bool crypto_shash_finup_max(struct crypto_shash *tfm) 32 + { 33 + return crypto_shash_alg(tfm)->base.cra_flags & 34 + CRYPTO_AHASH_ALG_FINUP_MAX; 35 + } 36 + 19 37 int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, 20 38 unsigned int keylen) 21 39 { ··· 64 46 } 65 47 EXPORT_SYMBOL_GPL(crypto_shash_setkey); 66 48 67 - int crypto_shash_update(struct shash_desc *desc, const u8 *data, 68 - unsigned int len) 49 + static int __crypto_shash_init(struct shash_desc *desc) 69 50 { 70 - return crypto_shash_alg(desc->tfm)->update(desc, data, len); 71 - } 72 - EXPORT_SYMBOL_GPL(crypto_shash_update); 51 + struct crypto_shash *tfm = desc->tfm; 73 52 74 - int crypto_shash_final(struct shash_desc *desc, u8 *out) 75 - { 76 - return crypto_shash_alg(desc->tfm)->final(desc, out); 53 + if (crypto_shash_block_only(tfm)) { 54 + u8 *buf = shash_desc_ctx(desc); 55 + 56 + buf += crypto_shash_descsize(tfm) - 1; 57 + *buf = 0; 58 + } 59 + 60 + return crypto_shash_alg(tfm)->init(desc); 77 61 } 78 - EXPORT_SYMBOL_GPL(crypto_shash_final); 62 + 63 + int crypto_shash_init(struct shash_desc *desc) 64 + { 65 + if (crypto_shash_get_flags(desc->tfm) & CRYPTO_TFM_NEED_KEY) 66 + return -ENOKEY; 67 + return __crypto_shash_init(desc); 68 + } 69 + EXPORT_SYMBOL_GPL(crypto_shash_init); 79 70 80 71 static int shash_default_finup(struct shash_desc *desc, const u8 *data, 81 72 unsigned int len, u8 *out) ··· 95 68 shash->final(desc, out); 96 69 } 97 70 98 - int crypto_shash_finup(struct shash_desc *desc, const u8 *data, 99 - unsigned int len, u8 *out) 71 + static int crypto_shash_op_and_zero( 72 + int (*op)(struct shash_desc *desc, const u8 *data, 73 + unsigned int len, u8 *out), 74 + struct shash_desc *desc, const u8 *data, unsigned int len, u8 *out) 100 75 { 101 - return crypto_shash_alg(desc->tfm)->finup(desc, data, len, out); 76 + int err; 77 + 78 + err = op(desc, data, len, out); 79 + memset(shash_desc_ctx(desc), 0, crypto_shash_descsize(desc->tfm)); 80 + return err; 81 + } 82 + 83 + int crypto_shash_finup(struct shash_desc *restrict desc, const u8 *data, 84 + unsigned int len, u8 *restrict out) 85 + { 86 + struct crypto_shash *tfm = desc->tfm; 87 + u8 *blenp = shash_desc_ctx(desc); 88 + bool finup_max, nonzero; 89 + unsigned int bs; 90 + int err; 91 + u8 *buf; 92 + 93 + if (!crypto_shash_block_only(tfm)) { 94 + if (out) 95 + goto finup; 96 + return crypto_shash_alg(tfm)->update(desc, data, len); 97 + } 98 + 99 + finup_max = out && crypto_shash_finup_max(tfm); 100 + 101 + /* Retain extra block for final nonzero algorithms. */ 102 + nonzero = crypto_shash_final_nonzero(tfm); 103 + 104 + /* 105 + * The partial block buffer follows the algorithm desc context. 106 + * The byte following that contains the length. 107 + */ 108 + blenp += crypto_shash_descsize(tfm) - 1; 109 + bs = crypto_shash_blocksize(tfm); 110 + buf = blenp - bs; 111 + 112 + if (likely(!*blenp && finup_max)) 113 + goto finup; 114 + 115 + while ((*blenp + len) >= bs + nonzero) { 116 + unsigned int nbytes = len - nonzero; 117 + const u8 *src = data; 118 + 119 + if (*blenp) { 120 + memcpy(buf + *blenp, data, bs - *blenp); 121 + nbytes = bs; 122 + src = buf; 123 + } 124 + 125 + err = crypto_shash_alg(tfm)->update(desc, src, nbytes); 126 + if (err < 0) 127 + return err; 128 + 129 + data += nbytes - err - *blenp; 130 + len -= nbytes - err - *blenp; 131 + *blenp = 0; 132 + } 133 + 134 + if (*blenp || !out) { 135 + memcpy(buf + *blenp, data, len); 136 + *blenp += len; 137 + if (!out) 138 + return 0; 139 + data = buf; 140 + len = *blenp; 141 + } 142 + 143 + finup: 144 + return crypto_shash_op_and_zero(crypto_shash_alg(tfm)->finup, desc, 145 + data, len, out); 102 146 } 103 147 EXPORT_SYMBOL_GPL(crypto_shash_finup); 104 148 105 149 static int shash_default_digest(struct shash_desc *desc, const u8 *data, 106 150 unsigned int len, u8 *out) 107 151 { 108 - struct shash_alg *shash = crypto_shash_alg(desc->tfm); 109 - 110 - return shash->init(desc) ?: 111 - shash->finup(desc, data, len, out); 152 + return __crypto_shash_init(desc) ?: 153 + crypto_shash_finup(desc, data, len, out); 112 154 } 113 155 114 156 int crypto_shash_digest(struct shash_desc *desc, const u8 *data, ··· 188 92 if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 189 93 return -ENOKEY; 190 94 191 - return crypto_shash_alg(tfm)->digest(desc, data, len, out); 95 + return crypto_shash_op_and_zero(crypto_shash_alg(tfm)->digest, desc, 96 + data, len, out); 192 97 } 193 98 EXPORT_SYMBOL_GPL(crypto_shash_digest); 194 99 ··· 197 100 unsigned int len, u8 *out) 198 101 { 199 102 SHASH_DESC_ON_STACK(desc, tfm); 200 - int err; 201 103 202 104 desc->tfm = tfm; 203 - 204 - err = crypto_shash_digest(desc, data, len, out); 205 - 206 - shash_desc_zero(desc); 207 - 208 - return err; 105 + return crypto_shash_digest(desc, data, len, out); 209 106 } 210 107 EXPORT_SYMBOL_GPL(crypto_shash_tfm_digest); 108 + 109 + int crypto_shash_export_core(struct shash_desc *desc, void *out) 110 + { 111 + int (*export)(struct shash_desc *desc, void *out); 112 + struct crypto_shash *tfm = desc->tfm; 113 + u8 *buf = shash_desc_ctx(desc); 114 + unsigned int plen, ss; 115 + 116 + plen = crypto_shash_blocksize(tfm) + 1; 117 + ss = crypto_shash_statesize(tfm); 118 + if (crypto_shash_block_only(tfm)) 119 + ss -= plen; 120 + export = crypto_shash_alg(tfm)->export; 121 + if (!export) { 122 + memcpy(out, buf, ss); 123 + return 0; 124 + } 125 + 126 + return export(desc, out); 127 + } 128 + EXPORT_SYMBOL_GPL(crypto_shash_export_core); 211 129 212 130 int crypto_shash_export(struct shash_desc *desc, void *out) 213 131 { 214 132 struct crypto_shash *tfm = desc->tfm; 215 - struct shash_alg *shash = crypto_shash_alg(tfm); 216 133 217 - if (shash->export) 218 - return shash->export(desc, out); 134 + if (crypto_shash_block_only(tfm)) { 135 + unsigned int plen = crypto_shash_blocksize(tfm) + 1; 136 + unsigned int descsize = crypto_shash_descsize(tfm); 137 + unsigned int ss = crypto_shash_statesize(tfm); 138 + u8 *buf = shash_desc_ctx(desc); 219 139 220 - memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(tfm)); 221 - return 0; 140 + memcpy(out + ss - plen, buf + descsize - plen, plen); 141 + } 142 + return crypto_shash_export_core(desc, out); 222 143 } 223 144 EXPORT_SYMBOL_GPL(crypto_shash_export); 224 145 225 - int crypto_shash_import(struct shash_desc *desc, const void *in) 146 + int crypto_shash_import_core(struct shash_desc *desc, const void *in) 226 147 { 148 + int (*import)(struct shash_desc *desc, const void *in); 227 149 struct crypto_shash *tfm = desc->tfm; 228 - struct shash_alg *shash = crypto_shash_alg(tfm); 150 + unsigned int descsize, plen, ss; 151 + u8 *buf = shash_desc_ctx(desc); 229 152 230 153 if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 231 154 return -ENOKEY; 232 155 233 - if (shash->import) 234 - return shash->import(desc, in); 156 + plen = crypto_shash_blocksize(tfm) + 1; 157 + descsize = crypto_shash_descsize(tfm); 158 + ss = crypto_shash_statesize(tfm); 159 + buf[descsize - 1] = 0; 160 + if (crypto_shash_block_only(tfm)) 161 + ss -= plen; 162 + import = crypto_shash_alg(tfm)->import; 163 + if (!import) { 164 + memcpy(buf, in, ss); 165 + return 0; 166 + } 235 167 236 - memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(tfm)); 237 - return 0; 168 + return import(desc, in); 169 + } 170 + EXPORT_SYMBOL_GPL(crypto_shash_import_core); 171 + 172 + int crypto_shash_import(struct shash_desc *desc, const void *in) 173 + { 174 + struct crypto_shash *tfm = desc->tfm; 175 + int err; 176 + 177 + err = crypto_shash_import_core(desc, in); 178 + if (crypto_shash_block_only(tfm)) { 179 + unsigned int plen = crypto_shash_blocksize(tfm) + 1; 180 + unsigned int descsize = crypto_shash_descsize(tfm); 181 + unsigned int ss = crypto_shash_statesize(tfm); 182 + u8 *buf = shash_desc_ctx(desc); 183 + 184 + memcpy(buf + descsize - plen, in + ss - plen, plen); 185 + if (buf[descsize - 1] >= plen) 186 + err = -EOVERFLOW; 187 + } 188 + return err; 238 189 } 239 190 EXPORT_SYMBOL_GPL(crypto_shash_import); 240 191 ··· 438 293 struct crypto_alg *base = &alg->halg.base; 439 294 int err; 440 295 441 - if (alg->descsize > HASH_MAX_DESCSIZE) 442 - return -EINVAL; 443 - 444 296 if ((alg->export && !alg->import) || (alg->import && !alg->export)) 445 297 return -EINVAL; 446 298 ··· 463 321 alg->finup = shash_default_finup; 464 322 if (!alg->digest) 465 323 alg->digest = shash_default_digest; 466 - if (!alg->export) 324 + if (!alg->export && !alg->halg.statesize) 467 325 alg->halg.statesize = alg->descsize; 468 326 if (!alg->setkey) 469 327 alg->setkey = shash_no_setkey; 328 + 329 + if (base->cra_flags & CRYPTO_AHASH_ALG_BLOCK_ONLY) { 330 + BUILD_BUG_ON(MAX_ALGAPI_BLOCKSIZE >= 256); 331 + alg->descsize += base->cra_blocksize + 1; 332 + alg->statesize += base->cra_blocksize + 1; 333 + } 334 + 335 + if (alg->descsize > HASH_MAX_DESCSIZE) 336 + return -EINVAL; 470 337 471 338 return 0; 472 339 }
+64 -40
include/crypto/hash.h
··· 85 85 * transformation object. Data processing can happen synchronously 86 86 * [SHASH] or asynchronously [AHASH] at this point. Driver must not use 87 87 * req->result. 88 + * For block-only algorithms, @update must return the number 89 + * of bytes to store in the API partial block buffer. 88 90 * @final: **[mandatory]** Retrieve result from the driver. This function finalizes the 89 91 * transformation and retrieves the resulting hash from the driver and 90 92 * pushes it back to upper layers. No data processing happens at this ··· 908 906 int crypto_shash_export(struct shash_desc *desc, void *out); 909 907 910 908 /** 909 + * crypto_shash_export_core() - extract core state for message digest 910 + * @desc: reference to the operational state handle whose state is exported 911 + * @out: output buffer of sufficient size that can hold the hash state 912 + * 913 + * Export the hash state without the partial block buffer. 914 + * 915 + * Context: Softirq or process context. 916 + * Return: 0 if the export creation was successful; < 0 if an error occurred 917 + */ 918 + int crypto_shash_export_core(struct shash_desc *desc, void *out); 919 + 920 + /** 911 921 * crypto_shash_import() - import operational state 912 922 * @desc: reference to the operational state handle the state imported into 913 923 * @in: buffer holding the state ··· 934 920 int crypto_shash_import(struct shash_desc *desc, const void *in); 935 921 936 922 /** 923 + * crypto_shash_import_core() - import core state 924 + * @desc: reference to the operational state handle the state imported into 925 + * @in: buffer holding the state 926 + * 927 + * Import the hash state without the partial block buffer. 928 + * 929 + * Context: Softirq or process context. 930 + * Return: 0 if the import was successful; < 0 if an error occurred 931 + */ 932 + int crypto_shash_import_core(struct shash_desc *desc, const void *in); 933 + 934 + /** 937 935 * crypto_shash_init() - (re)initialize message digest 938 936 * @desc: operational state handle that is already filled 939 937 * ··· 957 931 * Return: 0 if the message digest initialization was successful; < 0 if an 958 932 * error occurred 959 933 */ 960 - static inline int crypto_shash_init(struct shash_desc *desc) 961 - { 962 - struct crypto_shash *tfm = desc->tfm; 963 - 964 - if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 965 - return -ENOKEY; 966 - 967 - return crypto_shash_alg(tfm)->init(desc); 968 - } 969 - 970 - /** 971 - * crypto_shash_update() - add data to message digest for processing 972 - * @desc: operational state handle that is already initialized 973 - * @data: input data to be added to the message digest 974 - * @len: length of the input data 975 - * 976 - * Updates the message digest state of the operational state handle. 977 - * 978 - * Context: Softirq or process context. 979 - * Return: 0 if the message digest update was successful; < 0 if an error 980 - * occurred 981 - */ 982 - int crypto_shash_update(struct shash_desc *desc, const u8 *data, 983 - unsigned int len); 984 - 985 - /** 986 - * crypto_shash_final() - calculate message digest 987 - * @desc: operational state handle that is already filled with data 988 - * @out: output buffer filled with the message digest 989 - * 990 - * Finalize the message digest operation and create the message digest 991 - * based on all data added to the cipher handle. The message digest is placed 992 - * into the output buffer. The caller must ensure that the output buffer is 993 - * large enough by using crypto_shash_digestsize. 994 - * 995 - * Context: Softirq or process context. 996 - * Return: 0 if the message digest creation was successful; < 0 if an error 997 - * occurred 998 - */ 999 - int crypto_shash_final(struct shash_desc *desc, u8 *out); 934 + int crypto_shash_init(struct shash_desc *desc); 1000 935 1001 936 /** 1002 937 * crypto_shash_finup() - calculate message digest of buffer ··· 976 989 */ 977 990 int crypto_shash_finup(struct shash_desc *desc, const u8 *data, 978 991 unsigned int len, u8 *out); 992 + 993 + /** 994 + * crypto_shash_update() - add data to message digest for processing 995 + * @desc: operational state handle that is already initialized 996 + * @data: input data to be added to the message digest 997 + * @len: length of the input data 998 + * 999 + * Updates the message digest state of the operational state handle. 1000 + * 1001 + * Context: Softirq or process context. 1002 + * Return: 0 if the message digest update was successful; < 0 if an error 1003 + * occurred 1004 + */ 1005 + static inline int crypto_shash_update(struct shash_desc *desc, const u8 *data, 1006 + unsigned int len) 1007 + { 1008 + return crypto_shash_finup(desc, data, len, NULL); 1009 + } 1010 + 1011 + /** 1012 + * crypto_shash_final() - calculate message digest 1013 + * @desc: operational state handle that is already filled with data 1014 + * @out: output buffer filled with the message digest 1015 + * 1016 + * Finalize the message digest operation and create the message digest 1017 + * based on all data added to the cipher handle. The message digest is placed 1018 + * into the output buffer. The caller must ensure that the output buffer is 1019 + * large enough by using crypto_shash_digestsize. 1020 + * 1021 + * Context: Softirq or process context. 1022 + * Return: 0 if the message digest creation was successful; < 0 if an error 1023 + * occurred 1024 + */ 1025 + static inline int crypto_shash_final(struct shash_desc *desc, u8 *out) 1026 + { 1027 + return crypto_shash_finup(desc, NULL, 0, out); 1028 + } 979 1029 980 1030 static inline void shash_desc_zero(struct shash_desc *desc) 981 1031 {
+15
include/crypto/internal/hash.h
··· 11 11 #include <crypto/algapi.h> 12 12 #include <crypto/hash.h> 13 13 14 + /* Set this bit to handle partial blocks in the API. */ 15 + #define CRYPTO_AHASH_ALG_BLOCK_ONLY 0x01000000 16 + 17 + /* Set this bit if final requires at least one byte. */ 18 + #define CRYPTO_AHASH_ALG_FINAL_NONZERO 0x02000000 19 + 20 + /* Set this bit if finup can deal with multiple blocks. */ 21 + #define CRYPTO_AHASH_ALG_FINUP_MAX 0x04000000 22 + 14 23 #define HASH_FBREQ_ON_STACK(name, req) \ 15 24 char __##name##_req[sizeof(struct ahash_request) + \ 16 25 MAX_SYNC_HASH_REQSIZE] CRYPTO_MINALIGN_ATTR; \ ··· 288 279 req->nbytes = old->nbytes; 289 280 290 281 return req; 282 + } 283 + 284 + /* Return the state size without partial block for block-only algorithms. */ 285 + static inline unsigned int crypto_shash_coresize(struct crypto_shash *tfm) 286 + { 287 + return crypto_shash_statesize(tfm) - crypto_shash_blocksize(tfm) - 1; 291 288 } 292 289 293 290 #endif /* _CRYPTO_INTERNAL_HASH_H */
+2
include/linux/crypto.h
··· 136 136 /* Set if the algorithm supports request chains and virtual addresses. */ 137 137 #define CRYPTO_ALG_REQ_CHAIN 0x00040000 138 138 139 + /* The high bits 0xff000000 are reserved for type-specific flags. */ 140 + 139 141 /* 140 142 * Transform masks and values (for crt_flags). 141 143 */