developer | 02e6591 | 2023-08-17 16:33:10 +0800 | [diff] [blame^] | 1 | /* sa_builder_macsec.c |
| 2 | * |
| 3 | * MACsec specific functions (for initialization of SABuilder_Params_t |
| 4 | * structures and for building the MACsec specifc part of an SA.). |
| 5 | */ |
| 6 | |
| 7 | /***************************************************************************** |
| 8 | * Copyright (c) 2013-2020 by Rambus, Inc. and/or its subsidiaries. |
| 9 | * |
| 10 | * This program is free software: you can redistribute it and/or modify |
| 11 | * it under the terms of the GNU General Public License as published by |
| 12 | * the Free Software Foundation, either version 2 of the License, or |
| 13 | * any later version. |
| 14 | * |
| 15 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU General Public License for more details. |
| 19 | * |
| 20 | * You should have received a copy of the GNU General Public License |
| 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 22 | *****************************************************************************/ |
| 23 | |
| 24 | /*---------------------------------------------------------------------------- |
| 25 | * This module implements (provides) the following interface(s): |
| 26 | */ |
| 27 | #include "sa_builder_macsec.h" |
| 28 | #include "sa_builder_internal.h" /* SABuilder_SetMACsecParams */ |
| 29 | |
| 30 | /*---------------------------------------------------------------------------- |
| 31 | * This module uses (requires) the following interface(s): |
| 32 | */ |
| 33 | #include "c_sa_builder.h" |
| 34 | #include "basic_defs.h" |
| 35 | #include "log.h" |
| 36 | |
| 37 | #ifdef SAB_ENABLE_PROTO_MACSEC |
| 38 | |
| 39 | /*---------------------------------------------------------------------------- |
| 40 | * Definitions and macros |
| 41 | */ |
| 42 | |
| 43 | |
| 44 | /*---------------------------------------------------------------------------- |
| 45 | * Local variables |
| 46 | */ |
| 47 | |
| 48 | /*---------------------------------------------------------------------------- |
| 49 | * SABuilder_Init_MACsec |
| 50 | * |
| 51 | * This function initializes the SABuilder_Params_t data structure and its |
| 52 | * SABuilder_Params_MACsec_t extension with sensible defaults for MACsec |
| 53 | * processing. |
| 54 | * |
| 55 | * SAParams_p (output) |
| 56 | * Pointer to SA parameter structure to be filled in. |
| 57 | * SAParamsMACsec_p (output) |
| 58 | * Pointer to MACsec parameter extension to be filled in |
| 59 | * SCI_p (input) |
| 60 | * Pointer to Secure Channel Identifier, 8 bytes. |
| 61 | * AN (input) |
| 62 | * Association number, a number for 0 to 3. |
| 63 | * direction (input) |
| 64 | * Must be one of SAB_DIRECTION_INBOUND or SAB_DIRECTION_OUTBOUND. |
| 65 | * |
| 66 | * Both the crypto and the authentication algorithm are initialized to |
| 67 | * NULL. The crypto algorithm (which may remain NULL) must be set to |
| 68 | * one of the algorithms supported by the protocol. The authentication |
| 69 | * algorithm must also be set to one of the algorithms supported by |
| 70 | * the protocol..Any required keys have to be specified as well. |
| 71 | * |
| 72 | * Both the SAParams_p and SAParamsMACsec_p input parameters must point |
| 73 | * to valid storage where variables of the appropriate type can be |
| 74 | * stored. This function initializes the link from SAParams_p to |
| 75 | * SAParamsMACsec_p. |
| 76 | * |
| 77 | * Return: |
| 78 | * SAB_STATUS_OK on success |
| 79 | * SAB_INVALID_PARAMETER when one of the pointer parameters is NULL |
| 80 | * or the remaining parameters have illegal values. |
| 81 | */ |
| 82 | SABuilder_Status_t |
| 83 | SABuilder_Init_MACsec( |
| 84 | SABuilder_Params_t * const SAParams_p, |
| 85 | SABuilder_Params_MACsec_t * const SAParamsMACsec_p, |
| 86 | const uint8_t *SCI_p, |
| 87 | const uint8_t AN, |
| 88 | const SABuilder_Direction_t direction) |
| 89 | { |
| 90 | #ifdef SAB_STRICT_ARGS_CHECK |
| 91 | if (SAParams_p == NULL || SAParamsMACsec_p == NULL || SCI_p == NULL) |
| 92 | { |
| 93 | LOG_CRIT("SABuilder_Init_MACsec: NULL pointer parameter supplied.\n"); |
| 94 | return SAB_INVALID_PARAMETER; |
| 95 | } |
| 96 | |
| 97 | if (AN > 3) |
| 98 | { |
| 99 | LOG_CRIT("SABuilder_Init_MACsec: Invalid Association Number.\n"); |
| 100 | return SAB_INVALID_PARAMETER; |
| 101 | } |
| 102 | |
| 103 | if (direction != SAB_DIRECTION_OUTBOUND && |
| 104 | direction != SAB_DIRECTION_INBOUND) |
| 105 | { |
| 106 | LOG_CRIT("SABuilder_Init_ESP: Invalid direction.\n"); |
| 107 | return SAB_INVALID_PARAMETER; |
| 108 | } |
| 109 | #endif |
| 110 | |
| 111 | SAParams_p->protocol = SAB_PROTO_MACSEC; |
| 112 | SAParams_p->direction = direction; |
| 113 | SAParams_p->ProtocolExtension_p = (void*)SAParamsMACsec_p; |
| 114 | SAParams_p->flags = 0; |
| 115 | SAParams_p->RedirectInterface = 0; |
| 116 | |
| 117 | SAParams_p->CryptoAlgo = SAB_CRYPTO_NULL; |
| 118 | SAParams_p->CryptoMode = SAB_CRYPTO_MODE_CBC; |
| 119 | SAParams_p->IVSrc = SAB_IV_SRC_DEFAULT; |
| 120 | SAParams_p->CryptoParameter = 0; |
| 121 | SAParams_p->KeyByteCount = 0; |
| 122 | SAParams_p->Key_p = NULL; |
| 123 | SAParams_p->IV_p = NULL; |
| 124 | SAParams_p->Nonce_p = NULL; |
| 125 | |
| 126 | SAParams_p->AuthAlgo = SAB_AUTH_NULL; |
| 127 | SAParams_p->AuthKey1_p = NULL; |
| 128 | SAParams_p->AuthKey2_p = NULL; |
| 129 | SAParams_p->AuthKey3_p = NULL; |
| 130 | SAParams_p->AuthKeyByteCount = 0; |
| 131 | |
| 132 | SAParams_p->OffsetARC4StateRecord = 0; |
| 133 | SAParams_p->CW0 = 0; |
| 134 | SAParams_p->CW1 = 0; |
| 135 | SAParams_p->OffsetDigest0 = 0; |
| 136 | SAParams_p->OffsetDigest1 = 0; |
| 137 | SAParams_p->OffsetSeqNum = 0; |
| 138 | SAParams_p->OffsetSeqMask = 0; |
| 139 | SAParams_p->OffsetIV = 0; |
| 140 | SAParams_p->OffsetIJPtr = 0; |
| 141 | SAParams_p->OffsetARC4State = 0; |
| 142 | SAParams_p->SeqNumWord32Count = 0; |
| 143 | SAParams_p->SeqMaskWord32Count = 0; |
| 144 | SAParams_p->IVWord32Count = 0; |
| 145 | |
| 146 | SAParamsMACsec_p->MACsecFlags = 0; |
| 147 | SAParamsMACsec_p->SCI_p = SCI_p; |
| 148 | SAParamsMACsec_p->AN = AN; |
| 149 | SAParamsMACsec_p->SeqNum = 0; |
| 150 | SAParamsMACsec_p->ReplayWindow = 0; |
| 151 | SAParamsMACsec_p->ConfOffset = 0; |
| 152 | SAParamsMACsec_p->ContextRef = 0; |
| 153 | |
| 154 | return SAB_STATUS_OK; |
| 155 | } |
| 156 | |
| 157 | /*---------------------------------------------------------------------------- |
| 158 | * SABuilder_SetMACsecParams |
| 159 | * |
| 160 | * Fill in MACsec-specific extensions into the SA. |
| 161 | * |
| 162 | * SAParams_p (input) |
| 163 | * The SA parameters structure from which the SA is derived. |
| 164 | * SAState_p (input, output) |
| 165 | * Variables containing information about the SA being generated/ |
| 166 | * SABuffer_p (input, output). |
| 167 | * The buffer in which the SA is built. If NULL, no SA will be built, but |
| 168 | * state variables in SAState_p will still be updated. |
| 169 | * |
| 170 | * Return: |
| 171 | * SAB_STATUS_OK on success |
| 172 | * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of |
| 173 | * the buffer arguments is a null pointer while the corresponding buffer |
| 174 | * would be required for the operation. |
| 175 | * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that |
| 176 | * is not supported on the hardware for which this SA builder |
| 177 | * is configured. |
| 178 | */ |
| 179 | SABuilder_Status_t |
| 180 | SABuilder_SetMACsecParams(SABuilder_Params_t *const SAParams_p, |
| 181 | SABuilder_State_t * const SAState_p, |
| 182 | uint32_t * const SABuffer_p) |
| 183 | { |
| 184 | SABuilder_Params_MACsec_t *SAParamsMACsec_p; |
| 185 | SAParamsMACsec_p = (SABuilder_Params_MACsec_t *) |
| 186 | (SAParams_p->ProtocolExtension_p); |
| 187 | if (SAParamsMACsec_p == NULL) |
| 188 | { |
| 189 | LOG_CRIT("SABuilder: MACsec extension pointer is null\n"); |
| 190 | return SAB_INVALID_PARAMETER; |
| 191 | } |
| 192 | |
| 193 | /* Allow only AES-GMAC and AES-GCM */ |
| 194 | if (SAParams_p->AuthAlgo != SAB_AUTH_AES_GCM && |
| 195 | SAParams_p->AuthAlgo != SAB_AUTH_AES_GMAC) |
| 196 | { |
| 197 | LOG_CRIT("SABuilder: Only AES-GCM and GMAC allowed wtih MACsec\n"); |
| 198 | return SAB_INVALID_PARAMETER; |
| 199 | } |
| 200 | |
| 201 | if ( (SAParamsMACsec_p->MACsecFlags & SAB_MACSEC_ES) != 0 && |
| 202 | (SAParamsMACsec_p->MACsecFlags & SAB_MACSEC_SC) != 0) |
| 203 | { |
| 204 | LOG_CRIT("SABuilder: MACSEC if ES is set, then SC must be zero,\n"); |
| 205 | return SAB_INVALID_PARAMETER; |
| 206 | } |
| 207 | |
| 208 | /* Add sequence number */ |
| 209 | SAState_p->CW0 |= SAB_CW0_SEQNUM_32; |
| 210 | SAParams_p->OffsetSeqNum = SAState_p->CurrentOffset; |
| 211 | SAParams_p->SeqNumWord32Count = 1; |
| 212 | SAState_p->CW1 |= SAB_CW1_SEQNUM_STORE; |
| 213 | |
| 214 | if (SABuffer_p != NULL) |
| 215 | SABuffer_p[SAState_p->CurrentOffset] = SAParamsMACsec_p->SeqNum; |
| 216 | SAState_p->CurrentOffset += 1; |
| 217 | |
| 218 | if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND) |
| 219 | { |
| 220 | if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM) |
| 221 | SAState_p->CW0 |= SAB_CW0_TOP_ENCRYPT_HASH; |
| 222 | else |
| 223 | SAState_p->CW0 |= SAB_CW0_TOP_HASH_ENCRYPT; |
| 224 | /* Some versions of the hardware can update the sequence number |
| 225 | early, so multiple engines can operate in parallel. */ |
| 226 | SAState_p->CW1 |= SAB_CW1_EARLY_SEQNUM_UPDATE; |
| 227 | SAState_p->CW1 |= SAParams_p->OffsetSeqNum << 24; |
| 228 | } |
| 229 | else |
| 230 | { |
| 231 | SAState_p->CW0 |= SAB_CW0_TOP_HASH_DECRYPT; |
| 232 | |
| 233 | /* Add 'sequence number mask' parameter, which is the replay |
| 234 | window size */ |
| 235 | SAParams_p->OffsetSeqMask = SAState_p->CurrentOffset; |
| 236 | if(SABuffer_p != NULL) |
| 237 | { |
| 238 | SABuffer_p[SAState_p->CurrentOffset] = |
| 239 | SAParamsMACsec_p->ReplayWindow; |
| 240 | SABuffer_p[SAState_p->CurrentOffset+1] = 0; // Add dummy mask word. |
| 241 | } |
| 242 | SAParams_p->SeqMaskWord32Count = 1; |
| 243 | SAState_p->CurrentOffset += 2; |
| 244 | SAState_p->CW0 |= SAB_CW0_MASK_32; |
| 245 | SAState_p->CW1 |= SAB_CW1_MACSEC_SEQCHECK|SAB_CW1_NO_MASK_UPDATE; |
| 246 | } |
| 247 | |
| 248 | /* Add SCI (IV0 and IV1) */ |
| 249 | SAState_p->CW1 |= SAB_CW1_IV_CTR | SAB_CW1_IV0 | SAB_CW1_IV1 | SAB_CW1_IV2; |
| 250 | #ifdef SAB_STRICT_ARGS_CHECK |
| 251 | if (SAParamsMACsec_p->SCI_p == NULL) |
| 252 | { |
| 253 | LOG_CRIT("SABuilder: NULL pointer SCI.\n"); |
| 254 | return SAB_INVALID_PARAMETER; |
| 255 | } |
| 256 | #endif |
| 257 | SAParams_p->OffsetIV = SAState_p->CurrentOffset; |
| 258 | SAParams_p->IVWord32Count = 2; |
| 259 | |
| 260 | SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset, |
| 261 | SAParamsMACsec_p->SCI_p, 8); |
| 262 | SAState_p->CurrentOffset += 2; |
| 263 | |
| 264 | /* Add sequence number once more (IV2) */ |
| 265 | if (SABuffer_p != NULL) |
| 266 | SABuffer_p[SAState_p->CurrentOffset] = SAParamsMACsec_p->SeqNum; |
| 267 | SAState_p->CurrentOffset += 1; |
| 268 | |
| 269 | return SAB_STATUS_OK; |
| 270 | } |
| 271 | |
| 272 | |
| 273 | #endif /* SAB_ENABLE_PROTO_MACSEC */ |
| 274 | |
| 275 | /* end of file sa_builder_macsec.c */ |