/* Rijndael (AES) for GnuPG - PowerPC Vector Crypto AES implementation
* Copyright 2021- IBM Inc. All rights reserved
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see .
*
* Alternatively, this code may be used in OpenSSL from The OpenSSL Project,
* and Cryptogams by Andy Polyakov, and if made part of a release of either
* or both projects, is thereafter dual-licensed under the license said project
* is released under.
*/
#include
#include "rijndael-internal.h"
#include "cipher-internal.h"
#include "bufhelp.h"
#ifdef USE_PPC_CRYPTO_WITH_PPC9LE
extern size_t _gcry_ppc10_aes_gcm_encrypt (const void *inp, void *out,
size_t len,
const unsigned char *key,
unsigned char iv[16], void *Xip);
extern size_t _gcry_ppc10_aes_gcm_decrypt (const void *inp, void *out,
size_t len,
const unsigned char *key,
unsigned char iv[16], void *Xip);
size_t
_gcry_aes_p10le_gcm_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks, int encrypt)
{
RIJNDAEL_context *ctx = (RIJNDAEL_context *) &c->context.c;
unsigned char *rk = (unsigned char *) ctx->u1.keyschedule;
unsigned char *gcm_table = (unsigned char *) c->u_mode.gcm.gcm_table;
unsigned char *iv = c->u_ctr.ctr;
unsigned char *Xi = c->u_mode.gcm.u_tag.tag;
int s = 0;
int ndone = 0;
int ctr_reset = 0;
size_t len = nblocks * GCRY_GCM_BLOCK_LEN;
u64 blocks_unused;
u64 nb = nblocks;
u64 next_ctr = 0;
unsigned char ctr_saved[12];
unsigned char *inp = (unsigned char *) inbuf_arg;
unsigned char *out = (unsigned char *) outbuf_arg;
/*
* This is what the aes-gcm asembly code expects some input parameters.
*
* - Number of rounds is at 480 offset from rk (rk->rounds)
* - Xi at 256 offset from gcm_table
*/
gcry_assert (sizeof(c->u_mode.gcm.gcm_table) >= 256 + 16);
buf_cpy (gcm_table+256, Xi, 16);
buf_cpy (ctr_saved, c->u_ctr.ctr, 12);
while (nb)
{
blocks_unused = (u64) 0xffffffffU + 1 - (u64) buf_get_be32 (iv + 12);
if (nb > blocks_unused)
{
len = blocks_unused * GCRY_GCM_BLOCK_LEN;
nb -= blocks_unused;
next_ctr = blocks_unused;
ctr_reset = 1;
}
else
{
len = nb * GCRY_GCM_BLOCK_LEN;
next_ctr = nb;
nb = 0;
}
if (encrypt)
s = _gcry_ppc10_aes_gcm_encrypt((const void *) inp, (void *) out, len,
(const unsigned char *) rk, iv,
(void *) gcm_table);
else
s = _gcry_ppc10_aes_gcm_decrypt((const void *) inp, (void *) out, len,
(const unsigned char *) rk, iv,
(void *) gcm_table);
cipher_block_add(c->u_ctr.ctr, next_ctr, GCRY_GCM_BLOCK_LEN);
if (ctr_reset)
{
ctr_reset = 0;
inp += len;
out += len;
}
buf_cpy (c->u_ctr.ctr, ctr_saved, 12);
ndone += s;
}
buf_cpy (Xi, gcm_table+256, 16);
/*
* Return number of blocks done.
*/
s = ndone / GCRY_GCM_BLOCK_LEN;
s = nblocks - s;
return ( s );
}
#endif /* USE_PPC_CRYPTO_WITH_PPC9LE */