1195972f6Sopenharmony_ci/**
2195972f6Sopenharmony_ci * @file
3195972f6Sopenharmony_ci * Additional SNMPv3 functionality RFC3414 and RFC3826.
4195972f6Sopenharmony_ci */
5195972f6Sopenharmony_ci
6195972f6Sopenharmony_ci/*
7195972f6Sopenharmony_ci * Copyright (c) 2016 Elias Oenal.
8195972f6Sopenharmony_ci * All rights reserved.
9195972f6Sopenharmony_ci *
10195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
11195972f6Sopenharmony_ci * are permitted provided that the following conditions are met:
12195972f6Sopenharmony_ci *
13195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice,
14195972f6Sopenharmony_ci *    this list of conditions and the following disclaimer.
15195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice,
16195972f6Sopenharmony_ci *    this list of conditions and the following disclaimer in the documentation
17195972f6Sopenharmony_ci *    and/or other materials provided with the distribution.
18195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products
19195972f6Sopenharmony_ci *    derived from this software without specific prior written permission.
20195972f6Sopenharmony_ci *
21195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30195972f6Sopenharmony_ci * OF SUCH DAMAGE.
31195972f6Sopenharmony_ci *
32195972f6Sopenharmony_ci * Author: Elias Oenal <lwip@eliasoenal.com>
33195972f6Sopenharmony_ci */
34195972f6Sopenharmony_ci
35195972f6Sopenharmony_ci#include "snmpv3_priv.h"
36195972f6Sopenharmony_ci#include "lwip/apps/snmpv3.h"
37195972f6Sopenharmony_ci#include "lwip/sys.h"
38195972f6Sopenharmony_ci#include <string.h>
39195972f6Sopenharmony_ci
40195972f6Sopenharmony_ci#if LWIP_SNMP && LWIP_SNMP_V3
41195972f6Sopenharmony_ci
42195972f6Sopenharmony_ci#ifdef LWIP_SNMPV3_INCLUDE_ENGINE
43195972f6Sopenharmony_ci#include LWIP_SNMPV3_INCLUDE_ENGINE
44195972f6Sopenharmony_ci#endif
45195972f6Sopenharmony_ci
46195972f6Sopenharmony_ci#define SNMP_MAX_TIME_BOOT 2147483647UL
47195972f6Sopenharmony_ci
48195972f6Sopenharmony_ci/** Call this if engine has been changed. Has to reset boots, see below */
49195972f6Sopenharmony_civoid
50195972f6Sopenharmony_cisnmpv3_engine_id_changed(void)
51195972f6Sopenharmony_ci{
52195972f6Sopenharmony_ci  snmpv3_set_engine_boots(0);
53195972f6Sopenharmony_ci}
54195972f6Sopenharmony_ci
55195972f6Sopenharmony_ci/** According to RFC3414 2.2.2.
56195972f6Sopenharmony_ci *
57195972f6Sopenharmony_ci * The number of times that the SNMP engine has
58195972f6Sopenharmony_ci * (re-)initialized itself since snmpEngineID
59195972f6Sopenharmony_ci * was last configured.
60195972f6Sopenharmony_ci */
61195972f6Sopenharmony_cis32_t
62195972f6Sopenharmony_cisnmpv3_get_engine_boots_internal(void)
63195972f6Sopenharmony_ci{
64195972f6Sopenharmony_ci  if (snmpv3_get_engine_boots() == 0 ||
65195972f6Sopenharmony_ci      snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) {
66195972f6Sopenharmony_ci    return snmpv3_get_engine_boots();
67195972f6Sopenharmony_ci  }
68195972f6Sopenharmony_ci
69195972f6Sopenharmony_ci  snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT);
70195972f6Sopenharmony_ci  return snmpv3_get_engine_boots();
71195972f6Sopenharmony_ci}
72195972f6Sopenharmony_ci
73195972f6Sopenharmony_ci/** RFC3414 2.2.2.
74195972f6Sopenharmony_ci *
75195972f6Sopenharmony_ci * Once the timer reaches 2147483647 it gets reset to zero and the
76195972f6Sopenharmony_ci * engine boot ups get incremented.
77195972f6Sopenharmony_ci */
78195972f6Sopenharmony_cis32_t
79195972f6Sopenharmony_cisnmpv3_get_engine_time_internal(void)
80195972f6Sopenharmony_ci{
81195972f6Sopenharmony_ci  if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) {
82195972f6Sopenharmony_ci    snmpv3_reset_engine_time();
83195972f6Sopenharmony_ci
84195972f6Sopenharmony_ci    if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) {
85195972f6Sopenharmony_ci      snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1);
86195972f6Sopenharmony_ci    } else {
87195972f6Sopenharmony_ci      snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT);
88195972f6Sopenharmony_ci    }
89195972f6Sopenharmony_ci  }
90195972f6Sopenharmony_ci
91195972f6Sopenharmony_ci  return snmpv3_get_engine_time();
92195972f6Sopenharmony_ci}
93195972f6Sopenharmony_ci
94195972f6Sopenharmony_ci#if LWIP_SNMP_V3_CRYPTO
95195972f6Sopenharmony_ci
96195972f6Sopenharmony_ci/* This function ignores the byte order suggestion in RFC3414
97195972f6Sopenharmony_ci * since it simply doesn't influence the effectiveness of an IV.
98195972f6Sopenharmony_ci *
99195972f6Sopenharmony_ci * Implementing RFC3826 priv param algorithm if LWIP_RAND is available.
100195972f6Sopenharmony_ci *
101195972f6Sopenharmony_ci * @todo: This is a potential thread safety issue.
102195972f6Sopenharmony_ci */
103195972f6Sopenharmony_cierr_t
104195972f6Sopenharmony_cisnmpv3_build_priv_param(u8_t *priv_param)
105195972f6Sopenharmony_ci{
106195972f6Sopenharmony_ci#ifdef LWIP_RAND /* Based on RFC3826 */
107195972f6Sopenharmony_ci  static u8_t init;
108195972f6Sopenharmony_ci  static u32_t priv1, priv2;
109195972f6Sopenharmony_ci
110195972f6Sopenharmony_ci  /* Lazy initialisation */
111195972f6Sopenharmony_ci  if (init == 0) {
112195972f6Sopenharmony_ci    init = 1;
113195972f6Sopenharmony_ci    priv1 = LWIP_RAND();
114195972f6Sopenharmony_ci    priv2 = LWIP_RAND();
115195972f6Sopenharmony_ci  }
116195972f6Sopenharmony_ci
117195972f6Sopenharmony_ci  SMEMCPY(&priv_param[0], &priv1, sizeof(priv1));
118195972f6Sopenharmony_ci  SMEMCPY(&priv_param[4], &priv2, sizeof(priv2));
119195972f6Sopenharmony_ci
120195972f6Sopenharmony_ci  /* Emulate 64bit increment */
121195972f6Sopenharmony_ci  priv1++;
122195972f6Sopenharmony_ci  if (!priv1) { /* Overflow */
123195972f6Sopenharmony_ci    priv2++;
124195972f6Sopenharmony_ci  }
125195972f6Sopenharmony_ci#else /* Based on RFC3414 */
126195972f6Sopenharmony_ci  static u32_t ctr;
127195972f6Sopenharmony_ci  u32_t boots = snmpv3_get_engine_boots_internal();
128195972f6Sopenharmony_ci  SMEMCPY(&priv_param[0], &boots, 4);
129195972f6Sopenharmony_ci  SMEMCPY(&priv_param[4], &ctr, 4);
130195972f6Sopenharmony_ci  ctr++;
131195972f6Sopenharmony_ci#endif
132195972f6Sopenharmony_ci  return ERR_OK;
133195972f6Sopenharmony_ci}
134195972f6Sopenharmony_ci#endif /* LWIP_SNMP_V3_CRYPTO */
135195972f6Sopenharmony_ci
136195972f6Sopenharmony_ci#endif
137