16ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
26ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * key.c
36ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
46ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * key usage limits enforcement
56ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
66ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * David A. Mcgrew
76ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Cisco Systems, Inc.
86ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
96ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Copyright (c) 2001-2006 Cisco Systems, Inc.
126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * All rights reserved.
136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Redistribution and use in source and binary forms, with or without
156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * modification, are permitted provided that the following conditions
166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * are met:
176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Redistributions of source code must retain the above copyright
196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   notice, this list of conditions and the following disclaimer.
206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Redistributions in binary form must reproduce the above
226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   copyright notice, this list of conditions and the following
236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   disclaimer in the documentation and/or other materials provided
246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   with the distribution.
256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Neither the name of the Cisco Systems, Inc. nor the names of its
276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   contributors may be used to endorse or promote products derived
286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   from this software without specific prior written permission.
296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE.
426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include "key.h"
466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#define soft_limit 0x10000
486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgkey_limit_set(key_limit_t key, const xtd_seq_num_t s) {
516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef NO_64BIT_MATH
526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (high32(s) == 0 && low32(s) < soft_limit)
536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_bad_param;
546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (s < soft_limit)
566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_bad_param;
576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  key->num_left = s;
596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  key->state = key_state_normal;
606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgkey_limit_clone(key_limit_t original, key_limit_t *new_key) {
656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (original == NULL)
666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_bad_param;
676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  *new_key = original;
686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgerr_status_t
726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgkey_limit_check(const key_limit_t key) {
736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (key->state == key_state_expired)
746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return err_status_key_expired;
756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return err_status_ok;
766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgkey_event_t
796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgkey_limit_update(key_limit_t key) {
806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef NO_64BIT_MATH
816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (low32(key->num_left) == 0)
826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  {
836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	  // carry
846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	  key->num_left = make64(high32(key->num_left)-1,low32(key->num_left) - 1);
856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  else
876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  {
886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	  // no carry
896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	  key->num_left = make64(high32(key->num_left),low32(key->num_left) - 1);
906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (high32(key->num_left) != 0 || low32(key->num_left) >= soft_limit) {
926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return key_event_normal;   /* we're above the soft limit */
936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  key->num_left--;
966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (key->num_left >= soft_limit) {
976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return key_event_normal;   /* we're above the soft limit */
986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
1006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (key->state == key_state_normal) {
1016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* we just passed the soft limit, so change the state */
1026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    key->state = key_state_past_soft_limit;
1036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
1046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef NO_64BIT_MATH
1056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (low32(key->num_left) == 0 && high32(key->num_left == 0))
1066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
1076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (key->num_left < 1)
1086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
1096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  { /* we just hit the hard limit */
1106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    key->state = key_state_expired;
1116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return key_event_hard_limit;
1126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
1136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   return key_event_soft_limit;
1146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
1156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
116