crypto: hash - Zap unaligned buffers
authorHerbert Xu <herbert@gondor.apana.org.au>
Tue, 14 Jul 2009 13:35:36 +0000 (21:35 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Tue, 14 Jul 2009 13:35:36 +0000 (21:35 +0800)
Some unaligned buffers on the stack weren't zapped properly which
may cause secret data to be leaked.  This patch fixes them by doing
a zero memset.

It is also possible for us to place random kernel stack contents
in the digest buffer if a digest operation fails.  This is fixed
by only copying if the operation succeeded.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/ahash.c
crypto/shash.c

index cc824ef..1576f95 100644 (file)
@@ -152,8 +152,7 @@ static int ahash_setkey_unaligned(struct crypto_ahash *tfm, const u8 *key,
        alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
        memcpy(alignbuffer, key, keylen);
        ret = ahash->setkey(tfm, alignbuffer, keylen);
        alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
        memcpy(alignbuffer, key, keylen);
        ret = ahash->setkey(tfm, alignbuffer, keylen);
-       memset(alignbuffer, 0, keylen);
-       kfree(buffer);
+       kzfree(buffer);
        return ret;
 }
 
        return ret;
 }
 
index fd92c03..e543283 100644 (file)
@@ -45,8 +45,7 @@ static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
        alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
        memcpy(alignbuffer, key, keylen);
        err = shash->setkey(tfm, alignbuffer, keylen);
        alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
        memcpy(alignbuffer, key, keylen);
        err = shash->setkey(tfm, alignbuffer, keylen);
-       memset(alignbuffer, 0, keylen);
-       kfree(buffer);
+       kzfree(buffer);
        return err;
 }
 
        return err;
 }
 
@@ -79,13 +78,16 @@ static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
                                     ((unsigned long)data & alignmask);
        u8 buf[shash_align_buffer_size(unaligned_len, alignmask)]
                __attribute__ ((aligned));
                                     ((unsigned long)data & alignmask);
        u8 buf[shash_align_buffer_size(unaligned_len, alignmask)]
                __attribute__ ((aligned));
+       int err;
 
        if (unaligned_len > len)
                unaligned_len = len;
 
        memcpy(buf, data, unaligned_len);
 
        if (unaligned_len > len)
                unaligned_len = len;
 
        memcpy(buf, data, unaligned_len);
+       err = shash->update(desc, buf, unaligned_len);
+       memset(buf, 0, unaligned_len);
 
 
-       return shash->update(desc, buf, unaligned_len) ?:
+       return err ?:
               shash->update(desc, data + unaligned_len, len - unaligned_len);
 }
 
               shash->update(desc, data + unaligned_len, len - unaligned_len);
 }
 
@@ -114,7 +116,13 @@ static int shash_final_unaligned(struct shash_desc *desc, u8 *out)
        int err;
 
        err = shash->final(desc, buf);
        int err;
 
        err = shash->final(desc, buf);
+       if (err)
+               goto out;
+
        memcpy(out, buf, ds);
        memcpy(out, buf, ds);
+
+out:
+       memset(buf, 0, ds);
        return err;
 }
 
        return err;
 }