| 117 | } |
| 118 | |
| 119 | void |
| 120 | SipHash_Update(SIPHASH_CTX *ctx, const void *src, size_t len) |
| 121 | { |
| 122 | uint64_t m; |
| 123 | const uint64_t *p; |
| 124 | const uint8_t *s; |
| 125 | size_t rem; |
| 126 | |
| 127 | KASSERT(ctx->initialized == 2, |
| 128 | ("%s: context %p not properly initialized", __func__, ctx)); |
| 129 | |
| 130 | s = src; |
| 131 | ctx->bytes += len; |
| 132 | |
| 133 | /* |
| 134 | * Push length smaller than block size into buffer or |
| 135 | * fill up the buffer if there is already something |
| 136 | * in it. |
| 137 | */ |
| 138 | if (ctx->buflen > 0 || len < 8) |
| 139 | len -= SipBuf(ctx, &s, len, 0); |
| 140 | if (len == 0) |
| 141 | return; |
| 142 | |
| 143 | rem = len & 0x7; |
| 144 | len >>= 3; |
| 145 | |
| 146 | /* Optimze for 64bit aligned/unaligned access. */ |
| 147 | if (((uintptr_t)s & 0x7) == 0) { |
| 148 | for (p = (const uint64_t *)s; len > 0; len--, p++) { |
| 149 | m = le64toh(*p); |
| 150 | ctx->v[3] ^= m; |
| 151 | SipRounds(ctx, 0); |
| 152 | ctx->v[0] ^= m; |
| 153 | } |
| 154 | s = (const uint8_t *)p; |
| 155 | } else { |
| 156 | for (; len > 0; len--, s += 8) { |
| 157 | m = le64dec(s); |
| 158 | ctx->v[3] ^= m; |
| 159 | SipRounds(ctx, 0); |
| 160 | ctx->v[0] ^= m; |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | /* Push remainder into buffer. */ |
| 165 | if (rem > 0) |
| 166 | (void)SipBuf(ctx, &s, rem, 0); |
| 167 | } |
| 168 | |
| 169 | void |
| 170 | SipHash_Final(uint8_t dst[static SIPHASH_DIGEST_LENGTH], SIPHASH_CTX *ctx) |