Path: blob/main/contrib/bearssl/src/symcipher/aes_ct64_ctrcbc.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#include "inner.h"2526/* see bearssl_block.h */27void28br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx,29const void *key, size_t len)30{31ctx->vtable = &br_aes_ct64_ctrcbc_vtable;32ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len);33}3435static void36xorbuf(void *dst, const void *src, size_t len)37{38unsigned char *d;39const unsigned char *s;4041d = dst;42s = src;43while (len -- > 0) {44*d ++ ^= *s ++;45}46}4748/* see bearssl_block.h */49void50br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx,51void *ctr, void *data, size_t len)52{53unsigned char *buf;54unsigned char *ivbuf;55uint32_t iv0, iv1, iv2, iv3;56uint64_t sk_exp[120];5758br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);5960/*61* We keep the counter as four 32-bit values, with big-endian62* convention, because that's what is expected for purposes of63* incrementing the counter value.64*/65ivbuf = ctr;66iv0 = br_dec32be(ivbuf + 0);67iv1 = br_dec32be(ivbuf + 4);68iv2 = br_dec32be(ivbuf + 8);69iv3 = br_dec32be(ivbuf + 12);7071buf = data;72while (len > 0) {73uint64_t q[8];74uint32_t w[16];75unsigned char tmp[64];76int i, j;7778/*79* The bitslice implementation expects values in80* little-endian convention, so we have to byteswap them.81*/82j = (len >= 64) ? 16 : (int)(len >> 2);83for (i = 0; i < j; i += 4) {84uint32_t carry;8586w[i + 0] = br_swap32(iv0);87w[i + 1] = br_swap32(iv1);88w[i + 2] = br_swap32(iv2);89w[i + 3] = br_swap32(iv3);90iv3 ++;91carry = ~(iv3 | -iv3) >> 31;92iv2 += carry;93carry &= -(~(iv2 | -iv2) >> 31);94iv1 += carry;95carry &= -(~(iv1 | -iv1) >> 31);96iv0 += carry;97}98memset(w + i, 0, (16 - i) * sizeof(uint32_t));99100for (i = 0; i < 4; i ++) {101br_aes_ct64_interleave_in(102&q[i], &q[i + 4], w + (i << 2));103}104br_aes_ct64_ortho(q);105br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);106br_aes_ct64_ortho(q);107for (i = 0; i < 4; i ++) {108br_aes_ct64_interleave_out(109w + (i << 2), q[i], q[i + 4]);110}111112br_range_enc32le(tmp, w, 16);113if (len <= 64) {114xorbuf(buf, tmp, len);115break;116}117xorbuf(buf, tmp, 64);118buf += 64;119len -= 64;120}121br_enc32be(ivbuf + 0, iv0);122br_enc32be(ivbuf + 4, iv1);123br_enc32be(ivbuf + 8, iv2);124br_enc32be(ivbuf + 12, iv3);125}126127/* see bearssl_block.h */128void129br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx,130void *cbcmac, const void *data, size_t len)131{132const unsigned char *buf;133uint32_t cm0, cm1, cm2, cm3;134uint64_t q[8];135uint64_t sk_exp[120];136137br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);138139cm0 = br_dec32le((unsigned char *)cbcmac + 0);140cm1 = br_dec32le((unsigned char *)cbcmac + 4);141cm2 = br_dec32le((unsigned char *)cbcmac + 8);142cm3 = br_dec32le((unsigned char *)cbcmac + 12);143144buf = data;145memset(q, 0, sizeof q);146while (len > 0) {147uint32_t w[4];148149w[0] = cm0 ^ br_dec32le(buf + 0);150w[1] = cm1 ^ br_dec32le(buf + 4);151w[2] = cm2 ^ br_dec32le(buf + 8);152w[3] = cm3 ^ br_dec32le(buf + 12);153154br_aes_ct64_interleave_in(&q[0], &q[4], w);155br_aes_ct64_ortho(q);156br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);157br_aes_ct64_ortho(q);158br_aes_ct64_interleave_out(w, q[0], q[4]);159160cm0 = w[0];161cm1 = w[1];162cm2 = w[2];163cm3 = w[3];164buf += 16;165len -= 16;166}167168br_enc32le((unsigned char *)cbcmac + 0, cm0);169br_enc32le((unsigned char *)cbcmac + 4, cm1);170br_enc32le((unsigned char *)cbcmac + 8, cm2);171br_enc32le((unsigned char *)cbcmac + 12, cm3);172}173174/* see bearssl_block.h */175void176br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx,177void *ctr, void *cbcmac, void *data, size_t len)178{179/*180* When encrypting, the CBC-MAC processing must be lagging by181* one block, since it operates on the encrypted values, so182* it must wait for that encryption to complete.183*/184185unsigned char *buf;186unsigned char *ivbuf;187uint32_t iv0, iv1, iv2, iv3;188uint32_t cm0, cm1, cm2, cm3;189uint64_t sk_exp[120];190uint64_t q[8];191int first_iter;192193br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);194195/*196* We keep the counter as four 32-bit values, with big-endian197* convention, because that's what is expected for purposes of198* incrementing the counter value.199*/200ivbuf = ctr;201iv0 = br_dec32be(ivbuf + 0);202iv1 = br_dec32be(ivbuf + 4);203iv2 = br_dec32be(ivbuf + 8);204iv3 = br_dec32be(ivbuf + 12);205206/*207* The current CBC-MAC value is kept in little-endian convention.208*/209cm0 = br_dec32le((unsigned char *)cbcmac + 0);210cm1 = br_dec32le((unsigned char *)cbcmac + 4);211cm2 = br_dec32le((unsigned char *)cbcmac + 8);212cm3 = br_dec32le((unsigned char *)cbcmac + 12);213214buf = data;215first_iter = 1;216memset(q, 0, sizeof q);217while (len > 0) {218uint32_t w[8], carry;219220/*221* The bitslice implementation expects values in222* little-endian convention, so we have to byteswap them.223*/224w[0] = br_swap32(iv0);225w[1] = br_swap32(iv1);226w[2] = br_swap32(iv2);227w[3] = br_swap32(iv3);228iv3 ++;229carry = ~(iv3 | -iv3) >> 31;230iv2 += carry;231carry &= -(~(iv2 | -iv2) >> 31);232iv1 += carry;233carry &= -(~(iv1 | -iv1) >> 31);234iv0 += carry;235236/*237* The block for CBC-MAC.238*/239w[4] = cm0;240w[5] = cm1;241w[6] = cm2;242w[7] = cm3;243244br_aes_ct64_interleave_in(&q[0], &q[4], w);245br_aes_ct64_interleave_in(&q[1], &q[5], w + 4);246br_aes_ct64_ortho(q);247br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);248br_aes_ct64_ortho(q);249br_aes_ct64_interleave_out(w, q[0], q[4]);250br_aes_ct64_interleave_out(w + 4, q[1], q[5]);251252/*253* We do the XOR with the plaintext in 32-bit registers,254* so that the value are available for CBC-MAC processing255* as well.256*/257w[0] ^= br_dec32le(buf + 0);258w[1] ^= br_dec32le(buf + 4);259w[2] ^= br_dec32le(buf + 8);260w[3] ^= br_dec32le(buf + 12);261br_enc32le(buf + 0, w[0]);262br_enc32le(buf + 4, w[1]);263br_enc32le(buf + 8, w[2]);264br_enc32le(buf + 12, w[3]);265266buf += 16;267len -= 16;268269/*270* We set the cm* values to the block to encrypt in the271* next iteration.272*/273if (first_iter) {274first_iter = 0;275cm0 ^= w[0];276cm1 ^= w[1];277cm2 ^= w[2];278cm3 ^= w[3];279} else {280cm0 = w[0] ^ w[4];281cm1 = w[1] ^ w[5];282cm2 = w[2] ^ w[6];283cm3 = w[3] ^ w[7];284}285286/*287* If this was the last iteration, then compute the288* extra block encryption to complete CBC-MAC.289*/290if (len == 0) {291w[0] = cm0;292w[1] = cm1;293w[2] = cm2;294w[3] = cm3;295br_aes_ct64_interleave_in(&q[0], &q[4], w);296br_aes_ct64_ortho(q);297br_aes_ct64_bitslice_encrypt(298ctx->num_rounds, sk_exp, q);299br_aes_ct64_ortho(q);300br_aes_ct64_interleave_out(w, q[0], q[4]);301cm0 = w[0];302cm1 = w[1];303cm2 = w[2];304cm3 = w[3];305break;306}307}308309br_enc32be(ivbuf + 0, iv0);310br_enc32be(ivbuf + 4, iv1);311br_enc32be(ivbuf + 8, iv2);312br_enc32be(ivbuf + 12, iv3);313br_enc32le((unsigned char *)cbcmac + 0, cm0);314br_enc32le((unsigned char *)cbcmac + 4, cm1);315br_enc32le((unsigned char *)cbcmac + 8, cm2);316br_enc32le((unsigned char *)cbcmac + 12, cm3);317}318319/* see bearssl_block.h */320void321br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx,322void *ctr, void *cbcmac, void *data, size_t len)323{324unsigned char *buf;325unsigned char *ivbuf;326uint32_t iv0, iv1, iv2, iv3;327uint32_t cm0, cm1, cm2, cm3;328uint64_t sk_exp[120];329uint64_t q[8];330331br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);332333/*334* We keep the counter as four 32-bit values, with big-endian335* convention, because that's what is expected for purposes of336* incrementing the counter value.337*/338ivbuf = ctr;339iv0 = br_dec32be(ivbuf + 0);340iv1 = br_dec32be(ivbuf + 4);341iv2 = br_dec32be(ivbuf + 8);342iv3 = br_dec32be(ivbuf + 12);343344/*345* The current CBC-MAC value is kept in little-endian convention.346*/347cm0 = br_dec32le((unsigned char *)cbcmac + 0);348cm1 = br_dec32le((unsigned char *)cbcmac + 4);349cm2 = br_dec32le((unsigned char *)cbcmac + 8);350cm3 = br_dec32le((unsigned char *)cbcmac + 12);351352buf = data;353memset(q, 0, sizeof q);354while (len > 0) {355uint32_t w[8], carry;356unsigned char tmp[16];357358/*359* The bitslice implementation expects values in360* little-endian convention, so we have to byteswap them.361*/362w[0] = br_swap32(iv0);363w[1] = br_swap32(iv1);364w[2] = br_swap32(iv2);365w[3] = br_swap32(iv3);366iv3 ++;367carry = ~(iv3 | -iv3) >> 31;368iv2 += carry;369carry &= -(~(iv2 | -iv2) >> 31);370iv1 += carry;371carry &= -(~(iv1 | -iv1) >> 31);372iv0 += carry;373374/*375* The block for CBC-MAC.376*/377w[4] = cm0 ^ br_dec32le(buf + 0);378w[5] = cm1 ^ br_dec32le(buf + 4);379w[6] = cm2 ^ br_dec32le(buf + 8);380w[7] = cm3 ^ br_dec32le(buf + 12);381382br_aes_ct64_interleave_in(&q[0], &q[4], w);383br_aes_ct64_interleave_in(&q[1], &q[5], w + 4);384br_aes_ct64_ortho(q);385br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);386br_aes_ct64_ortho(q);387br_aes_ct64_interleave_out(w, q[0], q[4]);388br_aes_ct64_interleave_out(w + 4, q[1], q[5]);389390br_enc32le(tmp + 0, w[0]);391br_enc32le(tmp + 4, w[1]);392br_enc32le(tmp + 8, w[2]);393br_enc32le(tmp + 12, w[3]);394xorbuf(buf, tmp, 16);395cm0 = w[4];396cm1 = w[5];397cm2 = w[6];398cm3 = w[7];399buf += 16;400len -= 16;401}402403br_enc32be(ivbuf + 0, iv0);404br_enc32be(ivbuf + 4, iv1);405br_enc32be(ivbuf + 8, iv2);406br_enc32be(ivbuf + 12, iv3);407br_enc32le((unsigned char *)cbcmac + 0, cm0);408br_enc32le((unsigned char *)cbcmac + 4, cm1);409br_enc32le((unsigned char *)cbcmac + 8, cm2);410br_enc32le((unsigned char *)cbcmac + 12, cm3);411}412413/* see bearssl_block.h */414const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable = {415sizeof(br_aes_ct64_ctrcbc_keys),41616,4174,418(void (*)(const br_block_ctrcbc_class **, const void *, size_t))419&br_aes_ct64_ctrcbc_init,420(void (*)(const br_block_ctrcbc_class *const *,421void *, void *, void *, size_t))422&br_aes_ct64_ctrcbc_encrypt,423(void (*)(const br_block_ctrcbc_class *const *,424void *, void *, void *, size_t))425&br_aes_ct64_ctrcbc_decrypt,426(void (*)(const br_block_ctrcbc_class *const *,427void *, void *, size_t))428&br_aes_ct64_ctrcbc_ctr,429(void (*)(const br_block_ctrcbc_class *const *,430void *, const void *, size_t))431&br_aes_ct64_ctrcbc_mac432};433434435