Path: blob/main/contrib/bearssl/src/symcipher/aes_pwr8_cbcenc.c
39482 views
/*1* Copyright (c) 2017 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#define BR_POWER_ASM_MACROS 125#include "inner.h"2627#if BR_POWER82829/* see bearssl_block.h */30void31br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx,32const void *key, size_t len)33{34ctx->vtable = &br_aes_pwr8_cbcenc_vtable;35ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len);36}3738static void39cbcenc_128(const unsigned char *sk,40const unsigned char *iv, unsigned char *buf, size_t len)41{42long cc;4344#if BR_POWER8_LE45static const uint32_t idx2be[] = {460x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C47};48#endif4950cc = 0;51asm volatile (5253/*54* Load subkeys into v0..v1055*/56lxvw4x(32, %[cc], %[sk])57addi(%[cc], %[cc], 16)58lxvw4x(33, %[cc], %[sk])59addi(%[cc], %[cc], 16)60lxvw4x(34, %[cc], %[sk])61addi(%[cc], %[cc], 16)62lxvw4x(35, %[cc], %[sk])63addi(%[cc], %[cc], 16)64lxvw4x(36, %[cc], %[sk])65addi(%[cc], %[cc], 16)66lxvw4x(37, %[cc], %[sk])67addi(%[cc], %[cc], 16)68lxvw4x(38, %[cc], %[sk])69addi(%[cc], %[cc], 16)70lxvw4x(39, %[cc], %[sk])71addi(%[cc], %[cc], 16)72lxvw4x(40, %[cc], %[sk])73addi(%[cc], %[cc], 16)74lxvw4x(41, %[cc], %[sk])75addi(%[cc], %[cc], 16)76lxvw4x(42, %[cc], %[sk])7778#if BR_POWER8_LE79/*80* v15 = constant for byteswapping words81*/82lxvw4x(47, 0, %[idx2be])83#endif84/*85* Load IV into v16.86*/87lxvw4x(48, 0, %[iv])88#if BR_POWER8_LE89vperm(16, 16, 16, 15)90#endif9192mtctr(%[num_blocks])93label(loop)94/*95* Load next plaintext word and XOR with current IV.96*/97lxvw4x(49, 0, %[buf])98#if BR_POWER8_LE99vperm(17, 17, 17, 15)100#endif101vxor(16, 16, 17)102103/*104* Encrypt the block.105*/106vxor(16, 16, 0)107vcipher(16, 16, 1)108vcipher(16, 16, 2)109vcipher(16, 16, 3)110vcipher(16, 16, 4)111vcipher(16, 16, 5)112vcipher(16, 16, 6)113vcipher(16, 16, 7)114vcipher(16, 16, 8)115vcipher(16, 16, 9)116vcipherlast(16, 16, 10)117118/*119* Store back result (with byteswap)120*/121#if BR_POWER8_LE122vperm(17, 16, 16, 15)123stxvw4x(49, 0, %[buf])124#else125stxvw4x(48, 0, %[buf])126#endif127addi(%[buf], %[buf], 16)128129bdnz(loop)130131: [cc] "+b" (cc), [buf] "+b" (buf)132: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)133#if BR_POWER8_LE134, [idx2be] "b" (idx2be)135#endif136: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",137"v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",138"ctr", "memory"139);140}141142static void143cbcenc_192(const unsigned char *sk,144const unsigned char *iv, unsigned char *buf, size_t len)145{146long cc;147148#if BR_POWER8_LE149static const uint32_t idx2be[] = {1500x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C151};152#endif153154cc = 0;155asm volatile (156157/*158* Load subkeys into v0..v12159*/160lxvw4x(32, %[cc], %[sk])161addi(%[cc], %[cc], 16)162lxvw4x(33, %[cc], %[sk])163addi(%[cc], %[cc], 16)164lxvw4x(34, %[cc], %[sk])165addi(%[cc], %[cc], 16)166lxvw4x(35, %[cc], %[sk])167addi(%[cc], %[cc], 16)168lxvw4x(36, %[cc], %[sk])169addi(%[cc], %[cc], 16)170lxvw4x(37, %[cc], %[sk])171addi(%[cc], %[cc], 16)172lxvw4x(38, %[cc], %[sk])173addi(%[cc], %[cc], 16)174lxvw4x(39, %[cc], %[sk])175addi(%[cc], %[cc], 16)176lxvw4x(40, %[cc], %[sk])177addi(%[cc], %[cc], 16)178lxvw4x(41, %[cc], %[sk])179addi(%[cc], %[cc], 16)180lxvw4x(42, %[cc], %[sk])181addi(%[cc], %[cc], 16)182lxvw4x(43, %[cc], %[sk])183addi(%[cc], %[cc], 16)184lxvw4x(44, %[cc], %[sk])185186#if BR_POWER8_LE187/*188* v15 = constant for byteswapping words189*/190lxvw4x(47, 0, %[idx2be])191#endif192/*193* Load IV into v16.194*/195lxvw4x(48, 0, %[iv])196#if BR_POWER8_LE197vperm(16, 16, 16, 15)198#endif199200mtctr(%[num_blocks])201label(loop)202/*203* Load next plaintext word and XOR with current IV.204*/205lxvw4x(49, 0, %[buf])206#if BR_POWER8_LE207vperm(17, 17, 17, 15)208#endif209vxor(16, 16, 17)210211/*212* Encrypt the block.213*/214vxor(16, 16, 0)215vcipher(16, 16, 1)216vcipher(16, 16, 2)217vcipher(16, 16, 3)218vcipher(16, 16, 4)219vcipher(16, 16, 5)220vcipher(16, 16, 6)221vcipher(16, 16, 7)222vcipher(16, 16, 8)223vcipher(16, 16, 9)224vcipher(16, 16, 10)225vcipher(16, 16, 11)226vcipherlast(16, 16, 12)227228/*229* Store back result (with byteswap)230*/231#if BR_POWER8_LE232vperm(17, 16, 16, 15)233stxvw4x(49, 0, %[buf])234#else235stxvw4x(48, 0, %[buf])236#endif237addi(%[buf], %[buf], 16)238239bdnz(loop)240241: [cc] "+b" (cc), [buf] "+b" (buf)242: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)243#if BR_POWER8_LE244, [idx2be] "b" (idx2be)245#endif246: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",247"v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",248"ctr", "memory"249);250}251252static void253cbcenc_256(const unsigned char *sk,254const unsigned char *iv, unsigned char *buf, size_t len)255{256long cc;257258#if BR_POWER8_LE259static const uint32_t idx2be[] = {2600x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C261};262#endif263264cc = 0;265asm volatile (266267/*268* Load subkeys into v0..v14269*/270lxvw4x(32, %[cc], %[sk])271addi(%[cc], %[cc], 16)272lxvw4x(33, %[cc], %[sk])273addi(%[cc], %[cc], 16)274lxvw4x(34, %[cc], %[sk])275addi(%[cc], %[cc], 16)276lxvw4x(35, %[cc], %[sk])277addi(%[cc], %[cc], 16)278lxvw4x(36, %[cc], %[sk])279addi(%[cc], %[cc], 16)280lxvw4x(37, %[cc], %[sk])281addi(%[cc], %[cc], 16)282lxvw4x(38, %[cc], %[sk])283addi(%[cc], %[cc], 16)284lxvw4x(39, %[cc], %[sk])285addi(%[cc], %[cc], 16)286lxvw4x(40, %[cc], %[sk])287addi(%[cc], %[cc], 16)288lxvw4x(41, %[cc], %[sk])289addi(%[cc], %[cc], 16)290lxvw4x(42, %[cc], %[sk])291addi(%[cc], %[cc], 16)292lxvw4x(43, %[cc], %[sk])293addi(%[cc], %[cc], 16)294lxvw4x(44, %[cc], %[sk])295addi(%[cc], %[cc], 16)296lxvw4x(45, %[cc], %[sk])297addi(%[cc], %[cc], 16)298lxvw4x(46, %[cc], %[sk])299300#if BR_POWER8_LE301/*302* v15 = constant for byteswapping words303*/304lxvw4x(47, 0, %[idx2be])305#endif306/*307* Load IV into v16.308*/309lxvw4x(48, 0, %[iv])310#if BR_POWER8_LE311vperm(16, 16, 16, 15)312#endif313314mtctr(%[num_blocks])315label(loop)316/*317* Load next plaintext word and XOR with current IV.318*/319lxvw4x(49, 0, %[buf])320#if BR_POWER8_LE321vperm(17, 17, 17, 15)322#endif323vxor(16, 16, 17)324325/*326* Encrypt the block.327*/328vxor(16, 16, 0)329vcipher(16, 16, 1)330vcipher(16, 16, 2)331vcipher(16, 16, 3)332vcipher(16, 16, 4)333vcipher(16, 16, 5)334vcipher(16, 16, 6)335vcipher(16, 16, 7)336vcipher(16, 16, 8)337vcipher(16, 16, 9)338vcipher(16, 16, 10)339vcipher(16, 16, 11)340vcipher(16, 16, 12)341vcipher(16, 16, 13)342vcipherlast(16, 16, 14)343344/*345* Store back result (with byteswap)346*/347#if BR_POWER8_LE348vperm(17, 16, 16, 15)349stxvw4x(49, 0, %[buf])350#else351stxvw4x(48, 0, %[buf])352#endif353addi(%[buf], %[buf], 16)354355bdnz(loop)356357: [cc] "+b" (cc), [buf] "+b" (buf)358: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)359#if BR_POWER8_LE360, [idx2be] "b" (idx2be)361#endif362: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",363"v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",364"ctr", "memory"365);366}367368/* see bearssl_block.h */369void370br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx,371void *iv, void *data, size_t len)372{373if (len > 0) {374switch (ctx->num_rounds) {375case 10:376cbcenc_128(ctx->skey.skni, iv, data, len);377break;378case 12:379cbcenc_192(ctx->skey.skni, iv, data, len);380break;381default:382cbcenc_256(ctx->skey.skni, iv, data, len);383break;384}385memcpy(iv, (unsigned char *)data + (len - 16), 16);386}387}388389/* see bearssl_block.h */390const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable = {391sizeof(br_aes_pwr8_cbcenc_keys),39216,3934,394(void (*)(const br_block_cbcenc_class **, const void *, size_t))395&br_aes_pwr8_cbcenc_init,396(void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))397&br_aes_pwr8_cbcenc_run398};399400/* see bearssl_block.h */401const br_block_cbcenc_class *402br_aes_pwr8_cbcenc_get_vtable(void)403{404return br_aes_pwr8_supported() ? &br_aes_pwr8_cbcenc_vtable : NULL;405}406407#else408409/* see bearssl_block.h */410const br_block_cbcenc_class *411br_aes_pwr8_cbcenc_get_vtable(void)412{413return NULL;414}415416#endif417418419