| 1 | /* -*-c-*- |
| 2 | * |
| 3 | * The STROBE protocol framework |
| 4 | * |
| 5 | * (c) 2018 Straylight/Edgeware |
| 6 | */ |
| 7 | |
| 8 | /*----- Licensing notice --------------------------------------------------* |
| 9 | * |
| 10 | * This file is part of Catacomb. |
| 11 | * |
| 12 | * Catacomb is free software: you can redistribute it and/or modify it |
| 13 | * under the terms of the GNU Library General Public License as published |
| 14 | * by the Free Software Foundation; either version 2 of the License, or |
| 15 | * (at your option) any later version. |
| 16 | * |
| 17 | * Catacomb is distributed in the hope that it will be useful, but |
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 20 | * Library General Public License for more details. |
| 21 | * |
| 22 | * You should have received a copy of the GNU Library General Public |
| 23 | * License along with Catacomb. If not, write to the Free Software |
| 24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
| 25 | * USA. |
| 26 | */ |
| 27 | |
| 28 | /*----- Notes on the STROBE framework -------------------------------------* |
| 29 | * |
| 30 | * Mike Hamburg's STROBE framework is an attempt to do pretty much all the |
| 31 | * obvious parts of symmetric cryptography using a single primitive: the |
| 32 | * Keccak-p[1600, 24] sponge function which underlies the SHA3. This works |
| 33 | * excellently on tiny devices, because it's possible to implement |
| 34 | * Keccak-p[1600, 24] with a very small amount of code, and STROBE requires |
| 35 | * minimal additional state beyond the 200-byte Keccak-p[1600, n] state, |
| 36 | * which can be updated more-or-less in place. |
| 37 | * |
| 38 | * STROBE is stateful. The idea is that the two parties' STROBE states |
| 39 | * should evolve in lockstep with each other. This will obviously go wrong |
| 40 | * if messages cross over, or are reordered or duplicated. |
| 41 | * |
| 42 | * The model for a single STROBE-based endpoint consists of the application, |
| 43 | * and a transport for communicating with a peer. All data gets mixed into |
| 44 | * the STROBE state. Some operations mix input data with a keystream |
| 45 | * generated by the sponge function (used in duplexing mode), which can then |
| 46 | * be used to encrypt and authenticate messages. |
| 47 | */ |
| 48 | |
| 49 | #ifndef CATACOMB_STROBE_H |
| 50 | #define CATACOMB_STROBE_H |
| 51 | |
| 52 | #ifdef __cplusplus |
| 53 | extern "C" { |
| 54 | #endif |
| 55 | |
| 56 | /*----- Header files ------------------------------------------------------*/ |
| 57 | |
| 58 | #include <mLib/bits.h> |
| 59 | |
| 60 | #ifndef CATACOMB_KECCAK1600_H |
| 61 | # include "keccak1600.h" |
| 62 | #endif |
| 63 | |
| 64 | /*----- Data structures ---------------------------------------------------*/ |
| 65 | |
| 66 | #define STRBF_I 0x01 /* inbound */ |
| 67 | #define STRBF_A 0x02 /* application */ |
| 68 | #define STRBF_C 0x04 /* cipher */ |
| 69 | #define STRBF_T 0x08 /* transport */ |
| 70 | #define STRBF_M 0x10 /* metadata */ |
| 71 | #define STRBF_K 0x20 /* key-tree (not implemented) */ |
| 72 | #define STRBF_VALIDMASK 0x1f /* valid bits */ |
| 73 | #define STRBF_OPMASK 0xff /* observable operation bits */ |
| 74 | |
| 75 | typedef struct strobe_ctx { |
| 76 | keccak1600_state k; |
| 77 | octet buf[200]; |
| 78 | unsigned f, r, n0, n; |
| 79 | #define STRBF_I0 0x0001 /* initiator/responder role */ |
| 80 | #define STRBF_INIT 0x0100 /* initiator/responder role set? */ |
| 81 | #define STRBF_STMASK 0x01ff /* mask for persistent state bits */ |
| 82 | #define STRBF_ACTIVE 0x0200 /* operation in progress */ |
| 83 | #define STRBF_WANTIN 0x0400 /* expect input buffer */ |
| 84 | #define STRBF_WANTOUT 0x0800 /* expect output buffer */ |
| 85 | #define STRBF_VRFOUT 0x1000 /* verify that output is nonzero */ |
| 86 | #define STRBF_NZERO 0x2000 /* nonzero output from update */ |
| 87 | #define STRBF_MIXOUT 0x4000 /* mix output into state */ |
| 88 | #define STRBF_CRYPTO 0x8000 /* mix sponge state into output */ |
| 89 | } strobe_ctx; |
| 90 | |
| 91 | #define STROBE_KEY (STRBF_A | STRBF_C) |
| 92 | #define STROBE_AD (STRBF_A) |
| 93 | #define STROBE_PRF (STRBF_I | STRBF_A | STRBF_C) |
| 94 | #define STROBE_CLROUT (STRBF_A | STRBF_T) |
| 95 | #define STROBE_CLRIN (STRBF_I | STRBF_A | STRBF_T) |
| 96 | #define STROBE_ENCOUT (STRBF_A | STRBF_C | STRBF_T) |
| 97 | #define STROBE_ENCIN (STRBF_I | STRBF_A | STRBF_C | STRBF_T) |
| 98 | #define STROBE_MACOUT (STRBF_C | STRBF_T) |
| 99 | #define STROBE_MACIN (STRBF_I | STRBF_C | STRBF_T) |
| 100 | #define STROBE_RATCHET (STRBF_C) |
| 101 | |
| 102 | #define STROBE_ROLEMASK (STRBF_I0 | STRBF_INIT) |
| 103 | #define STRBRL_UNDCD (0) /* undecided */ |
| 104 | #define STRBRL_INIT (STRBF_INIT) /* initiator */ |
| 105 | #define STRBRL_RESP (STRBF_I0 | STRBF_INIT) /* responder */ |
| 106 | |
| 107 | /*----- Functions provided ------------------------------------------------*/ |
| 108 | |
| 109 | /* --- @strobe_init@ --- * |
| 110 | * |
| 111 | * Arguments: @strobe_ctx *ctx@ = pointer to context block to initialize |
| 112 | * @unsigned lambda@ = security parameter, in bits (must be a |
| 113 | * multiple of 32) |
| 114 | * |
| 115 | * Returns: --- |
| 116 | * |
| 117 | * Use: Initialize a STROBE context for use. |
| 118 | */ |
| 119 | |
| 120 | extern void strobe_init(strobe_ctx */*ctx*/, unsigned /*lambda*/); |
| 121 | |
| 122 | /* --- @strobe_begin@ --- * |
| 123 | * |
| 124 | * Arguments: @strobe_ctx *ctx@ = pointer to context block |
| 125 | * @unsigned op@ = bitmask of flags |
| 126 | * |
| 127 | * Returns: --- |
| 128 | * |
| 129 | * Use: Begin a STROBE operation. The flags determine the behaviour |
| 130 | * of the @strobe_process@ and @strobe_done@ functions. |
| 131 | * |
| 132 | * * The @I@ bit determines the primary direction of data |
| 133 | * movement. If it's clear, data comes from the application |
| 134 | * into STROBE. If it's set, data comes from STROBE towards |
| 135 | * the application. |
| 136 | * |
| 137 | * * The @C@ bit activates cryptographic processing. If it's |
| 138 | * clear, then the input and output data would be equal, so |
| 139 | * @dest@ must be null. If it's set, then input data is |
| 140 | * XORed with the keystream on its way to the output. |
| 141 | * |
| 142 | * * The @A@ bit determines whether the application is |
| 143 | * engaged. If it's set, then the input or output buffer |
| 144 | * (according to whether @I@ is clear or set, respectively) |
| 145 | * holds the application data. If it's clear, and @I@ is |
| 146 | * clear, then zero bytes are fed in; if @I@ is set, then |
| 147 | * the output is compared with zero, and @strobe_done@ |
| 148 | * reports the outcome of this comparison. |
| 149 | * |
| 150 | * * The @T@ bit determines whether the transport is engaged. |
| 151 | * If it's set, then the input or output buffer (according |
| 152 | * to whether @I@ is set or clear, respectively) holds |
| 153 | * transport data. If it's clear, and @I@ is set, then zero |
| 154 | * bytes are fed in; if @I@ is clear, then the output is |
| 155 | * discarded. |
| 156 | * |
| 157 | * * The @M@ bit marks the data as metadata, but has no other |
| 158 | * effect. |
| 159 | */ |
| 160 | |
| 161 | extern void strobe_begin(strobe_ctx */*ctx*/, unsigned /*op*/); |
| 162 | |
| 163 | /* --- @strobe_process@ --- * |
| 164 | * |
| 165 | * Arguments: @strobe_ctx *ctx@ = pointer to context block |
| 166 | * @const void *src@ = pointer to input data, or null |
| 167 | * @void *dest@ = pointer to output data, or null |
| 168 | * @size_t sz@ = common buffer length |
| 169 | * |
| 170 | * Returns: --- |
| 171 | * |
| 172 | * Use: Process data through the active STROBE operation. The exact |
| 173 | * behaviour depends on the flags passed to @strobe_begin@; see |
| 174 | * that function for details. If @src@ is null, then the |
| 175 | * behaviour is as if the input consists of @sz@ zero bytes. If |
| 176 | * @dest@ in null, then the output is discarded. |
| 177 | */ |
| 178 | |
| 179 | extern void strobe_process(strobe_ctx */*ctx*/, const void */*src*/, |
| 180 | void */*dest*/, size_t /*sz*/); |
| 181 | |
| 182 | /* --- @strobe_done@ --- * |
| 183 | * |
| 184 | * Arguments: @strobe_ctx *ctx@ = pointer to context block |
| 185 | * |
| 186 | * Returns: Zero on success; @-1@ on verification failure (if @I@ and @T@ |
| 187 | * are set and @A@ is clear) |
| 188 | * |
| 189 | * Use: Concludes a STROBE operation, returning the result. |
| 190 | */ |
| 191 | |
| 192 | extern int strobe_done(strobe_ctx */*ctx*/); |
| 193 | |
| 194 | /* --- @strobe_key@, @strobe_ad@, @strobe_@prf@, @strobe_clrout@, |
| 195 | * @strobe_clrin@, @strobe_encout@, @strobe_encin@, @strobe_macout@, |
| 196 | * @strobe_macin@, @strobe_ratchet@ --- * |
| 197 | * |
| 198 | * Arguments: @strobe_ctx *ctx@ = pointer to context block |
| 199 | * |
| 200 | * Returns: @strobe_macin@ returns zero on success, or @-1@ on |
| 201 | * verification failure |
| 202 | * |
| 203 | * Use: Perform a STROBE operation on a single buffer. |
| 204 | */ |
| 205 | |
| 206 | extern void strobe_key(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 207 | const void */*k*/, size_t /*sz*/); |
| 208 | extern void strobe_ad(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 209 | const void */*h*/, size_t /*sz*/); |
| 210 | extern void strobe_prf(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 211 | void */*t*/, size_t /*sz*/); |
| 212 | extern void strobe_clrout(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 213 | const void */*m*/, size_t /*sz*/); |
| 214 | extern void strobe_clrin(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 215 | const void */*m*/, size_t /*sz*/); |
| 216 | extern void strobe_encout(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 217 | const void */*m*/, void */*c*/, size_t /*sz*/); |
| 218 | extern void strobe_encin(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 219 | const void */*c*/, void */*m*/, size_t /*sz*/); |
| 220 | extern void strobe_macout(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 221 | void */*t*/, size_t /*sz*/); |
| 222 | extern int strobe_macin(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 223 | const void */*t*/, size_t /*sz*/); |
| 224 | extern void strobe_ratchet(strobe_ctx */*ctx*/, unsigned /*f*/, |
| 225 | size_t /*sz*/); |
| 226 | |
| 227 | /*----- That's all, folks -------------------------------------------------*/ |
| 228 | |
| 229 | #ifdef __cplusplus |
| 230 | } |
| 231 | #endif |
| 232 | |
| 233 | #endif |