/* * Copyright (C) 2004 Mike Wray * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free software Foundation, Inc., * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include "hash_table.h" #include "allocate.h" #define MODULE_NAME "IPSEC" #define DEBUG 1 #undef DEBUG #include "debug.h" /** @file IPSEC Security Association (SA). */ /** Maximum number of protocols.*/ #define INET_PROTOCOL_MAX 256 /** Table of SA types indexed by protocol. */ static SAType *sa_type[INET_PROTOCOL_MAX] = {}; /** Hash a protocol number. * * @param protocol protocol number * @return hashcode */ static inline unsigned char InetProtocol_hash(int protocol){ return (protocol) & (INET_PROTOCOL_MAX - 1); } /** Register an SA type. * It is an error if an SA type is already registered for the protocol. * * @param type SA type * @return 0 on success, error code otherwise */ int SAType_add(SAType *type){ int err = -EINVAL; int hash; if(!type) goto exit; hash = InetProtocol_hash(type->protocol); if(sa_type[hash]) goto exit; err = 0; sa_type[hash] = type; exit: return err; } /** Deregister an SA type. * It is an error if no SA type is registered for the protocol. * * @param type SA type * @return 0 on success, error code otherwise */ int SAType_del(SAType *type){ int err = -EINVAL; int hash; if(!type) goto exit; hash = InetProtocol_hash(type->protocol); if(!sa_type[hash]) goto exit; err = 0; sa_type[hash] = NULL; exit: return err; } int SAType_get(int protocol, SAType **type){ int err = -ENOENT; int hash; hash = InetProtocol_hash(protocol); *type = sa_type[hash]; if(!*type) goto exit; err = 0; exit: return err; } /* Defeat compiler warnings about unused functions. */ static int sa_key_check(SAKey *key, enum sa_alg_type type) __attribute__((unused)); static u32 random_spi(void) __attribute__((unused)); static u32 generate_key(u32 key, u32 offset, u32 spi) __attribute__((unused)); /** Check a key has an acceptable length for an algorithm. * * @param key key * @param type algorithm * @return 0 on success, error code otherwise */ static int sa_key_check(SAKey *key, enum sa_alg_type type){ return 0; } static unsigned long sa_spi_counter = 0; /** Mangle some input to generate output. * This is used to derive spis and keying material from secrets, * so it probably ought to be cryptographically strong. * Probably ought to use a good hash (sha1) or cipher (aes). * * @param input input bytes * @param n number of bytes * @return mangled value */ static u32 mangle(void *input, int n){ return hash_hvoid(0, input, n); } /** Generate a random spi. * Uses a hashed counter. * * @return spi */ static u32 random_spi(void){ u32 spi; do{ spi = sa_spi_counter++; spi = mangle(&spi, sizeof(spi)); } while(!spi); return spi; } /** Generate a spi for a given protocol and address, using a secret key. * The offset is used when it is necessary to generate more than one spi * for the same protocol and address. * * @param key key * @param offset offset * @param protocol protocol * @param addr IP address * @return spi */ static u32 generate_spi(u32 key, u32 offset, u32 protocol, u32 addr){ u32 input[] = { key, offset, protocol, addr }; return mangle(input, sizeof(input)); } /** Generate keying material for a given spi, based on a * secret. * * @param key secret * @param offset offset * @param spi spi * @return keying material */ static u32 generate_key(u32 key, u32 offset, u32 spi){ u32 input[] = { key, offset, spi }; return mangle(input, sizeof(input)); } /** Allocate a spi. * Want to use random ones. * So check for ones not in use. * * When using static keying, both ends need to agree on key. * How does that work? Also, will suddenly get traffic using a spi, * and will have to create SA then. Or need to create in advance. * But can't do that because don't know peers. * When get message on a spi that doesn't exist - do what? * Use a spi related to the destination addr and a secret. * Then receiver can check if spi is ok and create SA on demand. * Use hash of key, protocol, addr to generate. Then have to check * for in-use because of potential collisions. Receiver can do the * same hash and check spi is in usable range. Then derive keys from * the spi (using another secret). * * @param key spi generation key * @param protocol protocol * @param addr IP address * @param spip return parameter for spi * @return 0 on success, error code otherwise */ int sa_spi_alloc(u32 key, u32 protocol, u32 addr, u32 *spip){ int err = 0; int i = 0, n = 100; u32 spi; for(i = 0; i < n; i++, spi++){ spi = generate_spi(key, i, protocol, addr); if(!spi) continue; if(!sa_table_lookup_spi(spi, protocol, addr)){ *spip = spi; goto exit; } } err = -ENOMEM; exit: return err; } /** Table of SAs. Indexed by unique id and spi/protocol/addr triple. */ static HashTable *sa_table = NULL; static u32 sa_id = 1; /** Hash an SA id. * * @param id SA id * @return hashcode */ static inline Hashcode sa_table_hash_id(u32 id){ return hash_hvoid(0, &id, sizeof(id)); } /** Hash SA spi/protocol/addr. * * @param spi spi * @param protocol protocol * @param addr IP address * @return hashcode */ static inline Hashcode sa_table_hash_spi(u32 spi, u32 protocol, u32 addr){ u32 a[] = { spi, protocol, addr }; return hash_hvoid(0, a, sizeof(a)); } /** Test if an SA entry has a given value. * * @param arg contains SA pointer * @param table hashtable * @param entry entry containing SA * @return 1 if it does, 0 otherwise */ static int sa_table_state_fn(TableArg arg, HashTable *table, HTEntry *entry){ return entry->value == arg.ptr; } /** Test if an SA entry has a given id. * * @param arg contains SA id * @param table hashtable * @param entry entry containing SA * @return 1 if it does, 0 otherwise */ static int sa_table_id_fn(TableArg arg, HashTable *table, HTEntry *entry){ SAState *state = entry->value; u32 id = arg.ul; return state->ident.id == id; } /** Test if an SA entry has a given spi/protocol/addr. * * @param arg contains SAIdent pointer * @param table hashtable * @param entry entry containing SA * @return 1 if it does, 0 otherwise */ static int sa_table_spi_fn(TableArg arg, HashTable *table, HTEntry *entry){ SAState *state = entry->value; SAIdent *ident = arg.ptr; return state->ident.spi == ident->spi && state->ident.protocol == ident->protocol && state->ident.addr == ident->addr; } /** Free an SA entry. Decrements the SA refcount and frees the entry. * * @param table containing table * @param entry to free */ static void sa_table_free_fn(HashTable *table, HTEntry *entry){ if(!entry) return; if(entry->value){ SAState *state = entry->value; SAState_decref(state); } deallocate(entry); } /** Initialize the SA table. * * @return 0 on success, error code otherwise */ int sa_table_init(void){ int err = 0; sa_table = HashTable_new(0); if(!sa_table){ err = -ENOMEM; goto exit; } sa_table->entry_free_fn = sa_table_free_fn; exit: return err; } void sa_table_exit(void){ HashTable_free(sa_table); } /** Remove an SA from the table. * * @param state SA */ int sa_table_delete(SAState *state){ int count = 0; Hashcode h1, h2; TableArg arg = { .ptr = state }; // Remove by id. h1 = sa_table_hash_id(state->ident.id); count += HashTable_remove_entry(sa_table, h1, sa_table_state_fn, arg); // Remove by spi/protocol/addr if spi nonzero. if(!state->ident.spi) goto exit; h2 = sa_table_hash_spi(state->ident.spi, state->ident.protocol, state->ident.addr); if(h1 == h2) goto exit; count += HashTable_remove_entry(sa_table, h2, sa_table_state_fn, arg); exit: return count; } /** Add an SA to the table. * The SA is indexed by id and spi/protocol/addr (if the spi is non-zero). * * @param state SA * @return 0 on success, error code otherwise */ int sa_table_add(SAState *state){ int err = 0; Hashcode h1, h2; int entries = 0; dprintf(">\n"); // Index by id. h1 = sa_table_hash_id(state->ident.id); if(!HashTable_add_entry(sa_table, h1, HKEY(state->ident.id), state)){ err = -ENOMEM; goto exit; } entries++; SAState_incref(state); // Index by spi/protocol/addr if spi non-zero. if(state->ident.spi){ h2 = sa_table_hash_spi(state->ident.spi, state->ident.protocol, state->ident.addr); if(h1 != h2){ if(!HashTable_add_entry(sa_table, h2, HKEY(state->ident.id), state)){ err = -ENOMEM; goto exit; } entries++; SAState_incref(state); } } exit: if(err && entries){ sa_table_delete(state); } dprintf("< err=%d\n", err); return err; } /** Find an SA by spi/protocol/addr. * Increments the SA refcount on success. * * @param spi spi * @param protocol
/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011,2012 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#define STM32F103_MCUCONF

