1 // SPDX-License-Identifier: GPL-2.0 1 2 /* 3 * NHPoly1305 - ε-almost-∆-universal hash f 4 * 5 * Copyright 2018 Google LLC 6 */ 7 8 /* 9 * "NHPoly1305" is the main component of Adian 10 * Specifically, it is the calculation 11 * 12 * H_L ← Poly1305_{K_L}(NH_{K_N}(pad_{1 13 * 14 * from the procedure in section 6.4 of the Ad 15 * ε-almost-∆-universal (ε-∆U) hash func 16 * Z/(2^{128}Z), where the "∆" operation is 17 * chunks of the input with the NH hash functi 18 * by 32x. The resulting NH digests are evalu 19 * GF(2^{130}-5), like in the Poly1305 MAC [3] 20 * evaluation by itself would suffice to achie 21 * for performance since it's over twice as fa 22 * 23 * This is *not* a cryptographic hash function 24 * 25 * [1] Adiantum: length-preserving encryption 26 * (https://eprint.iacr.org/2018/720.pdf) 27 * [2] UMAC: Fast and Secure Message Authentic 28 * (https://fastcrypto.org/umac/umac_proc. 29 * [3] The Poly1305-AES message-authentication 30 * (https://cr.yp.to/mac/poly1305-20050329 31 */ 32 33 #include <asm/unaligned.h> 34 #include <crypto/algapi.h> 35 #include <crypto/internal/hash.h> 36 #include <crypto/internal/poly1305.h> 37 #include <crypto/nhpoly1305.h> 38 #include <linux/crypto.h> 39 #include <linux/kernel.h> 40 #include <linux/module.h> 41 42 static void nh_generic(const u32 *key, const u 43 __le64 hash[NH_NUM_PASS 44 { 45 u64 sums[4] = { 0, 0, 0, 0 }; 46 47 BUILD_BUG_ON(NH_PAIR_STRIDE != 2); 48 BUILD_BUG_ON(NH_NUM_PASSES != 4); 49 50 while (message_len) { 51 u32 m0 = get_unaligned_le32(me 52 u32 m1 = get_unaligned_le32(me 53 u32 m2 = get_unaligned_le32(me 54 u32 m3 = get_unaligned_le32(me 55 56 sums[0] += (u64)(u32)(m0 + key 57 sums[1] += (u64)(u32)(m0 + key 58 sums[2] += (u64)(u32)(m0 + key 59 sums[3] += (u64)(u32)(m0 + key 60 sums[0] += (u64)(u32)(m1 + key 61 sums[1] += (u64)(u32)(m1 + key 62 sums[2] += (u64)(u32)(m1 + key 63 sums[3] += (u64)(u32)(m1 + key 64 key += NH_MESSAGE_UNIT / sizeo 65 message += NH_MESSAGE_UNIT; 66 message_len -= NH_MESSAGE_UNIT 67 } 68 69 hash[0] = cpu_to_le64(sums[0]); 70 hash[1] = cpu_to_le64(sums[1]); 71 hash[2] = cpu_to_le64(sums[2]); 72 hash[3] = cpu_to_le64(sums[3]); 73 } 74 75 /* Pass the next NH hash value through Poly130 76 static void process_nh_hash_value(struct nhpol 77 const struct 78 { 79 BUILD_BUG_ON(NH_HASH_BYTES % POLY1305_ 80 81 poly1305_core_blocks(&state->poly_stat 82 NH_HASH_BYTES / P 83 } 84 85 /* 86 * Feed the next portion of the source data, a 87 * "NH message units", through NH and Poly1305 88 * 1024 bytes, except possibly the final one w 89 * 16 bytes up to 1024. Also, in the case whe 90 * chunks, we combine partial hashes; the end 91 */ 92 static void nhpoly1305_units(struct nhpoly1305 93 const struct nhpo 94 const u8 *src, un 95 { 96 do { 97 unsigned int bytes; 98 99 if (state->nh_remaining == 0) 100 /* Starting a new NH m 101 bytes = min_t(unsigned 102 nh_fn(key->nh_key, src 103 state->nh_remaining = 104 } else { 105 /* Continuing a previo 106 __le64 tmp_hash[NH_NUM 107 unsigned int pos; 108 int i; 109 110 pos = NH_MESSAGE_BYTES 111 bytes = min(srclen, st 112 nh_fn(&key->nh_key[pos 113 for (i = 0; i < NH_NUM 114 le64_add_cpu(& 115 l 116 state->nh_remaining -= 117 } 118 if (state->nh_remaining == 0) 119 process_nh_hash_value( 120 src += bytes; 121 srclen -= bytes; 122 } while (srclen); 123 } 124 125 int crypto_nhpoly1305_setkey(struct crypto_sha 126 const u8 *key, un 127 { 128 struct nhpoly1305_key *ctx = crypto_sh 129 int i; 130 131 if (keylen != NHPOLY1305_KEY_SIZE) 132 return -EINVAL; 133 134 poly1305_core_setkey(&ctx->poly_key, k 135 key += POLY1305_BLOCK_SIZE; 136 137 for (i = 0; i < NH_KEY_WORDS; i++) 138 ctx->nh_key[i] = get_unaligned 139 140 return 0; 141 } 142 EXPORT_SYMBOL(crypto_nhpoly1305_setkey); 143 144 int crypto_nhpoly1305_init(struct shash_desc * 145 { 146 struct nhpoly1305_state *state = shash 147 148 poly1305_core_init(&state->poly_state) 149 state->buflen = 0; 150 state->nh_remaining = 0; 151 return 0; 152 } 153 EXPORT_SYMBOL(crypto_nhpoly1305_init); 154 155 int crypto_nhpoly1305_update_helper(struct sha 156 const u8 * 157 nh_t nh_fn 158 { 159 struct nhpoly1305_state *state = shash 160 const struct nhpoly1305_key *key = cry 161 unsigned int bytes; 162 163 if (state->buflen) { 164 bytes = min(srclen, (int)NH_ME 165 memcpy(&state->buffer[state->b 166 state->buflen += bytes; 167 if (state->buflen < NH_MESSAGE 168 return 0; 169 nhpoly1305_units(state, key, s 170 nh_fn); 171 state->buflen = 0; 172 src += bytes; 173 srclen -= bytes; 174 } 175 176 if (srclen >= NH_MESSAGE_UNIT) { 177 bytes = round_down(srclen, NH_ 178 nhpoly1305_units(state, key, s 179 src += bytes; 180 srclen -= bytes; 181 } 182 183 if (srclen) { 184 memcpy(state->buffer, src, src 185 state->buflen = srclen; 186 } 187 return 0; 188 } 189 EXPORT_SYMBOL(crypto_nhpoly1305_update_helper) 190 191 int crypto_nhpoly1305_update(struct shash_desc 192 const u8 *src, un 193 { 194 return crypto_nhpoly1305_update_helper 195 } 196 EXPORT_SYMBOL(crypto_nhpoly1305_update); 197 198 int crypto_nhpoly1305_final_helper(struct shas 199 { 200 struct nhpoly1305_state *state = shash 201 const struct nhpoly1305_key *key = cry 202 203 if (state->buflen) { 204 memset(&state->buffer[state->b 205 NH_MESSAGE_UNIT - state 206 nhpoly1305_units(state, key, s 207 nh_fn); 208 } 209 210 if (state->nh_remaining) 211 process_nh_hash_value(state, k 212 213 poly1305_core_emit(&state->poly_state, 214 return 0; 215 } 216 EXPORT_SYMBOL(crypto_nhpoly1305_final_helper); 217 218 int crypto_nhpoly1305_final(struct shash_desc 219 { 220 return crypto_nhpoly1305_final_helper( 221 } 222 EXPORT_SYMBOL(crypto_nhpoly1305_final); 223 224 static struct shash_alg nhpoly1305_alg = { 225 .base.cra_name = "nhpoly1305" 226 .base.cra_driver_name = "nhpoly1305- 227 .base.cra_priority = 100, 228 .base.cra_ctxsize = sizeof(struc 229 .base.cra_module = THIS_MODULE, 230 .digestsize = POLY1305_DIG 231 .init = crypto_nhpol 232 .update = crypto_nhpol 233 .final = crypto_nhpol 234 .setkey = crypto_nhpol 235 .descsize = sizeof(struc 236 }; 237 238 static int __init nhpoly1305_mod_init(void) 239 { 240 return crypto_register_shash(&nhpoly13 241 } 242 243 static void __exit nhpoly1305_mod_exit(void) 244 { 245 crypto_unregister_shash(&nhpoly1305_al 246 } 247 248 subsys_initcall(nhpoly1305_mod_init); 249 module_exit(nhpoly1305_mod_exit); 250 251 MODULE_DESCRIPTION("NHPoly1305 ε-almost-∆-u 252 MODULE_LICENSE("GPL v2"); 253 MODULE_AUTHOR("Eric Biggers <ebiggers@google.c 254 MODULE_ALIAS_CRYPTO("nhpoly1305"); 255 MODULE_ALIAS_CRYPTO("nhpoly1305-generic"); 256
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.