/* * Copyright 1997-2000 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Niels Provos. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ /* * validity.c: * validity verification */ #ifndef lint static char rcsid[] = "$Id: validity.c,v 1.3 2000/12/15 02:50:40 provos Exp $"; #endif #define _VALIDITY_C_ #include #include #include #include #include #include #include #include #include #include "config.h" #include "scheme.h" #include "exchange.h" #include "log.h" #include "state.h" #include "attributes.h" #include "validity.h" #include "identity.h" #include "buffer.h" int valsign(struct stateob *st, struct idxform *hash, u_int8_t *signature, u_int8_t *packet, u_int16_t psize); int valverify(struct stateob *st, struct idxform *hash, u_int8_t *signature, u_int8_t *packet, u_int16_t psize); u_int16_t get_validity_verification_size(struct stateob *st) { switch(ntohs(*((u_int16_t *)st->scheme))) { case DH_G_2_MD5: case DH_G_3_MD5: case DH_G_5_MD5: case DH_G_2_DES_MD5: case DH_G_3_DES_MD5: case DH_G_5_DES_MD5: return (128/8)+2; /* Two octets for varpre size */ case DH_G_2_3DES_SHA1: case DH_G_3_3DES_SHA1: case DH_G_5_3DES_SHA1: return (160/8)+2; default: log_print("validitiy.c: Unknown exchange scheme: %d\n", *((u_int16_t *)st->scheme)); return 0; } } int create_validity_verification(struct stateob *st, u_int8_t *buffer, u_int8_t *packet, u_int16_t size) { struct idxform *hash; switch(ntohs(*((u_int16_t *)st->scheme))) { case DH_G_2_MD5: case DH_G_3_MD5: case DH_G_5_MD5: case DH_G_2_DES_MD5: case DH_G_3_DES_MD5: case DH_G_5_DES_MD5: hash = get_hash(HASH_MD5); break; case DH_G_2_3DES_SHA1: case DH_G_3_3DES_SHA1: case DH_G_5_3DES_SHA1: hash = get_hash(HASH_SHA1); break; default: log_print("validity.c: Unknown exchange scheme: %d\n", *((u_int16_t *)st->scheme)); return 0; } if(valsign(st, hash, buffer+2, packet, size)) { /* Create varpre number from digest */ buffer[0] = (hash->hashsize >> 5) & 0xFF; buffer[1] = (hash->hashsize << 3) & 0xFF; } state_save_verification(st, buffer, hash->hashsize+2); return hash->hashsize+2; } int verify_validity_verification(struct stateob *st, u_int8_t *buffer, u_int8_t *packet, u_int16_t size) { struct idxform *hash; switch(ntohs(*((u_int16_t *)st->scheme))) { case DH_G_2_MD5: case DH_G_3_MD5: case DH_G_5_MD5: case DH_G_2_DES_MD5: case DH_G_3_DES_MD5: case DH_G_5_DES_MD5: if (varpre2octets(buffer) != 18) return 0; hash = get_hash(HASH_MD5); break; case DH_G_2_3DES_SHA1: case DH_G_3_3DES_SHA1: case DH_G_5_3DES_SHA1: if (varpre2octets(buffer) != 22) return 0; hash = get_hash(HASH_SHA1); break; default: log_print("validity.c: Unknown exchange scheme: %d\n", *((u_int16_t *)st->scheme)); return 0; } state_save_verification(st, buffer, hash->hashsize+2); return valverify(st, hash, buffer+2, packet, size); } int valsign(struct stateob *st, struct idxform *hash, u_int8_t *signature, u_int8_t *packet, u_int16_t psize) { u_int8_t key[HASH_MAX]; u_int16_t keylen = HASH_MAX; create_verification_key(st, key, &keylen, 1); /* Owner direction */ hash->Init(hash->ctx); hash->Update(hash->ctx, key, keylen); hash->Update(hash->ctx, st->icookie, COOKIE_SIZE); hash->Update(hash->ctx, st->rcookie, COOKIE_SIZE); packet += 2*COOKIE_SIZE; psize -= 2*COOKIE_SIZE; hash->Update(hash->ctx, packet, 4 + SPI_SIZE); hash->Update(hash->ctx, st->oSPIidentver, st->oSPIidentversize); hash->Update(hash->ctx, st->uSPIidentver, st->uSPIidentversize); packet += 4 + SPI_SIZE + hash->hashsize + 2; psize -= 4 + SPI_SIZE + hash->hashsize + 2; hash->Update(hash->ctx, packet, psize); /* Data fill */ hash->Final(NULL, hash->ctx); hash->Update(hash->ctx, key, keylen); hash->Final(signature, hash->ctx); return hash->hashsize; } /* We assume that the verification field is zeroed */ int valverify(struct stateob *st, struct idxform *hash, u_int8_t *signature, u_int8_t *packet, u_int16_t psize) { u_int8_t digest[HASH_MAX]; u_int8_t key[HASH_MAX]; u_int16_t keylen = HASH_MAX; create_verification_key(st, key, &keylen, 0); /* User direction */ hash->Init(hash->ctx); hash->Update(hash->ctx, key, keylen); hash->Update(hash->ctx, st->icookie, COOKIE_SIZE); hash->Update(hash->ctx, st->rcookie, COOKIE_SIZE); packet += 2*COOKIE_SIZE; psize -= 2*COOKIE_SIZE; hash->Update(hash->ctx, packet, 4 + SPI_SIZE); hash->Update(hash->ctx, st->uSPIidentver, st->uSPIidentversize); hash->Update(hash->ctx, st->oSPIidentver, st->oSPIidentversize); packet += 4 + SPI_SIZE + hash->hashsize + 2; psize -= 4 + SPI_SIZE + hash->hashsize + 2; hash->Update(hash->ctx, packet, psize); /* Data fill */ hash->Final(NULL, hash->ctx); hash->Update(hash->ctx, key, keylen); hash->Final(digest, hash->ctx); return !bcmp(digest,signature,hash->hashsize); }