gcm-ppc.c (3135B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifdef FREEBL_NO_DEPEND 6 #include "stubs.h" 7 #endif 8 #include "gcm.h" 9 #include "secerr.h" 10 11 #if defined(USE_PPC_CRYPTO) 12 13 SECStatus 14 gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf) 15 { 16 vec_xst_be((vec_u8)ghash->x, 0, outbuf); 17 return SECSuccess; 18 } 19 20 static vec_u64 21 vpmsumd(const vec_u64 a, const vec_u64 b) 22 { 23 #if defined(__clang__) 24 /* Clang uses a different name */ 25 return __builtin_altivec_crypto_vpmsumd(a, b); 26 #elif (__GNUC__ >= 10) || (__GNUC__ == 9 && __GNUC_MINOR__ >= 3) || \ 27 (__GNUC__ == 8 && __GNUC_MINOR__ >= 4) || \ 28 (__GNUC__ == 7 && __GNUC_MINOR__ >= 5) 29 /* GCC versions not affected by https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91275 */ 30 return __builtin_crypto_vpmsumd(a, b); 31 #else 32 /* GCC versions where this builtin is buggy */ 33 vec_u64 vr; 34 __asm("vpmsumd %0, %1, %2" 35 : "=v"(vr) 36 : "v"(a), "v"(b)); 37 return vr; 38 #endif 39 } 40 41 SECStatus 42 gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf, 43 unsigned int count) 44 { 45 const vec_u8 leftshift = vec_splat_u8(1); 46 const vec_u64 onebit = (vec_u64){ 1, 0 }; 47 const unsigned long long pd = 0xc2LLU << 56; 48 49 vec_u64 ci, v, r0, r1; 50 vec_u64 hibit; 51 unsigned i; 52 53 ci = ghash->x; 54 55 for (i = 0; i < count; i++, buf += 16) { 56 /* clang needs the following cast away from const; maybe a bug in 7.0.0 */ 57 v = (vec_u64)vec_xl_be(0, (unsigned char *)buf); 58 ci ^= v; 59 60 /* Do binary mult ghash->X = C * ghash->H (Karatsuba). */ 61 r0 = vpmsumd((vec_u64){ ci[0], 0 }, (vec_u64){ ghash->h[0], 0 }); 62 r1 = vpmsumd((vec_u64){ ci[1], 0 }, (vec_u64){ ghash->h[1], 0 }); 63 v = (vec_u64){ ci[0] ^ ci[1], ghash->h[0] ^ ghash->h[1] }; 64 v = vpmsumd((vec_u64){ v[0], 0 }, (vec_u64){ v[1], 0 }); 65 v ^= r0; 66 v ^= r1; 67 r0 ^= (vec_u64){ 0, v[0] }; 68 r1 ^= (vec_u64){ v[1], 0 }; 69 70 /* Shift one (multiply by x) as gcm spec is stupid. */ 71 hibit = (vec_u64)vec_splat((vec_u8)r0, 15); 72 hibit = (vec_u64)vec_rl((vec_u8)hibit, leftshift); 73 hibit &= onebit; 74 r0 = vec_sll(r0, leftshift); 75 r1 = vec_sll(r1, leftshift); 76 r1 |= hibit; 77 78 /* Reduce */ 79 v = vpmsumd((vec_u64){ r0[0], 0 }, (vec_u64){ pd, 0 }); 80 r0 ^= (vec_u64){ 0, v[0] }; 81 r1 ^= (vec_u64){ v[1], 0 }; 82 v = vpmsumd((vec_u64){ r0[1], 0 }, (vec_u64){ pd, 0 }); 83 r1 ^= v; 84 ci = r0 ^ r1; 85 } 86 87 ghash->x = ci; 88 89 return SECSuccess; 90 } 91 92 SECStatus 93 gcm_HashInit_hw(gcmHashContext *ghash) 94 { 95 ghash->x = (vec_u64)vec_splat_u32(0); 96 ghash->h = (vec_u64){ ghash->h_low, ghash->h_high }; 97 ghash->ghash_mul = gcm_HashMult_hw; 98 ghash->hw = PR_TRUE; 99 return SECSuccess; 100 } 101 102 SECStatus 103 gcm_HashZeroX_hw(gcmHashContext *ghash) 104 { 105 ghash->x = (vec_u64)vec_splat_u32(0); 106 return SECSuccess; 107 } 108 109 #endif /* defined(USE_PPC_CRYPTO) */