/*
 * STM32F103 drivers configuration.
 * The following settings override the default settings present in
 * the various device driver implementation headers.
 * Note that the settings for each driver only have effect if the whole
 * driver is enabled in halconf.h.
 *
 * IRQ priorities:
 * 15...0       Lowest...Highest.
 *
 * DMA priorities:
 * 0...3        Lowest...Highest.
 */

/*
 * HAL driver system settings.
 */
#define STM32_NO_INIT                       FALSE
#define STM32_HSI_ENABLED                   TRUE
#define STM32_LSI_ENABLED                   FALSE
#define STM32_HSE_ENABLED                   TRUE
#define STM32_LSE_ENABLED                   FALSE
#define STM32_SW                            STM32_SW_PLL
#define STM32_PLLSRC                        STM32_PLLSRC_HSE
#define STM32_PLLXTPRE                      STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE                  9
#define STM32_HPRE                          STM32_HPRE_DIV1
#define STM32_PPRE1                         STM32_PPRE1_DIV2
#define STM32_PPRE2                         STM32_PPRE2_DIV2
#define STM32_ADCPRE                        STM32_ADCPRE_DIV4
#define STM32_USB_CLOCK_REQUIRED            TRUE
#define STM32_USBPRE                        STM32_USBPRE_DIV1P5
#define STM32_MCOSEL                        STM32_MCOSEL_NOCLOCK
#define STM32_RTCSEL                        STM32_RTCSEL_HSEDIV
#define STM32_PVD_ENABLE                    FALSE
#define STM32_PLS                           STM32_PLS_LEV0

