summaryrefslogtreecommitdiffstats
path: root/src/vppinfra/pcg.h
diff options
context:
space:
mode:
authorBenoît Ganne <bganne@cisco.com>2022-01-18 15:56:41 +0100
committerBeno�t Ganne <bganne@cisco.com>2023-03-23 08:59:31 +0000
commit5527a78ed96043d2c26e3271066c50b44dd7fc0b (patch)
tree3e4186cb439e10051d013cc71c1f7d8d81ad9613 /src/vppinfra/pcg.h
parentad95b06181c354291f4433c5e550cb89c5122252 (diff)
ipsec: make pre-shared keys harder to misuse
Using pre-shared keys is usually a bad idea, one should use eg. IKEv2 instead, but one does not always have the choice. For AES-CBC, the IV must be unpredictable (see NIST SP800-38a Appendix C) whereas for AES-CTR or AES-GCM, the IV should never be reused with the same key material (see NIST SP800-38a Appendix B and NIST SP800-38d section 8). If one uses pre-shared keys and VPP is restarted, the IV counter restarts at 0 and the same IVs are generated with the same pre-shared keys materials. To fix those issues we follow the recommendation from NIST SP800-38a and NIST SP800-38d: - we use a PRNG (not cryptographically secured) to generate IVs to avoid generating the same IV sequence between VPP restarts. The PRNG is chosen so that there is a low chance of generating the same sequence - for AES-CBC, the generated IV is encrypted as part of the message. This makes the (predictable) PRNG-generated IV unpredictable as it is encrypted with the secret key - for AES-CTR and GCM, we use the IV as-is as predictable IVs are fine Most of the changes in this patch are caused by the need to shoehorn an additional state of 2 u64 for the PRNG in the 1st cacheline of the SA object. Type: improvement Change-Id: I2af89c21ae4b2c4c33dd21aeffcfb79c13c9d84c Signed-off-by: Benoît Ganne <bganne@cisco.com>
Diffstat (limited to 'src/vppinfra/pcg.h')
-rw-r--r--src/vppinfra/pcg.h85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/vppinfra/pcg.h b/src/vppinfra/pcg.h
new file mode 100644
index 00000000000..a7cc9201b8f
--- /dev/null
+++ b/src/vppinfra/pcg.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014-2019 Melissa O'Neill <oneill@pcg-random.org>,
+ * and the PCG Project contributors.
+ *
+ * SPDX-License-Identifier: (Apache-2.0 OR MIT)
+ *
+ * Licensed under the Apache License, Version 2.0 (provided in
+ * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0)
+ * or under the MIT license (provided in LICENSE-MIT.txt and at
+ * http://opensource.org/licenses/MIT), at your option. This file may not
+ * be copied, modified, or distributed except according to those terms.
+ *
+ * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See your chosen license for details.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * visit http://www.pcg-random.org/.
+ */
+
+/* This implements the pcg64i_random_t PCG specialized generator:
+ * https://www.pcg-random.org/using-pcg-c.html#specialized-generators
+ * This generator produces each 64-bits output exactly once, which is
+ * perfectly suited to generated non-repeating IVs. However, because of this
+ * property the entire internal state is revealed with each output.
+ * It has a 2^64 period and supports 2^63 non-overlaping streams */
+
+#define clib_pcg64i_random_r clib_pcg_setseq_64_rxs_m_xs_64_random_r
+#define clib_pcg64i_srandom_r clib_pcg_setseq_64_srandom_r
+
+typedef struct
+{
+ u64 state;
+ u64 inc;
+} clib_pcg_state_setseq_64_t;
+
+typedef clib_pcg_state_setseq_64_t clib_pcg64i_random_t;
+
+static_always_inline void
+clib_pcg_setseq_64_step_r (clib_pcg_state_setseq_64_t *rng)
+{
+ rng->state = rng->state * 6364136223846793005ULL + rng->inc;
+}
+
+static_always_inline u64
+clib_pcg_output_rxs_m_xs_64_64 (u64 state)
+{
+ u64 word =
+ ((state >> ((state >> 59u) + 5u)) ^ state) * 12605985483714917081ull;
+ return (word >> 43u) ^ word;
+}
+
+static_always_inline u64
+clib_pcg_setseq_64_rxs_m_xs_64_random_r (clib_pcg_state_setseq_64_t *rng)
+{
+ u64 oldstate = rng->state;
+ clib_pcg_setseq_64_step_r (rng);
+ return clib_pcg_output_rxs_m_xs_64_64 (oldstate);
+}
+
+static_always_inline void
+clib_pcg_setseq_64_srandom_r (clib_pcg_state_setseq_64_t *rng, u64 initstate,
+ u64 initseq)
+{
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ clib_pcg_setseq_64_step_r (rng);
+ rng->state += initstate;
+ clib_pcg_setseq_64_step_r (rng);
+}