Commit ca786dc738f4f583b57b1bba7a335b5e8233f4b0

Authored by Herbert Xu
1 parent caee16883a

crypto: hash - Fixed digest size check

The digest size check on hash algorithms is incorrect.  It's
perfectly valid for hash algorithms to have a digest length
longer than their block size.  For example crc32c has a block
size of 1 and a digest size of 4.  Rather than having it lie
about its block size, this patch fixes the checks to do what
they really should which is to bound the digest size so that
code placing the digest on the stack continue to work.

HMAC however still needs to check this as it's only defined
for such algorithms.

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

Showing 4 changed files with 13 additions and 9 deletions Side-by-side Diff

... ... @@ -68,7 +68,7 @@
68 68 struct ahash_alg *alg = &tfm->__crt_alg->cra_ahash;
69 69 struct ahash_tfm *crt = &tfm->crt_ahash;
70 70  
71   - if (alg->digestsize > crypto_tfm_alg_blocksize(tfm))
  71 + if (alg->digestsize > PAGE_SIZE / 8)
72 72 return -EINVAL;
73 73  
74 74 crt->init = alg->init;
... ... @@ -141,7 +141,7 @@
141 141 struct hash_tfm *ops = &tfm->crt_hash;
142 142 struct digest_alg *dalg = &tfm->__crt_alg->cra_digest;
143 143  
144   - if (dalg->dia_digestsize > crypto_tfm_alg_blocksize(tfm))
  144 + if (dalg->dia_digestsize > PAGE_SIZE / 8)
145 145 return -EINVAL;
146 146  
147 147 ops->init = init;
... ... @@ -152,7 +152,7 @@
152 152 {
153 153 struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
154 154  
155   - if (alg->digestsize > crypto_tfm_alg_blocksize(tfm))
  155 + if (alg->digestsize > PAGE_SIZE / 8)
156 156 return -EINVAL;
157 157  
158 158 if ((mask & CRYPTO_ALG_TYPE_HASH_MASK) != CRYPTO_ALG_TYPE_HASH_MASK)
... ... @@ -226,6 +226,7 @@
226 226 struct crypto_instance *inst;
227 227 struct crypto_alg *alg;
228 228 int err;
  229 + int ds;
229 230  
230 231 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
231 232 if (err)
... ... @@ -236,6 +237,13 @@
236 237 if (IS_ERR(alg))
237 238 return ERR_CAST(alg);
238 239  
  240 + inst = ERR_PTR(-EINVAL);
  241 + ds = (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
  242 + CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
  243 + alg->cra_digest.dia_digestsize;
  244 + if (ds > alg->cra_blocksize)
  245 + goto out_put_alg;
  246 +
239 247 inst = crypto_alloc_instance("hmac", alg);
240 248 if (IS_ERR(inst))
241 249 goto out_put_alg;
242 250  
... ... @@ -246,14 +254,10 @@
246 254 inst->alg.cra_alignmask = alg->cra_alignmask;
247 255 inst->alg.cra_type = &crypto_hash_type;
248 256  
249   - inst->alg.cra_hash.digestsize =
250   - (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
251   - CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
252   - alg->cra_digest.dia_digestsize;
  257 + inst->alg.cra_hash.digestsize = ds;
253 258  
254 259 inst->alg.cra_ctxsize = sizeof(struct hmac_ctx) +
255   - ALIGN(inst->alg.cra_blocksize * 2 +
256   - inst->alg.cra_hash.digestsize,
  260 + ALIGN(inst->alg.cra_blocksize * 2 + ds,
257 261 sizeof(void *));
258 262  
259 263 inst->alg.cra_init = hmac_init_tfm;