/*
 * ADC driver system settings.
 */
#define STM32_ADC_USE_ADC1                  FALSE
#define STM32_ADC_ADC1_DMA_PRIORITY         2
#define STM32_ADC_ADC1_IRQ_PRIORITY         6

/*
 * CAN driver system settings.
 */
#define STM32_CAN_USE_CAN1                  FALSE
#define STM32_CAN_CAN1_IRQ_PRIORITY         11

/*
 * EXT driver system settings.
 */
#define STM32_EXT_EXTI0_IRQ_PRIORITY        6
#define STM32_EXT_EXTI1_IRQ_PRIORITY        6
#define STM32_EXT_EXTI2_IRQ_PRIORITY        6
#define STM32_EXT_EXTI3_IRQ_PRIORITY        6
#define STM32_EXT_EXTI4_IRQ_PRIORITY        6
#define STM32_EXT_EXTI5_9_IRQ_PRIORITY      6
#define STM32_EXT_EXTI10_15_IRQ_PRIORITY    6
#define STM32_EXT_EXTI16_IRQ_PRIORITY       6
#define STM32_EXT_EXTI17_IRQ_PRIORITY       6
#define STM32_EXT_EXTI18_IRQ_PRIORITY       6
#define STM32_EXT_EXTI19_IRQ_PRIORITY       6

/*
 * GPT driver system settings.
 */
#define STM32_GPT_USE_TIM1                  FALSE
#define STM32_GPT_USE_TIM2                  FALSE
#define STM32_GPT_USE_TIM3                  FALSE
#define STM32_GPT_USE_TIM4                  FALSE
#define STM32_GPT_USE_TIM5                  FALSE
#define STM32_GPT_USE_TIM8                  FALSE
#define STM32_GPT_TIM1_IRQ_PRIORITY         7
#define STM32_GPT_TIM2_IRQ_PRIORITY         7
#define STM32_GPT_TIM3_IRQ_PRIORITY         7
#define STM32_GPT_TIM4_IRQ_PRIORITY         7
#define STM32_GPT_TIM5_IRQ_PRIORITY         7
#define STM32_GPT_TIM8_IRQ_PRIORITY         7

/*
 * I2C driver system settings.
 */
#define STM32_I2C_USE_I2C1                  FALSE
#define STM32_I2C_USE_I2C2                  FALSE
#define STM32_I2C_I2C1_IRQ_PRIORITY         5
#define STM32_I2C_I2C2_IRQ_PRIORITY         5
#define STM32_I2C_I2C1_DMA_PRIORITY         3
#define STM32_I2C_I2C2_DMA_PRIORITY         3
#define STM32_I2C_I2C1_DMA_ERROR_HOOK()     chSysHalt()
#define STM32_I2C_I2C2_DMA_ERROR_HOOK()     chSysHalt()

