Home | History | Annotate | Line # | Download | only in x86
aes_ssse3_subr.c revision 1.1
      1 /*	$NetBSD: aes_ssse3_subr.c,v 1.1 2020/06/29 23:51:35 riastradh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2020 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(1, "$NetBSD: aes_ssse3_subr.c,v 1.1 2020/06/29 23:51:35 riastradh Exp $");
     31 
     32 #include <sys/systm.h>
     33 
     34 #include <lib/libkern/libkern.h>
     35 
     36 #include "aes_ssse3_impl.h"
     37 
     38 static inline __m128i
     39 loadblock(const void *in)
     40 {
     41 	return _mm_loadu_epi8(in);
     42 }
     43 
     44 static inline void
     45 storeblock(void *out, __m128i block)
     46 {
     47 	_mm_storeu_epi8(out, block);
     48 }
     49 
     50 void
     51 aes_ssse3_enc(const struct aesenc *enc, const uint8_t in[static 16],
     52     uint8_t out[static 16], uint32_t nrounds)
     53 {
     54 	__m128i block;
     55 
     56 	block = loadblock(in);
     57 	block = aes_ssse3_enc1(enc, block, nrounds);
     58 	storeblock(out, block);
     59 }
     60 
     61 void
     62 aes_ssse3_dec(const struct aesdec *dec, const uint8_t in[static 16],
     63     uint8_t out[static 16], uint32_t nrounds)
     64 {
     65 	__m128i block;
     66 
     67 	block = loadblock(in);
     68 	block = aes_ssse3_dec1(dec, block, nrounds);
     69 	storeblock(out, block);
     70 }
     71 
     72 void
     73 aes_ssse3_cbc_enc(const struct aesenc *enc, const uint8_t in[static 16],
     74     uint8_t out[static 16], size_t nbytes, uint8_t iv[static 16],
     75     uint32_t nrounds)
     76 {
     77 	__m128i cv;
     78 
     79 	KASSERT(nbytes);
     80 
     81 	cv = loadblock(iv);
     82 	for (; nbytes; nbytes -= 16, in += 16, out += 16) {
     83 		cv ^= loadblock(in);
     84 		cv = aes_ssse3_enc1(enc, cv, nrounds);
     85 		storeblock(out, cv);
     86 	}
     87 	storeblock(iv, cv);
     88 }
     89 
     90 void
     91 aes_ssse3_cbc_dec(const struct aesdec *dec, const uint8_t in[static 16],
     92     uint8_t out[static 16], size_t nbytes, uint8_t iv[static 16],
     93     uint32_t nrounds)
     94 {
     95 	__m128i iv0, cv, b;
     96 
     97 	KASSERT(nbytes);
     98 	KASSERT(nbytes % 16 == 0);
     99 
    100 	iv0 = loadblock(iv);
    101 	cv = loadblock(in + nbytes - 16);
    102 	storeblock(iv, cv);
    103 
    104 	for (;;) {
    105 		b = aes_ssse3_dec1(dec, cv, nrounds);
    106 		if ((nbytes -= 16) == 0)
    107 			break;
    108 		cv = loadblock(in + nbytes - 16);
    109 		storeblock(out + nbytes, b ^ cv);
    110 	}
    111 	storeblock(out, b ^ iv0);
    112 }
    113 
    114 static inline __m128i
    115 aes_ssse3_xts_update(__m128i t)
    116 {
    117 	const __m128i one = _mm_set_epi64x(1, 1);
    118 	__m128i s, m, c;
    119 
    120 	s = _mm_srli_epi64(t, 63);	/* 1 if high bit set else 0 */
    121 	m = _mm_sub_epi64(s, one);	/* 0 if high bit set else -1 */
    122 	m = _mm_shuffle_epi32(m, 0x4e);	/* swap halves */
    123 	c = _mm_set_epi64x(1, 0x87);	/* carry */
    124 
    125 	return _mm_slli_epi64(t, 1) ^ (c & ~m);
    126 }
    127 
    128 static int
    129 aes_ssse3_xts_update_selftest(void)
    130 {
    131 	static const struct {
    132 		uint32_t in[4], out[4];
    133 	} cases[] = {
    134 		[0] = { {1}, {2} },
    135 		[1] = { {0x80000000U,0,0,0}, {0,1,0,0} },
    136 		[2] = { {0,0x80000000U,0,0}, {0,0,1,0} },
    137 		[3] = { {0,0,0x80000000U,0}, {0,0,0,1} },
    138 		[4] = { {0,0,0,0x80000000U}, {0x87,0,0,0} },
    139 		[5] = { {0,0x80000000U,0,0x80000000U}, {0x87,0,1,0} },
    140 	};
    141 	unsigned i;
    142 	uint32_t t[4];
    143 	int result = 0;
    144 
    145 	for (i = 0; i < sizeof(cases)/sizeof(cases[0]); i++) {
    146 		t[0] = cases[i].in[0];
    147 		t[1] = cases[i].in[1];
    148 		t[2] = cases[i].in[2];
    149 		t[3] = cases[i].in[3];
    150 		storeblock(t, aes_ssse3_xts_update(loadblock(t)));
    151 		if (t[0] != cases[i].out[0] ||
    152 		    t[1] != cases[i].out[1] ||
    153 		    t[2] != cases[i].out[2] ||
    154 		    t[3] != cases[i].out[3]) {
    155 			printf("%s %u:"
    156 			    " %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n",
    157 			    __func__, i, t[0], t[1], t[2], t[3]);
    158 			result = -1;
    159 		}
    160 	}
    161 
    162 	return result;
    163 }
    164 
    165 void
    166 aes_ssse3_xts_enc(const struct aesenc *enc, const uint8_t in[static 16],
    167     uint8_t out[static 16], size_t nbytes, uint8_t tweak[static 16],
    168     uint32_t nrounds)
    169 {
    170 	__m128i t, b;
    171 
    172 	KASSERT(nbytes);
    173 	KASSERT(nbytes % 16 == 0);
    174 
    175 	t = loadblock(tweak);
    176 	for (; nbytes; nbytes -= 16, in += 16, out += 16) {
    177 		b = t ^ loadblock(in);
    178 		b = aes_ssse3_enc1(enc, b, nrounds);
    179 		storeblock(out, t ^ b);
    180 		t = aes_ssse3_xts_update(t);
    181 	}
    182 	storeblock(tweak, t);
    183 }
    184 
    185 void
    186 aes_ssse3_xts_dec(const struct aesdec *dec, const uint8_t in[static 16],
    187     uint8_t out[static 16], size_t nbytes, uint8_t tweak[static 16],
    188     uint32_t nrounds)
    189 {
    190 	__m128i t, b;
    191 
    192 	KASSERT(nbytes);
    193 	KASSERT(nbytes % 16 == 0);
    194 
    195 	t = loadblock(tweak);
    196 	for (; nbytes; nbytes -= 16, in += 16, out += 16) {
    197 		b = t ^ loadblock(in);
    198 		b = aes_ssse3_dec1(dec, b, nrounds);
    199 		storeblock(out, t ^ b);
    200 		t = aes_ssse3_xts_update(t);
    201 	}
    202 	storeblock(tweak, t);
    203 }
    204 
    205 int
    206 aes_ssse3_selftest(void)
    207 {
    208 
    209 	if (aes_ssse3_xts_update_selftest())
    210 		return -1;
    211 
    212 	return 0;
    213 }
    214