crypto: poly1305 - expose init/update/final library interface
Expose the existing generic Poly1305 code via a init/update/final library interface so that callers are not required to go through the crypto API's shash abstraction to access it. At the same time, make some preparations so that the library implementation can be superseded by an accelerated arch-specific version in the future. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:

committed by
Herbert Xu

parent
ad8f5b8838
commit
a1d9306409
@@ -154,5 +154,79 @@ void poly1305_core_emit(const struct poly1305_state *state, void *dst)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(poly1305_core_emit);
|
||||
|
||||
void poly1305_init_generic(struct poly1305_desc_ctx *desc, const u8 *key)
|
||||
{
|
||||
poly1305_core_setkey(desc->r, key);
|
||||
desc->s[0] = get_unaligned_le32(key + 16);
|
||||
desc->s[1] = get_unaligned_le32(key + 20);
|
||||
desc->s[2] = get_unaligned_le32(key + 24);
|
||||
desc->s[3] = get_unaligned_le32(key + 28);
|
||||
poly1305_core_init(&desc->h);
|
||||
desc->buflen = 0;
|
||||
desc->sset = true;
|
||||
desc->rset = 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(poly1305_init_generic);
|
||||
|
||||
void poly1305_update_generic(struct poly1305_desc_ctx *desc, const u8 *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
unsigned int bytes;
|
||||
|
||||
if (unlikely(desc->buflen)) {
|
||||
bytes = min(nbytes, POLY1305_BLOCK_SIZE - desc->buflen);
|
||||
memcpy(desc->buf + desc->buflen, src, bytes);
|
||||
src += bytes;
|
||||
nbytes -= bytes;
|
||||
desc->buflen += bytes;
|
||||
|
||||
if (desc->buflen == POLY1305_BLOCK_SIZE) {
|
||||
poly1305_core_blocks(&desc->h, desc->r, desc->buf, 1, 1);
|
||||
desc->buflen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (likely(nbytes >= POLY1305_BLOCK_SIZE)) {
|
||||
poly1305_core_blocks(&desc->h, desc->r, src,
|
||||
nbytes / POLY1305_BLOCK_SIZE, 1);
|
||||
src += nbytes - (nbytes % POLY1305_BLOCK_SIZE);
|
||||
nbytes %= POLY1305_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if (unlikely(nbytes)) {
|
||||
desc->buflen = nbytes;
|
||||
memcpy(desc->buf, src, nbytes);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(poly1305_update_generic);
|
||||
|
||||
void poly1305_final_generic(struct poly1305_desc_ctx *desc, u8 *dst)
|
||||
{
|
||||
__le32 digest[4];
|
||||
u64 f = 0;
|
||||
|
||||
if (unlikely(desc->buflen)) {
|
||||
desc->buf[desc->buflen++] = 1;
|
||||
memset(desc->buf + desc->buflen, 0,
|
||||
POLY1305_BLOCK_SIZE - desc->buflen);
|
||||
poly1305_core_blocks(&desc->h, desc->r, desc->buf, 1, 0);
|
||||
}
|
||||
|
||||
poly1305_core_emit(&desc->h, digest);
|
||||
|
||||
/* mac = (h + s) % (2^128) */
|
||||
f = (f >> 32) + le32_to_cpu(digest[0]) + desc->s[0];
|
||||
put_unaligned_le32(f, dst + 0);
|
||||
f = (f >> 32) + le32_to_cpu(digest[1]) + desc->s[1];
|
||||
put_unaligned_le32(f, dst + 4);
|
||||
f = (f >> 32) + le32_to_cpu(digest[2]) + desc->s[2];
|
||||
put_unaligned_le32(f, dst + 8);
|
||||
f = (f >> 32) + le32_to_cpu(digest[3]) + desc->s[3];
|
||||
put_unaligned_le32(f, dst + 12);
|
||||
|
||||
*desc = (struct poly1305_desc_ctx){};
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(poly1305_final_generic);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
|
||||
|
Reference in New Issue
Block a user