/*
 * ICU driver system settings.
 */
#define STM32_ICU_USE_TIM1                  FALSE
#define STM32_ICU_USE_TIM2                  FALSE
#define STM32_ICU_USE_TIM3                  FALSE
#define STM32_ICU_USE_TIM4                  FALSE
#define STM32_ICU_USE_TIM5                  FALSE
#define STM32_ICU_USE_TIM8                  FALSE
#define STM32_ICU_TIM1_IRQ_PRIORITY         7
#define STM32_ICU_TIM2_IRQ_PRIORITY         7
#define STM32_ICU_TIM3_IRQ_PRIORITY         7
#define STM32_ICU_TIM4_IRQ_PRIORITY         7
#define STM32_ICU_TIM5_IRQ_PRIORITY         7
#define STM32_ICU_TIM8_IRQ_PRIORITY         7

/*
 * PWM driver system settings.
 */
#define STM32_PWM_USE_ADVANCED              FALSE
#define STM32_PWM_USE_TIM1                  FALSE
#define STM32_PWM_USE_TIM2                  FALSE
#define STM32_PWM_USE_TIM3                  FALSE
#define STM32_PWM_USE_TIM4                  FALSE
#define STM32_PWM_USE_TIM5                  FALSE
#define STM32_PWM_USE_TIM8                  FALSE
#define STM32_PWM_TIM1_IRQ_PRIORITY         7
#define STM32_PWM_TIM2_IRQ_PRIORITY         7
#define STM32_PWM_TIM3_IRQ_PRIORITY         7
#define STM32_PWM_TIM4_IRQ_PRIORITY         7
#define STM32_PWM_TIM5_IRQ_PRIORITY         7
#define STM32_PWM_TIM8_IRQ_PRIORITY         7

/*
 * RTC driver system settings.
 */
#define STM32_RTC_IRQ_PRIORITY              15

/*
 * SERIAL driver system settings.
 */
#define STM32_SERIAL_USE_USART1             FALSE
#define STM32_SERIAL_USE_USART2             TRUE
#define STM32_SERIAL_USE_USART3             FALSE
#define STM32_SERIAL_USE_UART4              FALSE
#define STM32_SERIAL_USE_UART5              FALSE
#define STM32_SERIAL_USART1_PRIORITY        12
#define STM32_SERIAL_USART2_PRIORITY        12
#define STM32_SERIAL_USART3_PRIORITY        12
#define STM32_SERIAL_UART4_PRIORITY         12
#define STM32_SERIAL_UART5_PRIORITY         12

/*
 * SPI driver system settings.
 */
#define STM32_SPI_USE_SPI1                  FALSE
#define STM32_SPI_USE_SPI2                  FALSE
#define STM32_SPI_USE_SPI3                  FALSE
#define STM32_SPI_SPI1_DMA_PRIORITY         1
#define STM32_SPI_SPI2_DMA_PRIORITY         1
#define STM32_SPI_SPI3_DMA_PRIORITY         1
#define STM32_SPI_SPI1_IRQ_PRIORITY         10
#define STM32_SPI_SPI2_IRQ_PRIORITY         10
#define STM32_SPI_SPI3_IRQ_PRIORITY         10
#define STM32_SPI_DMA_ERROR_HOOK(spip)      chSysHalt()

/*
 * UART driver system settings.
 */
#define STM32_UART_USE_USART1               FALSE
#define STM32_UART_USE_USART2               FALSE
#define STM32_UART_USE_USART3               FALSE
#define STM32_UART_USART1_IRQ_PRIORITY      12
#define STM32_UART_USART2_IRQ_PRIORITY      12
#define STM32_UART_USART3_IRQ_PRIORITY      12
#define STM32_UART_USART1_DMA_PRIORITY      0
#define STM32_UART_USART2_DMA_PRIORITY      0
#define STM32_UART_USART3_DMA_PRIORITY      0
#define STM32_UART_DMA_ERROR_HOOK(uartp)    chSysHalt()

/*
 * USB driver system settings.
 */
#define STM32_USB_USE_USB1                  FALSE
#define STM32_USB_LOW_POWER_ON_SUSPEND      FALSE
#define STM32_USB_USB1_HP_IRQ_PRIORITY      13
#define STM32_USB_USB1_LP_IRQ_PRIORITY      14