📄 tmmh.c
字号:
/* * tmmh.c * * tmmh - the extended mmh hash function, with authenticated * truncation * * David A. McGrew * Cisco Systems, Inc. * *//* * * Copyright (c) 2001, 2002, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the Cisco Systems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * *//* * This implemenation is VERSION ONE of TMMH - you probably want * version two, which is in the file tmmhv2.c. */#include <stdlib.h> /* for malloc() */#include "tmmh.h"#define TMMH_MOD_EXPLICIT 0 /* don't use an explicit modulo operation */hash_statustmmh_16_init(tmmh_16_ctx_t *ctx, octet_t *value, int key_len, int output_len) { int i; uint16_t *key = (uint16_t *)value; /* check parameters */ if ((key_len & 1) || (key_len - output_len - 2 <= 0)) return hash_status_init_err; /* allocate space for the key */ ctx->value = malloc(key_len); if (ctx->value == NULL) return hash_status_init_err; ctx->key_length = key_len; ctx->tag_length = output_len; /* copy key and convert into host byte order */ for (i=0; i < key_len/2; i++) ctx->value[i] = ntohs(*key++); return hash_status_normal;}hash_statustmmh_16_init_uint16(tmmh_16_ctx_t *ctx, uint16_t *value, int key_len, int output_len) { ctx->key_length = key_len; ctx->value = value; ctx->tag_length = output_len; return 0;}hash_statustmmh_16_compute(tmmh_16_ctx_t *key, octet_t *m, int len_octets, octet_t *result) { uint16_t *msg = (uint16_t *)m; uint16_t *msg_penultimate = msg + (len_octets-1)/2; uint16_t *K = key->value; uint16_t tmp; uint32_t sum; uint32_t utmp; int32_t stmp; sum = (uint32_t) *K++ * len_octets; /* hash most of message into sum */ while (msg < msg_penultimate) { tmp = ntohs(*msg++); sum += (uint32_t) *K++ * tmp; } /* if len is odd, zeroize the last octet */ *msg = ntohs(*msg); if (len_octets & 1) *msg &= 0xff00; /* hash ultimate word of message into sum */ sum += (uint32_t) *K * *msg; /* compute modulus */#if TMMH_MOD_EXPLICIT sum = sum % tmmh_16_prime;#else stmp = (sum & 0xffff) - (sum >> 16); utmp = (stmp & 0xffff) - (stmp >> 16); sum = utmp & 0xffff; if (utmp > 0x10001) sum -= 1;#endif /* report result */ sum = htons(sum); result[0] = sum >> 8; result[1] = sum & 0xff;/* (*(uint16_t *)result) = htons(sum); */ return hash_status_normal;}hash_statustmmh_16_compute_aligned(tmmh_16_ctx_t *key, uint16_t *msg, int len_octets, uint16_t *result) { uint16_t *msg_penultimate = msg + (len_octets/2) - 1; uint16_t *K = key->value; uint32_t sum = 0; uint32_t utmp; int32_t stmp; /* hash message length in octets into sum */ sum += (uint32_t) *K++ * len_octets; /* hash most of message into sum */ while (msg < msg_penultimate) { sum += (uint32_t) *K++ * *msg++; } /* if len is odd, zeroize the last octet */ if (len_octets & 1) *msg &= 0xff; /* hash ultimate word of message into sum */ sum += (uint32_t) *K * *msg; /* compute modulus */#if TMMH_MOD_EXPLICIT sum = sum % tmmh_16_prime;#else stmp = (sum & 0xffff) - (sum >> 16); utmp = (stmp & 0xffff) - (stmp >> 16); sum = utmp & 0xffff; if (utmp > 0x10001) sum -= 1;#endif /* report result */ *result = (uint16_t) sum; return hash_status_normal;}hash_statustmmh_16_compute_4_aligned(tmmh_16_ctx_t *key, uint16_t *msg, int len_octets, uint16_t *result) { uint16_t *msg_penultimate = msg + (len_octets/2) - 1; uint16_t *K = key->value; uint32_t sum0, sum1; uint32_t utmp; int32_t stmp; /* hash message length in octets into sums */ sum0 = (uint32_t) *K++ * len_octets; sum1 = (uint32_t) *K * len_octets; /* hash most of message into sum */ while (msg < msg_penultimate) { sum0 += (uint32_t) *K++ * *msg; sum1 += (uint32_t) *K * *msg++; } /* if len is odd, zeroize the last octet */ if (len_octets & 1) *msg &= 0xff; /* hash ultimate word of message into sums */ sum0 += (uint32_t) *K++ * *msg; sum1 += (uint32_t) *K * *msg; /* compute moduli */#if TMMH_MOD_EXPLICIT sum0 = sum0 % tmmh_16_prime; sum1 = sum1 % tmmh_16_prime;#else stmp = (sum0 & 0xffff) - (sum0 >> 16); utmp = (stmp & 0xffff) - (stmp >> 16); sum0 = utmp & 0xffff; if (utmp > 0x10001) sum0 -= 1; stmp = (sum1 & 0xffff) - (sum1 >> 16); utmp = (stmp & 0xffff) - (stmp >> 16); sum1 = utmp & 0xffff; if (utmp > 0x10001) sum1 -= 1;#endif /* report result */ *result++ = (uint16_t) sum0; *result = (uint16_t) sum1; return hash_status_normal;}hash_statustmmh_16_compute_4(tmmh_16_ctx_t *key, octet_t *m, int len_octets, octet_t *result) { uint16_t *msg = (uint16_t *)m; uint16_t *msg_penultimate = (uint16_t *)(m + (len_octets/2) - 1); uint16_t *K = key->value; uint32_t sum0, sum1; uint32_t utmp; int32_t stmp; /* hash message length in octets into sums */ sum0 = (uint32_t) *K++ * len_octets; sum1 = (uint32_t) *K * len_octets; /* hash most of message into sum */ while (msg < msg_penultimate) { sum0 += (uint32_t) *K++ * *msg; sum1 += (uint32_t) *K * *msg++; } /* if len is odd, zeroize the last octet */ if (len_octets & 1) *msg &= 0xff; /* hash ultimate word of message into sums */ sum0 += (uint32_t) *K++ * *msg; sum1 += (uint32_t) *K * *msg; /* compute moduli */#if TMMH_MOD_EXPLICIT sum0 = sum0 % tmmh_16_prime; sum1 = sum1 % tmmh_16_prime;#else stmp = (sum0 & 0xffff) - (sum0 >> 16); utmp = (stmp & 0xffff) - (stmp >> 16); sum0 = utmp & 0xffff; if (utmp > 0x10001) sum0 -= 1; stmp = (sum1 & 0xffff) - (sum1 >> 16); utmp = (stmp & 0xffff) - (stmp >> 16); sum1 = utmp & 0xffff; if (utmp > 0x10001) sum1 -= 1;#endif /* report result */ *result++ = (uint16_t) sum0; *result = (uint16_t) sum1; return hash_status_normal;}char tmmh_16_description[] = "truncated multi-modular hash TMMH/16";hash_statushash_set_to_tmmh_16(hash *h, tmmh_16_ctx_t *ctx, int output_length) { h->init = (hash_init_func) tmmh_16_init; if (output_length == 2) { h->out_len = 2; h->compute = (hash_compute_func) tmmh_16_compute; } else if (output_length == 4) { h->out_len = 4; h->compute = (hash_compute_func) tmmh_16_compute_4; } else { return hash_status_init_err; } h->state = ctx; h->type = hash_type_tmmh_16; h->description = tmmh_16_description; return hash_status_normal;}/* below are the tmmh_32 routines */hash_statustmmh_32_init(tmmh_32_ctx_t *ctx, octet_t *value, int key_len, int output_len) { int i; uint32_t *key = (uint32_t *)value; /* check parameters */ if (((key_len & 3) != 0) || (key_len - output_len <= 0)) return hash_status_init_err; /* allocate space for the key */ ctx->value = malloc(key_len); if (ctx->value == NULL) return hash_status_init_err; ctx->key_length = key_len; ctx->tag_length = output_len; /* copy key and convert into host byte order */ for (i=0; i < key_len/4; i++) ctx->value[i] = ntohl(*key++); /* set state value to zero and current_key to start value */ ctx->state = 0; ctx->current_key = ctx->value; return hash_status_normal;}#include <stdio.h>hash_statustmmh_32_compute(tmmh_32_ctx_t *key, octet_t *m, int len_octets, octet_t *result) { uint32_t *msg = (uint32_t *)m; uint32_t *msg_penultimate = msg + (len_octets-1)/4; uint32_t *K = key->value; uint32_t tmp; uint64_t sum; uint64_t utmp; int64_t stmp; sum = (uint64_t) *K++ * len_octets;/* printf("sum: %llu\n", sum); */ /* hash most of message into sum */ while (msg < msg_penultimate) { tmp = ntohl(*msg++); sum += (uint64_t) *K++ * tmp;/* printf("dth word of message: %x\n", tmp); *//* printf("sum: %llu\n", sum); */ } /* zeroize octets, according to length */ tmp = ntohl(*msg); switch (len_octets & 3) { case 3: tmp &= 0xffffff00; break; case 2: tmp &= 0xffff0000; break; case 1: tmp &= 0xff000000; break; case 0: /* no padding needed */ } /* hash ultimate word of message into sum */ sum += (uint64_t) *K * tmp;/* printf("last word of message: %x\n", tmp); *//* printf("sum: %llu\n", sum); */ /* compute modulus */#if TMMH_MOD_EXPLICIT sum = (uint64_t) sum % tmmh_32_prime;#else stmp = (sum & 0xffffffffLL) - ((sum >> 32) * 15); utmp = (stmp & 0xffffffffLL) - ((stmp >> 32) * 15); sum = utmp & 0xffffffffLL; if (utmp > 0x10000000fLL) sum -= 15;#endif /* report result *//* printf("result: %x\n", sum); *//* sum = htonl(sum); *//* result[0] = sum >> 8; *//* result[1] = sum & 0xff; */ /* (*(uint32_t *)result) = htonl(sum); */ /* add sum into result */ (*(uint32_t *)result) = htonl(ntohl(*(uint32_t *)result) + sum); return hash_status_normal;}const char *tmmh_32_description = "truncated multi-modular hash TMMH/32";hash_statushash_set_to_tmmh_32(hash *h, tmmh_32_ctx_t *ctx, int out_len) { h->init = (hash_init_func) tmmh_32_init; if (out_len == 4) { h->out_len = 4; h->compute = (hash_compute_func) tmmh_32_compute; } else { return hash_status_init_err; } h->state = ctx; h->type = hash_type_tmmh_32; h->description = tmmh_32_description; return hash_status_normal;}/* DAM -- auth.h ---------------------------------------------------- */#include "auth.h"err_statustmmh_16_compute_auth(tmmh_16_ctx_t *key, octet_t *m, int len_octets, octet_t *result) { uint16_t *msg = (uint16_t *)m; uint16_t *msg_penultimate = msg + (len_octets-1)/2; uint16_t *K = key->value; uint16_t tmp; uint32_t sum; uint32_t utmp; int32_t stmp; sum = (uint32_t) *K++ * len_octets; /* hash most of message into sum */ while (msg < msg_penultimate) { tmp = ntohs(*msg++); sum += (uint32_t) *K++ * tmp; } /* if len is odd, zeroize the last octet */ *msg = ntohs(*msg); if (len_octets & 1) *msg &= 0xff00; /* hash ultimate word of message into sum */ sum += (uint32_t) *K * *msg; /* compute modulus */#if TMMH_MOD_EXPLICIT sum = sum % tmmh_16_prime;#else stmp = (sum & 0xffff) - (sum >> 16); utmp = (stmp & 0xffff) - (stmp >> 16); sum = utmp & 0xffff; if (utmp > 0x10001) sum -= 1;#endif /* compare with auth. tag and return result */ sum = htons(sum); printf("sum: %x\n", sum); if ((result[0] == (sum >> 8)) && (result[1] == (sum & 0xff))) return err_status_ok; return err_status_fail;}err_statustmmh_16_alloc(auth **a, int key_len, int out_len) { extern auth_type_t tmmh_16; int tmp; void *pointer; tmmh_16_ctx_t *tmmh_state; /* check parameters */ if ((key_len & 1) || (key_len - out_len - 2 <= 0)) return err_status_bad_param; /* allocate memory a auth func of type tmmh_16 */ tmp = (sizeof(tmmh_16_ctx_t) + sizeof(auth) + key_len); pointer = malloc(tmp); *a = pointer; if (*a == NULL) { fprintf(stderr, "failed to allocate %d bytes\n", tmp); return err_status_alloc_fail; } fprintf(stderr, "allocated %d bytes at %p\n", tmp, pointer); /* set pointers and parameters */ (*a)->type = &tmmh_16; tmmh_state = (tmmh_16_ctx_t *) *a + sizeof(auth); (*a)->state = tmmh_state; tmmh_state->value = (uint16_t *)(*a + sizeof(auth) + sizeof(tmmh_16_ctx_t)); tmmh_state->key_length = key_len; tmmh_state->tag_length = out_len; /* increment ref_count */ tmmh_16.ref_count++; /* set key size */ ((tmmh_16_ctx_t *)(*a)->state)->key_length = key_len; return err_status_ok; }err_statustmmh_16_dealloc(auth *a) { extern auth_type_t tmmh_16; /* deallocate memory */ fprintf(stderr, "freeing memory at %p\n", a); free(a); /* decrement ref count */ tmmh_16.ref_count--; return err_status_ok;}err_statustmmh_16_init_auth(tmmh_16_ctx_t *state, const octet_t *key, int key_len) { int i; /* copy key and convert into host byte order */ for (i=0; i < key_len/2; i++) state->value[i] = ntohs(*key++); return err_status_ok;}auth_type_ttmmh_16 = { (auth_alloc_func) tmmh_16_alloc, (auth_dealloc_func) tmmh_16_dealloc, (auth_init_func) tmmh_16_init_auth, (auth_compute_func) tmmh_16_compute_auth, (auth_id) auth_id_tmmh_16, (char *) tmmh_16_description, (int) 0, (auth_test_case_t *) NULL };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -