linux/crypto/vmac.c
<<
333<3 ="+search" method="post" onsubmit="return do_search(this);">3 ">33Search33< ="ajax+*" method="post" onsubmit="return false;">3< ">3/o.3 33
3 31/*3 32 * Modified to interface to the Linux kernel3 33 * Copyright (c) 2009, Intel Corpora> .3 34 *3 35 * This program is free software; you ca redistribute it and/or modify it3 36 * under the terms and condi> s of the GNU General Public License,3 37 * verstion2, as published by the Free Software Founda> .3 38 *3 39 * This program is distributed in the hope it will be useful, but WITHOUT3 v3.a> * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or3 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for3 12 * more details.3 13 *3 14 * You should have received a copy of the GNU General Public License along with3 15 * this program; if not, write to the Free Software Founda> , Inc., 59 Temple3 16 * Place - Suite 330, Bost , MA 02111-1307 USA.3 17 */3 1833 19/* --------------------------------------------------------------------------3 2v3.a> * VMAC and VHASH Implementa> by Ted Krovetz (tdk@acm.org) and Wei Dai.3 21 * This implementa> is herby placed in the public domai .3 22 * The authors offers no warranty. Use at your ow risk.3 23 * Please send bug reports to the authors.3 24 * Last modified: 17 APR 08, 1700 PDT3 25 * ----------------------------------------------------------------------- */3 2633 27#include <linux/init.h>33 28#include <linux/typ s.h>33 29#include <linux/crypto.h>33 30#include <linux/module.h>33 31#include <linux/scatterlist.h>33 32#include <asm/byteorder.h>33 33#include <crypto/scatterwalk.h>33 34#include <crypto/vmac.h>33 35#include <crypto/internal/hash.h>33 3633 37/*3 38 * Constants and masks3 39 */3 40#define3UINT64_C(x)3x##ULL33 41static const u64 p64 =3UINT64_C(0xfffffffffffffeff); /* 2^64 - 257 prime */3 42static const u64 m62 =3UINT64_C(0x3fffffffffffffff); /* 62-bit mask/o.3 3 */3 43static const u64 m63 =3UINT64_C(0x7fffffffffffffff); /* 63-bit mask/o.3 3 */3 44static const u64 m64 =3UINT64_C(0xffffffffffffffff); /* 64-bit mask/o.3 3 */3 45static const u64 mpoly =3UINT64_C(0x1fffffff1fffffff); /* Poly key mask/o.3 */3 4633 47#define3pe64_to_cpup le64_to_cpup /* Prefer little endia */3 4833 49#ifdef __LITTLE_ENDIAN33 50#define3INDEX_HIGH 133 51#define3INDEX_LOW 033 52#else33 53#define3INDEX_HIGH 033 54#define3INDEX_LOW 133 55#endif33 5633 57/*3 58 * The following routines are used in this implementa> . They are3 59 * written via macros to simulate zero-overhead call-by-reference.3 6v3.a> *3 61 * MUL64: 64x64->128-bit multiplica> 3 62 * PMUL64: assumes top bits cleared inputs3 63 * ADD128: 128x128->128-bit addi> 3 64 */3 6533 66#define3ADD128(rh,3rl,3ih,3il)333333333333333333333333333333333333333333\33 67 do {333333333333333333333333333333333333333333333333333333333333\33 68 u64 _il =3(il);33333333333333333333333333333333333333333\33 69 (rl) +=3(_il);333333333333333333333333333333333333333333\33 70 if ((rl) <3(_il))333333333333333333333333333333333333333\33 71 (rh)++;33333333333333333333333333333333333333333\33 72 (rh) +=3(ih);3333333333333333333333333333333333333333333\33 73 } while (0)33 7433 75#define3MUL32(i1,3i2)333((u64)(u32)(i1)*(u32)(i2))33 7633 77#define3PMUL64(rh,3rl,3i1,3i2)33/* Assumes m doesn't overflow */3 78 do {333333333333333333333333333333333333333333333333333333333333\33 79 u64 _i1 =3(i1),3_i2 =3(i2);33333333333333333333333333333\33 80 u64 m =3MUL32(_i1,3_i2>>32) +3MUL32(_i1>>32,3_i2);333333\33 81 rh =3MUL32(_i1>>32,3_i2>>32);333333333333333333333333333\33 82 rl =3MUL32(_i1,3_i2);33333333333333333333333333333333333\33 83 ADD128(rh,3rl,3(m >> 32),3(m <<332));3333333333333333333\33 84 } while (0)33 8533 86#define3MUL64(rh,3rl,3i1,3i2)3333333333333333333333333333333333333333333\33 87 do {333333333333333333333333333333333333333333333333333333333333\33 88 u64 _i1 =3(i1),3_i2 =3(i2);33333333333333333333333333333\33 89 u64 m1 =3MUL32(_i1,3_i2>>32);333333333333333333333333333\33 90 u64 m2 =3MUL32(_i1>>32,3_i2);333333333333333333333333333\33 91 rh =3MUL32(_i1>>32,3_i2>>32);333333333333333333333333333\33 92 rl =3MUL32(_i1,3_i2);33333333333333333333333333333333333\33 93 ADD128(rh,3rl,3(m1 >> 32),3(m1 <<332));33333333333333333\33 94 ADD128(rh,3rl,3(m2 >> 32),3(m2 <<332));33333333333333333\33 95 } while (0)33 9633 97/*3 98 * For highest performance the L1 NH and L2 polynomial hashes should be3 99 * carefully implemented to take advantage of one's target architecture.3100 * Here these two hash func> s are defined multiple time; once for3101 * 64-bit architectures, once for332-bit SSE2 architectures, and once3102 * for3the rest (32-bit) architectures.3103 * For each, nh_16 *must* be defined (works multiples of 16 bytes).3104 * O > ally, nh_vmac_nhbytes ca be defined (for3multiples of3105 * VMAC_NHBYTES), and nh_16_2 and nh_vmac_nhbytes_2 (verstios that do two3106 * NH computa> s at once).3107 */310833109#ifdef CONFIG_64BIT331 v3.a>33111#define3nh_16(mp,3kp,3nw,3rh,3rl)333333333333333333333333333333333333333\33112 do {333333333333333333333333333333333333333333333333333333333333\33113 int i; u64 th,3tl; 3333333333333333333333333333333333333\33114 rh =3rl =30;33333333333333333333333333333333333333333333\33115 for3(i =30;3i <3nw;3i += 2) {333333333333333333333333333\33116333333333333333333333333MUL64(th,3tl,3pe64_to_cpup((mp)+i)+(kp)[i],33333\3311733333333333333333333333333333333pe64_to_cpup((mp)+i+1)+(kp)[i+1]);333333\33118 33333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33119 }3333333333333333333333333333333333333333333333333333333\33120 } while (0)3312133122#define3nh_16_2(mp,3kp,3nw,3rh,3rl,3rh1,3rl1)333333333333333333333333333\33123 do {333333333333333333333333333333333333333333333333333333333333\33124 int i; u64 th,3tl; 3333333333333333333333333333333333333\33125 rh1 =3rl1 =3rh =3rl =30;33333333333333333333333333333333\331263333333333333333for3(i =30;3i <3nw;3i += 2) {333333333333333333333333333\33127333333333333333333333333MUL64(th,3tl,3pe64_to_cpup((mp)+i)+(kp)[i],33333\3312833333333333333333333333333333333pe64_to_cpup((mp)+i+1)+(kp)[i+1]);333333\33129 33333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33130 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i)+(kp)[i+2],333\33131 33333333pe64_to_cpup((mp)+i+1)+(kp)[i+3]);333333\33132 33333333ADD128(rh1,3rl1,3th,3tl);33333333333333333333333\33133 }3333333333333333333333333333333333333333333333333333333\33134 } while (0)3313533136#if (VMAC_NHBYTES >= 64)3/* These verstios do 64-bytes of message at a time */3137#define3nh_vmac_nhbytes(mp,3kp,3nw,3rh,3rl)33333333333333333333333333333\33138 do {333333333333333333333333333333333333333333333333333333333333\33139 int i; u64 th,3tl; 3333333333333333333333333333333333333\33140 rh =3rl =30;33333333333333333333333333333333333333333333\33141 for3(i =30;3i <3nw;3i += 8) {333333333333333333333333333\33142 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i)+(kp)[i],33333\33143 33333333pe64_to_cpup((mp)+i+1)+(kp)[i+1]);333333\33144 33333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33145 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i+2)+(kp)[i+2],3\3314633333333333333333333333333333333pe64_to_cpup((mp)+i+3)+(kp)[i+3]);333333\33147333333333333333333333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33148 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i+4)+(kp)[i+4],3\33149 3333333333333333pe64_to_cpup((mp)+i+5)+(kp)[i+5]);333333\33150 33333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33151 MUL64(th,3tl,3pe64_to_cpup((mp)+i+6)+(kp)[i+6],3\33152 3333333333333333pe64_to_cpup((mp)+i+7)+(kp)[i+7]);333333\33153 ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33154 }3333333333333333333333333333333333333333333333333333333\33155 } while (0)3315633157#define3nh_vmac_nhbytes_2(mp,3kp,3nw,3rh,3rl,3rh1,3rl1)33333333333333333\33158 do {333333333333333333333333333333333333333333333333333333333333\33159 int i; u64 th,3tl; 3333333333333333333333333333333333333\33160 rh1 =3rl1 =3rh =3rl =30;33333333333333333333333333333333\33161 for3(i =30;3i <3nw;3i += 8) {333333333333333333333333333\33162 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i)+(kp)[i],33333\33163 33333333pe64_to_cpup((mp)+i+1)+(kp)[i+1]);333333\33164 33333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33165 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i)+(kp)[i+2],333\3316633333333333333333333333333333333pe64_to_cpup((mp)+i+1)+(kp)[i+3]);333333\33167333333333333333333333333ADD128(rh1,3rl1,3th,3tl);33333333333333333333333\33168 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i+2)+(kp)[i+2],3\33169 3333333333333333pe64_to_cpup((mp)+i+3)+(kp)[i+3]);333333\33170 33333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33171 MUL64(th,3tl,3pe64_to_cpup((mp)+i+2)+(kp)[i+4],3\33172 3333333333333333pe64_to_cpup((mp)+i+3)+(kp)[i+5]);333333\33173 ADD128(rh1,3rl1,3th,3tl);33333333333333333333333\33174 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i+4)+(kp)[i+4],3\33175 3333333333333333pe64_to_cpup((mp)+i+5)+(kp)[i+5]);333333\33176333333333333333333333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33177333333333333333333333333MUL64(th,3tl,3pe64_to_cpup((mp)+i+4)+(kp)[i+6],3\33178 3333333333333333pe64_to_cpup((mp)+i+5)+(kp)[i+7]);333333\33179 33333333ADD128(rh1,3rl1,3th,3tl);33333333333333333333333\33180 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i+6)+(kp)[i+6],3\33181 3333333333333333pe64_to_cpup((mp)+i+7)+(kp)[i+7]);333333\33182 33333333ADD128(rh,3rl,3th,3tl);3333333333333333333333333\33183 33333333MUL64(th,3tl,3pe64_to_cpup((mp)+i+6)+(kp)[i+8],3\33184 3333333333333333pe64_to_cpup((mp)+i+7)+(kp)[i+9]);333333\33185 33333333ADD128(rh1,3rl1,3th,3tl);33333333333333333333333\331863333333333333333}3333333333333333333333333333333333333333333333333333333\33187 } while (0)33188#endif3318933190#define3poly_step(ah,3al,3kh,3kl,3mh,3ml)3333333333333333333333333333333\33191 do {333333333333333333333333333333333333333333333333333333333333\33192 u64 t1h,3t1l,3t2h,3t2l,3t3h,3t3l,3z =30;3333333333333333\33193 /* compute ab*cd, put bd into result registers */3194 PMUL64(t3h,3t3l,3al,3kh);3333333333333333333333333333333\33195 PMUL64(t2h,3t2l,3ah,3kl);3333333333333333333333333333333\331963333333333333333PMUL64(t1h,3t1l,3ah,32*kh);33333333333333333333333333333\331973333333333333333PMUL64(ah,3al,3al,3kl);333333333333333333333333333333333\33198 /* add 2 * ac to result */3199 ADD128(ah,3al,3t1h,3t1l);3333333333333333333333333333333\33200 /* add together ad + bc */3201 ADD128(t2h,3t2l,3t3h,3t3l);33333333333333333333333333333\33202 /* now (ah,al),3(t2l,2*t2h) need summing */3203 /* first add the high registers, carrying into t2h */3204 ADD128(t2h,3ah,3z,3t2l);33333333333333333333333333333333\33205 /* double t2h and add top bit of ah */32063333333333333333t2h =32 * t2h +3(ah >> 63);33333333333333333333333333333\332073333333333333333ah &=3m63;3333333333333333333333333333333333333333333333\33208 /* now add the low registers */3209 ADD128(ah,3al,3mh,3ml);333333333333333333333333333333333\33210 ADD128(ah,3al,3z,3t2h);333333333333333333333333333333333\33211 } while (0)3321233213#else /* ! CONFIG_64BIT */321433215#ifndef nh_1633216#define3nh_16(mp,3kp,3nw,3rh,3rl)333333333333333333333333333333333333333\3321733333333do {333333333333333333333333333333333333333333333333333333333333\33218 u64 t1,3t2,3m1,3m2,3t;3333333333333333333333333333333333\33219 int i; 3333333333333333333333333333333333333333333333333\33220 rh =3rl =3t =30;3333333333333333333333333333333333333333\33221 for3(i =30;3i <3nw;3i += 2)33{33333333333333333333333333\33222 33333333t1 =3pe64_to_cpup(mp+i) +3kp[i];3333333333333333\33223 33333333t2 =3pe64_to_cpup(mp+i+1) +3kp[i+1];333333333333\33224 33333333m2 =3MUL32(t1 >> 32,3t2);33333333333333333333333\33225 33333333m1 =3MUL32(t1,3t2 >> 32);33333333333333333333333\33226333333333333333333333333ADD128(rh,3rl,3MUL32(t1 >> 32,3t2 >> 32),3333333\3322733333333333333333333333333333333MUL32(t1,3t2));3333333333333333333333333\33228333333333333333333333333rh += (u64)(u32)(m1 >> 32)3333333333333333333333\33229 3333333333333333+3(u32)(m2 >> 32);3333333333333333333333\33230 33333333t += (u64)(u32)m1 +3(u32)m2;33333333333333333333\33231 }3333333333333333333333333333333333333333333333333333333\33232 ADD128(rh,3rl,3(t >> 32),3(t <<332));3333333333333333333\33233 } while (0)33234#endif3323533236static void3poly_step_func(u64 *ahi,3u64 *alo,33237333333333333333333333333const u64 *kh,3const u64 *kl,33238333333333333333333333333const u64 *mh,3const u64 *ml)33239{33240#define3a0 (*(((u32 *)alo)+INDEX_LOW))33241#define3a1 (*(((u32 *)alo)+INDEX_HIGH))33242#define3a2 (*(((u32 *)ahi)+INDEX_LOW))33243#define3a3 (*(((u32 *)ahi)+INDEX_HIGH))33244#define3k0 (*(((u32 *)kl)+INDEX_LOW))33245#define3k1 (*(((u32 *)kl)+INDEX_HIGH))33246#define3k2 (*(((u32 *)kh)+INDEX_LOW))33247#define3k3 (*(((u32 *)kh)+INDEX_HIGH))3324833249 u64 p,3q,3t;33250 u32 t2;3325133252 p =3MUL32(a3,3k3);33253 p +=3p;33254 p +=3*(u64 *)mh;33255 p +=3MUL32(a0,3k2);33256 p +=3MUL32(a1,3k1);33257 p +=3MUL32(a2,3k0);33258 t = (u32)(p);33259 p >>= 32;33260 p +=3MUL32(a0,3k3);33261 p +=3MUL32(a1,3k2);33262 p +=3MUL32(a2,3k1);33263 p +=3MUL32(a3,3k0);33264 t |= ((u64)((u32)p & 0x7fffffff)) <<332;33265 p >>= 31;33266 p +=3(u64)(((u32 *)ml)[INDEX_LOW]);33267 p +=3MUL32(a0,3k0);33268 q = 3MUL32(a1,3k3);33269 q +=3MUL32(a2,3k2);33270 q +=3MUL32(a3,3k1);33271 q +=3q;33272 p +=3q;33273 t2 =3(u32)(p);33274 p >>= 32;33275 p +=3(u64)(((u32 *)ml)[INDEX_HIGH]);33276 p +=3MUL32(a0,3k1);33277 p +=3MUL32(a1,3k0);33278 q = 3MUL32(a2,3k3);33279 q +=3MUL32(a3,3k2);33280 q +=3q;33281 p +=3q;33282 *(u64 *)(alo) =3(p <<332) | t2;33283 p >>= 32;33284 *(u64 *)(ahi) =3p +3t;3328533286#undef a033287#undef a133288#undef a233289#undef a333290#undef k033291#undef k133292#undef k233293#undef k333294}3329533296#define3poly_step(ah,3al,3kh,3kl,3mh,3ml) \33297 poly_step_func(&(ah), &(al), &(kh), &(kl), &(mh), &(ml))3329833299#endif /* end of specialized NH and poly definitions */330033301/* At least nh_16 is defined. Defined others as needed here */3302#ifndef nh_16_233303#define3nh_16_2(mp,3kp,3nw,3rh,3rl,3rh2,3rl2) \33304 do {333333333333333333333333333333333333333333333333333333333333\33305 nh_16(mp,3kp,3nw,3rh,3rl);333333333333333333333333333333\333063333333333333333nh_16(mp,3((kp)+2),3nw,3rh2,3rl2);3333333333333333333333\33307 } while (0)33308#endif33309#ifndef nh_vmac_nhbytes33310#define3nh_vmac_nhbytes(mp,3kp,3nw,3rh,3rl)33333333333333333333333333333\33311 nh_16(mp,3kp,3nw,3rh,3rl)33312#endif33313#ifndef nh_vmac_nhbytes_233314#define3nh_vmac_nhbytes_2(mp,3kp,3nw,3rh,3rl,3rh2,3rl2) \33315 do {333333333333333333333333333333333333333333333333333333333333\333163333333333333333nh_vmac_nhbytes(mp,3kp,3nw,3rh,3rl);33333333333333333333\333173333333333333333nh_vmac_nhbytes(mp,3((kp)+2),3nw,3rh2,3rl2);333333333333\33318 } while (0)33319#endif3332033321static void3vhash_abort(struct vmac_ctx *ctx)33322{33323 ctx->polytmp[0] =3ctx->polykey[0] ;33324 ctx->polytmp[1] =3ctx->polykey[1] ;33325 ctx->first_block_processed =30;33326}3332733328static u64 l3hash(u64 p1,3u64 p2,3u64 k1,3u64 k2,3u64 len)33329{33330 u64 rh,3rl,3t,3z =30;3333133332 /* fully reduce (p1,p2)+(len,0) mod p127 */3333 t =3p1 >> 63;33334 p1 &=3m63;33335 ADD128(p1,3p2,3len,3t);33336 /* At this point, (p1,p2) is at most 2^127+(len<<64) */3337 t = (p1 >3m63) +3((p1 ==3m63) && (p2 ==3m64));33338 ADD128(p1,3p2,3z,3t);33339 p1 &=3m63;3334033341 /* compute (p1,p2)/(2^64-2^32) and (p1,p2)%(2^64-2^32) */3342 t =3p1 +3(p2 >> 32);33343 t +=3(t >> 32);33344 t +=3(u32)t > 0xfffffffeu;33345 p1 +=3(t >> 32);33346 p2 +=3(p1 <<332);3334733348 /* compute (p1+k1)%p64 and (p2+k2)%p64 */3349 p1 +=3k1;33350 p1 +=3(0 -3(p1 <3k1)) &3257;33351 p2 +=3k2;33352 p2 +=3(0 -3(p2 <3k2)) &3257;3335333354 /* compute (p1+k1)*(p2+k2)%p64 */3355 MUL64(rh,3rl,3p1,3p2);33356 t =3rh >> 56;33357 ADD128(t,3rl,3z,3rh);33358 rh <<= 8;33359 ADD128(t,3rl,3z,3rh);33360 t +=3t <<38;33361 rl +=3t;33362 rl +=3(0 -3(rl <3t)) &3257;33363 rl +=3(0 -3(rl >3p64-1)) &3257;33364 return rl;33365}3336633367static void3vhash_update(const unsigned char *m,33368 unsigned int mbytes, /* Pos multiple of VMAC_NHBYTES */3369 33333333struct vmac_ctx *ctx)33370{33371 u64 rh,3rl,3*mptr;33372 const u64 *kptr =3(u64 *)ctx->nhkey;33373 int i;33374 u64 ch,3cl;33375 u64 pkh =3ctx->polykey[0];33376 u64 pkl =3ctx->polykey[1];3337733378 mptr =3(u64 *)m;33379 i =3mbytes /3VMAC_NHBYTES; /* Must be non-zero */338033381 ch =3ctx->polytmp[0];33382 cl =3ctx->polytmp[1];3338333384 if (!ctx->first_block_processed) {33385 ctx->first_block_processed =31;333863333333333333333nh_vmac_nhbytes(mptr,3kptr,3VMAC_NHBYTES/8,3rh,3rl);333873333333333333333rh &=3m62;33388 ADD128(ch,3cl,3rh,3rl);33389 mptr +=3(VMAC_NHBYTES/sizeof(u64));33390 i--;33391 }3339233393 while (i--) {333943333333333333333nh_vmac_nhbytes(mptr,3kptr,3VMAC_NHBYTES/8,3rh,3rl);33395 rh &=3m62;333963333333333333333poly_step(ch,3cl,3pkh,3pkl,3rh,3rl);333973333333333333333mptr +=3(VMAC_NHBYTES/sizeof(u64));33398 }3339933400 ctx->polytmp[0] =3ch;33401 ctx->polytmp[1] =3cl;33402}3340333404static u64 vhash(unsigned char m[], unsigned int mbytes,33405 u64 *tagl,3struct vmac_ctx *ctx)33406{33407 u64 rh,3rl,3*mptr;33408 const u64 *kptr =3(u64 *)ctx->nhkey;33409 int i,3remaining;33410 u64 ch,3cl;33411 u64 pkh =3ctx->polykey[0];33412 u64 pkl =3ctx->polykey[1];3341333414 mptr =3(u64 *)m;33415 i =3mbytes /3VMAC_NHBYTES;33416 remaining =3mbytes %3VMAC_NHBYTES;3341733418 if (ctx->first_block_processed) {33419 ch =3ctx->polytmp[0];33420 cl =3ctx->polytmp[1];33421 } else if (i) {33422 nh_vmac_nhbytes(mptr,3kptr,3VMAC_NHBYTES/8,3ch,3cl);33423 ch &=3m62;334243333333333333333ADD128(ch,3cl,3pkh,3pkl);33425 mptr +=3(VMAC_NHBYTES/sizeof(u64));334263333333333333333i--;33427 } else if (remaining) {33428 nh_16(mptr,3kptr,32*((remaining+15)/16),3ch,3cl);33429 ch &=3m62;33430 ADD128(ch,3cl,3pkh,3pkl);33431 mptr +=3(VMAC_NHBYTES/sizeof(u64));33432 goto do_l3;33433 } else {/* Empty String */34343333333333333333ch =3pkh;3cl =3pkl;33435 goto do_l3;33436 }3343733438 while (i--) {33439 nh_vmac_nhbytes(mptr,3kptr,3VMAC_NHBYTES/8,3rh,3rl);33440 rh &=3m62;33441 poly_step(ch,3cl,3pkh,3pkl,3rh,3rl);33442 mptr +=3(VMAC_NHBYTES/sizeof(u64));33443 }33444 if (remaining) {33445 nh_16(mptr,3kptr,32*((remaining+15)/16),3rh,3rl);334463333333333333333rh &=3m62;334473333333333333333poly_step(ch,3cl,3pkh,3pkl,3rh,3rl);33448 }3344933450do_l3:33451 vhash_abort(ctx);33452 remaining *= 8;33453 return l3hash(ch,3cl,3ctx->l3key[0],3ctx->l3key[1],3remaining);33454}3345533456static u64 vmac(unsigned char m[], unsigned int mbytes,33457333333333333333333333333unsigned char n[16],3u64 *tagl,33458 struct vmac_ctx_t *ctx)33459{33460 u64 *in_n,3*out_p;33461 u64 p,3h;33462 int i;3346333464 in_n =3ctx->__vmac_ctx.cached_nonce;33465 out_p =3ctx->__vmac_ctx.cached_aes;3346633467 i =3n[15] &31;33468 if ((*(u64 *)(n+8) !=3in_n[1]) || (*(u64 *)(n) !=3in_n[0])) {33469 in_n[0] =3*(u64 *)(n);33470 in_n[1] =3*(u64 *)(n+8);33471 ((unsigned char *)in_n)[15] &= 0xFE;33472 crypto_cipher_encrypt_one(ctx->child,33473 (unsigned char *)out_p, (unsigned char *)in_n);3347433475 ((unsigned char *)in_n)[15] |= (unsigned char)(1-i);33476 }33477 p =3be64_to_cpup(out_p + i);33478 h =3vhash(m,3mbytes, (u64 *)0, &ctx->__vmac_ctx);33479 return le64_to_cpu(p + h);33480}3348133482static int vmac_set_key(unsigned char user_key[], struct vmac_ctx_t *ctx)33483{33484 u64 in[2] =3{0},3out[2];33485 unsigned i;3348633333333int err =30;3348733488 err =3crypto_cipher_setkey(ctx->child, user_key,3VMAC_KEY_LEN);33489 if (err)33490 return err;3349133492 /* Fill nh key */3493 ((unsigned char *)in)[0] =30x80;3349433333333for (i =30; i <3sizeof(ctx->__vmac_ctx.nhkey)/8; i += 2) {33495 crypto_cipher_encrypt_one(ctx->child,334963333333333333333 (unsigned char *)out, (unsigned char *)in);334973333333333333333ctx->__vmac_ctx.nhkey[i] =3be64_to_cpup(out);33498 ctx->__vmac_ctx.nhkey[i+1] =3be64_to_cpup(out+1);33499 ((unsigned char *)in)[15] +=31;33500 }3350133502 /* Fill poly key */3503 ((unsigned char *)in)[0] =30xC0;33504 in[1] =30;33505 for (i =30; i <3sizeof(ctx->__vmac_ctx.polykey)/8; i += 2) {335063333333333333333crypto_cipher_encrypt_one(ctx->child,33507333333333333333333333333(unsigned char *)out, (unsigned char *)in);33508 ctx->__vmac_ctx.polytmp[i] =33509 ctx->__vmac_ctx.polykey[i] =33510 be64_to_cpup(out) &3mpoly;33511 ctx->__vmac_ctx.polytmp[i+1] =33512 ctx->__vmac_ctx.polykey[i+1] =33513 be64_to_cpup(out+1) &3mpoly;33514 ((unsigned char *)in)[15] +=31;33515 }3351633517 /* Fill ip key */3518 ((unsigned char *)in)[0] =30xE0;33519 in[1] =30;33520 for (i =30; i <3sizeof(ctx->__vmac_ctx.l3key)/8; i += 2) {33521 do {33522 crypto_cipher_encrypt_one(ctx->child,33523 (unsigned char *)out, (unsigned char *)in);335243333333333333333 ctx->__vmac_ctx.l3key[i] =3be64_to_cpup(out);33525 ctx->__vmac_ctx.l3key[i+1] =3be64_to_cpup(out+1);335263333333333333333 ((unsigned char *)in)[15] +=31;335273333333333333333} while (ctx->__vmac_ctx.l3key[i] >=3p6433528 || ctx->__vmac_ctx.l3key[i+1] >=3p64);33529 }3353033531 /* Invalidate nonce/aes cache and reset other elements */3532 ctx->__vmac_ctx.cached_nonce[0] =3(u64)-1; /* Ensure illegal nonce */3533 ctx->__vmac_ctx.cached_nonce[1] =3(u64)0; /* Ensure illegal nonce */3534 ctx->__vmac_ctx.first_block_processed =30;3353533536 return err;33537}3353833539static int vmac_setkey(struct crypto_shash *parent,33540 const u8 *key,3unsigned int keylen)33541{33542 struct vmac_ctx_t *ctx =3crypto_shash_ctx(parent);3354333544 if (keylen !=3VMAC_KEY_LEN) {33545 crypto_shash_set_flags(parent,3CRYPTO_TFM_RES_BAD_KEY_LEN);335463333333333333333return -EINVAL;3354733333333}3354833549 return vmac_set_key((u8 *)key,3ctx);33550}3355133552static int vmac_init(struct shash_desc *pdesc)33553{33554 return 0;33555}3355633557static int vmac_update(struct shash_desc *pdesc, const u8 *p,33558 unsigned int len)33559{33560 struct crypto_shash *parent =3pdesc->tfm;33561 struct vmac_ctx_t *ctx =3crypto_shash_ctx(parent);3356233563 vhash_update(p, len, &ctx->__vmac_ctx);3356433565 return 0;33566}3356733568static int vmac_final(struct shash_desc *pdesc, u8 *out)33569{33570 struct crypto_shash *parent =3pdesc->tfm;33571 struct vmac_ctx_t *ctx =3crypto_shash_ctx(parent);33572 vmac_t mac;33573 u8 nonce[16] =3{};3357433575 mac =3vmac(NULL, 0, nonce, NULL, ctx);33576 memcpy(out, &mac,3sizeof(vmac_t));33577 memset(&mac,30,3sizeof(vmac_t));33578 memset(&ctx->__vmac_ctx,30,3sizeof(struct vmac_ctx));33579 return 0;33580}3358133582static int vmac_init_tfm(struct crypto_tfm *tfm)33583{33584 struct crypto_cipher *cipher;33585 struct crypto_instance *inst =3(void *)tfm->__crt_alg;3358633333333struct crypto_spawn *spawn =3crypto_instance_ctx(inst);3358733333333struct vmac_ctx_t *ctx =3crypto_tfm_ctx(tfm);3358833589 cipher =3crypto_spawn_cipher(spawn);33590 if (IS_ERR(cipher))33591 return PTR_ERR(cipher);3359233593 ctx->child =3cipher;33594 return 0;33595}3359633597static void vmac_exit_tfm(struct crypto_tfm *tfm)33598{33599 struct vmac_ctx_t *ctx =3crypto_tfm_ctx(tfm);33600 crypto_free_cipher(ctx->child);33601}3360233603static int vmac_create(struct crypto_template *tmpl,3struct rtattr **tb)33604{33605 struct shash_instance *inst;3360633333333struct crypto_alg *alg;3360733333333int err;3360833609 err =3crypto_check_attr_type(tb,3CRYPTO_ALG_TYPE_SHASH);33610 if (err)33611 return err;3361233613 alg =3crypto_get_attr_alg(tb,3CRYPTO_ALG_TYPE_CIPHER,33614 CRYPTO_ALG_TYPE_MASK);33615 if (IS_ERR(alg))336163333333333333333return PTR_ERR(alg);3361733618 inst =3shash_alloc_instance("vmac"alg);33619 err =3PTR_ERR(inst);33620 if (IS_ERR(inst))33621 goto3out_put_alg;3362233623 err =3crypto_init_spawn(shash_instance_ctx(inst),3alg,336243333333333333333 shash_crypto_instance(inst),33625 CRYPTO_ALG_TYPE_MASK);3362633333333if (err)336273333333333333333goto3out_free_inst;3362833629 inst->alg.base.cra_priority =3alg->cra_priority;33630 inst->alg.base.cra_blocksize =3alg->cra_blocksize;33631 inst->alg.base.cra_alignmask =3alg->cra_alignmask;3363233633 inst->alg.digestsize =3sizeof(vmac_t);33634 inst->alg.base.cra_ctxsize =3sizeof(struct vmac_ctx_t);33635 inst->alg.base.cra_init =3vmac_init_tfm;33636 inst->alg.base.cra_exit =3vmac_exit_tfm;3363733638 inst->alg.init =3vmac_init;33639 inst->alg.update =3vmac_update;33640 inst->alg.final =3vmac_final;33641 inst->alg.setkey =3vmac_setkey;3364233643 err =3shash_register_instance(tmpl,3inst);33644 if (err) {33645out_free_inst:336463333333333333333shash_free_instance(shash_crypto_instance(inst));3364733333333}3364833649out_put_alg:33650 crypto_mod_put(alg);33651 return err;33652}3365333654static struct crypto_template vmac_tmpl =3{33655 .nam =3"vmac"3656 .create =3vmac_create,33657 .free =3shash_free_instance,33658 .module =3THIS_MODULE,33659};3366033661static int __init vmac_module_init(void)33662{33663 return crypto_register_template(&vmac_tmpl);33664}3356534 L661" class="lineoEN__vmac_ctx.class="sref">cry,5ac.c#L66 nypto/vmac.c#L664" id L664" truct 356733568static int inst(&unsref">crypto_register_template(&unsref">crypto_regimac_tmpl" class="sref">vmac_tmpl);33569{33570 struc6 3571 struc6 module odule_init(void)ref="crypto/vmac_init" class="sref">vmac_module_init(void)33572 module ouct 3573 35743,33575 3576 3577 The /vmgvmac LXR software by the 7" id L5http://sourceforge.net/projects/lxr">LXR nonunmac.c#L, this experince ac version by 7" id L5mailto:lxr@ ux.no">lxr@ ux.no" cla
subfoo>cr"> lxr. ux.no kindly ho">cd by 7" id L5http://www.redpill- pro.no">Redpill L pro AS.c#L, provider of L uxclassult v,*/