Noise-C
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
symmetricstate.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "internal.h"
24 #include <string.h>
25 
58 static int noise_symmetricstate_new
59  (NoiseSymmetricState **state, const char *name, const NoiseProtocolId *id)
60 {
61  NoiseSymmetricState *new_state;
62  size_t name_len;
63  size_t hash_len;
64  int err;
65 
66  /* Construct a state object and initialize it */
67  new_state = noise_new(NoiseSymmetricState);
68  if (!new_state)
69  return NOISE_ERROR_NO_MEMORY;
70  new_state->id = *id;
71  err = noise_cipherstate_new_by_id(&(new_state->cipher), id->cipher_id);
72  if (err != NOISE_ERROR_NONE) {
73  noise_symmetricstate_free(new_state);
74  return err;
75  }
76  err = noise_hashstate_new_by_id(&(new_state->hash), id->hash_id);
77  if (err != NOISE_ERROR_NONE) {
78  noise_symmetricstate_free(new_state);
79  return err;
80  }
81 
82  /* Check the hash length against the maximum, just in case someone
83  adds a new hash algorithm in the future with longer output.
84  If this happens, modify NOISE_MAX_HASHLEN in internal.h accordingly */
85  hash_len = noise_hashstate_get_hash_length(new_state->hash);
86  if (hash_len > NOISE_MAX_HASHLEN) {
87  noise_symmetricstate_free(new_state);
89  }
90 
91  /* The key length must also be less than or equal to the hash length */
92  if (noise_cipherstate_get_key_length(new_state->cipher) > hash_len) {
93  noise_symmetricstate_free(new_state);
95  }
96 
97  /* Initialize the chaining key "ck" and the handshake hash "h" from
98  the protocol name. If the name is too long, hash it down first */
99  name_len = strlen(name);
100  if (name_len <= hash_len) {
101  memcpy(new_state->h, name, name_len);
102  memset(new_state->h + name_len, 0, hash_len - name_len);
103  } else {
105  (new_state->hash, (const uint8_t *)name, name_len,
106  new_state->h, hash_len);
107  }
108  memcpy(new_state->ck, new_state->h, hash_len);
109 
110  /* Ready to go */
111  *state = new_state;
112  return NOISE_ERROR_NONE;
113 }
114 
136 {
137  char name[NOISE_MAX_PROTOCOL_NAME];
138  int err;
139 
140  /* Validate the parameters */
141  if (!state)
143  *state = 0;
144  if (!id)
146 
147  /* Format the full protocol name from the identifiers. We need the
148  full name because the handshake hash is initialized from the name */
149  err = noise_protocol_id_to_name(name, sizeof(name), id);
150  if (err != NOISE_ERROR_NONE)
151  return err;
152 
153  /* Create the SymmetricState object */
154  return noise_symmetricstate_new(state, name, id);
155 }
156 
176  (NoiseSymmetricState **state, const char *name)
177 {
178  NoiseProtocolId id;
179  size_t name_len;
180  int err;
181 
182  /* Validate the parameters */
183  if (!state)
185  *state = 0;
186  if (!name)
188 
189  /* Parse the protocol identifier and validate the names */
190  name_len = strlen(name);
191  err = noise_protocol_name_to_id(&id, name, name_len);
192  if (err != NOISE_ERROR_NONE)
193  return err;
194 
195  /* Create the SymmetricState object */
196  return noise_symmetricstate_new(state, name, &id);
197 }
198 
210 {
211  /* Bail out if no symmetric state */
212  if (!state)
214 
215  /* Free the sub objects that are hanging off the symmetricstate */
216  if (state->cipher)
218  if (state->hash)
219  noise_hashstate_free(state->hash);
220 
221  /* Clean and free the memory for "state" */
222  noise_free(state, state->size);
223  return NOISE_ERROR_NONE;
224 }
225 
239 {
240  /* Validate the parameters */
241  if (!state || !id)
243 
244  /* Copy the internal id block to the parameter */
245  *id = state->id;
246  return NOISE_ERROR_NONE;
247 }
248 
263  (NoiseSymmetricState *state, const uint8_t *input, size_t size)
264 {
265  uint8_t temp_k[NOISE_MAX_HASHLEN];
266  size_t hash_len;
267  size_t key_len;
268 
269  /* Validate the parameters */
270  if (!state || !input)
272 
273  /* If the state has been split, then we cannot do this */
274  if (!state->cipher)
276 
277  /* Mix the input data in using HKDF */
278  hash_len = noise_hashstate_get_hash_length(state->hash);
279  key_len = noise_cipherstate_get_key_length(state->cipher);
281  (state->hash, state->ck, hash_len, input, size,
282  state->ck, hash_len, temp_k, key_len);
283 
284  /* Change the cipher key, or set it for the first time */
285  noise_cipherstate_init_key(state->cipher, temp_k, key_len);
286  noise_clean(temp_k, sizeof(temp_k));
287  return NOISE_ERROR_NONE;
288 }
289 
304  (NoiseSymmetricState *state, const uint8_t *input, size_t size)
305 {
306  size_t hash_len;
307 
308  /* Validate the parameters */
309  if (!state || !input)
311 
312  /* If the state has been split, then we cannot do this */
313  if (!state->cipher)
315 
316  /* Mix the input data into "h" */
317  hash_len = noise_hashstate_get_hash_length(state->hash);
319  (state->hash, state->h, hash_len, input, size, state->h, hash_len);
320  return NOISE_ERROR_NONE;
321 }
322 
354 {
355  size_t hash_len;
356  int err;
357 
358  /* Validate the parameters */
359  if (!state || !buffer || !(buffer->data))
361 
362  /* If the state has been split, then we cannot do this */
363  if (!state->cipher)
365 
366  /* Encrypt the plaintext using the underlying cipher */
367  hash_len = noise_hashstate_get_hash_length(state->hash);
369  (state->cipher, state->h, hash_len, buffer);
370  if (err != NOISE_ERROR_NONE)
371  return err;
372 
373  /* Feed the ciphertext into the handshake hash */
374  noise_symmetricstate_mix_hash(state, buffer->data, buffer->size);
375  return NOISE_ERROR_NONE;
376 }
377 
404 {
405  uint8_t temp[NOISE_MAX_HASHLEN];
406  size_t hash_len;
407  int err;
408 
409  /* Validate the parameters */
410  if (!state || !buffer || !(buffer->data))
412 
413  /* If the state has been split, then we cannot do this */
414  if (!state->cipher)
416 
417  /* Validate the input data length before we hash the data */
418  if (buffer->size > NOISE_MAX_PAYLOAD_LEN)
420  if (noise_cipherstate_has_key(state->cipher)) {
421  if (buffer->size < noise_cipherstate_get_mac_length(state->cipher))
423  }
424 
425  /* Feed the ciphertext into the handshake hash first. We make a
426  temporary copy of the hash. If the decryption fails below,
427  then we don't update the handshake hash with the bogus data */
428  hash_len = noise_hashstate_get_hash_length(state->hash);
430  (state->hash, state->h, hash_len,
431  buffer->data, buffer->size, temp, hash_len);
432 
433  /* Decrypt the ciphertext using the underlying cipher */
435  (state->cipher, state->h, hash_len, buffer);
436  if (err != NOISE_ERROR_NONE) {
437  noise_clean(temp, sizeof(temp));
438  return err;
439  }
440 
441  /* Update the handshake hash */
442  memcpy(state->h, temp, hash_len);
443  noise_clean(temp, sizeof(temp));
444  return NOISE_ERROR_NONE;
445 }
446 
465 {
466  /* Validate the parameter */
467  if (!state)
468  return 0;
469 
470  /* If the state has been split or the key has not been set, then zero */
471  if (!state->cipher)
472  return 0;
473  if (!noise_cipherstate_has_key(state->cipher))
474  return 0;
475 
476  /* Return the MAC length for the cipher */
478 }
479 
516 {
517  uint8_t temp_k1[NOISE_MAX_HASHLEN];
518  uint8_t temp_k2[NOISE_MAX_HASHLEN];
519  size_t hash_len;
520  size_t key_len;
521 
522  /* Validate the parameters */
523  if (!state)
525  if (!c1 && !c2)
527  if (c1)
528  *c1 = 0;
529  if (c2)
530  *c2 = 0;
531 
532  /* If the state has already been split, then we cannot split again */
533  if (!state->cipher)
535 
536  /* Generate the two encryption keys with HKDF */
537  hash_len = noise_hashstate_get_hash_length(state->hash);
538  key_len = noise_cipherstate_get_key_length(state->cipher);
540  (state->hash, state->ck, hash_len, state->ck, 0,
541  temp_k1, key_len, temp_k2, key_len);
542 
543  /* If we only need c2, then re-initialize the key in the internal
544  cipher and copy it to c2 */
545  if (!c1 && c2) {
546  noise_cipherstate_init_key(state->cipher, temp_k2, key_len);
547  *c2 = state->cipher;
548  state->cipher = 0;
549  noise_clean(temp_k1, sizeof(temp_k1));
550  noise_clean(temp_k2, sizeof(temp_k2));
551  return NOISE_ERROR_NONE;
552  }
553 
554  /* Split a copy out of the cipher and give it the second key.
555  We don't need to do this if the second CipherSuite is not required */
556  if (c2) {
557  *c2 = (*(state->cipher->create))();
558  if (!(*c2)) {
559  noise_clean(temp_k1, sizeof(temp_k1));
560  noise_clean(temp_k2, sizeof(temp_k2));
561  return NOISE_ERROR_NO_MEMORY;
562  }
563  noise_cipherstate_init_key(*c2, temp_k2, key_len);
564  }
565 
566  /* Re-initialize the key in the internal cipher and copy it to c1 */
567  noise_cipherstate_init_key(state->cipher, temp_k1, key_len);
568  *c1 = state->cipher;
569  state->cipher = 0;
570  noise_clean(temp_k1, sizeof(temp_k1));
571  noise_clean(temp_k2, sizeof(temp_k2));
572  return NOISE_ERROR_NONE;
573 }
574 
Noise protocol name broken out into separate identifier fields.
Definition: names.h:33
#define NOISE_MAX_PAYLOAD_LEN
Maximum payload length for Noise packets.
int cipher_id
Definition: names.h:38
int noise_cipherstate_init_key(NoiseCipherState *state, const uint8_t *key, size_t key_len)
Initializes the key on a CipherState object.
Definition: cipherstate.c:222
void noise_clean(void *data, size_t size)
Cleans a block of memory to destroy its contents.
Definition: util.c:170
#define NOISE_ERROR_INVALID_STATE
Operation cannot be performed in the current state.
uint8_t ck[NOISE_MAX_HASHLEN]
Current value of the chaining key for the handshake.
Definition: internal.h:522
NoiseHashState * hash
Points to the HashState object for this SymmetricState.
Definition: internal.h:519
#define NOISE_ERROR_INVALID_PARAM
Invalid parameter to function; e.g. a NULL value.
NoiseProtocolId id
Algorithm identifiers for the components of the protocol.
Definition: internal.h:506
#define NOISE_ERROR_NONE
Success, no error.
size_t size
Total size of the structure.
Definition: internal.h:503
int noise_cipherstate_decrypt_with_ad(NoiseCipherState *state, const uint8_t *ad, size_t ad_len, NoiseBuffer *buffer)
Decrypts a block of data with this CipherState object.
Definition: cipherstate.c:374
int noise_protocol_name_to_id(NoiseProtocolId *id, const char *name, size_t name_len)
Parses a protocol name into a set of identifiers for the algorithms that are indicated by the name...
Definition: names.c:332
int noise_cipherstate_free(NoiseCipherState *state)
Frees a CipherState object after destroying all sensitive material.
Definition: cipherstate.c:152
uint8_t * data
Definition: buffer.h:35
int noise_symmetricstate_mix_key(NoiseSymmetricState *state, const uint8_t *input, size_t size)
Mixes new input data into the chaining key.
uint8_t h[NOISE_MAX_HASHLEN]
Current value of the handshake hash.
Definition: internal.h:525
int noise_cipherstate_encrypt_with_ad(NoiseCipherState *state, const uint8_t *ad, size_t ad_len, NoiseBuffer *buffer)
Encrypts a block of data with this CipherState object.
Definition: cipherstate.c:294
int noise_symmetricstate_get_protocol_id(const NoiseSymmetricState *state, NoiseProtocolId *id)
Gets the protocol identifier associated with a SymmetricState object.
int noise_hashstate_new_by_id(NoiseHashState **state, int id)
Creates a new HashState object by its algorithm identifier.
Definition: hashstate.c:73
#define NOISE_MAX_HASHLEN
Maximum hash length over all supported hash algorithms.
Definition: internal.h:48
int noise_hashstate_hash_one(NoiseHashState *state, const uint8_t *data, size_t data_len, uint8_t *hash, size_t hash_len)
Hashes a single data buffer and returns the hash value.
Definition: hashstate.c:309
size_t noise_cipherstate_get_mac_length(const NoiseCipherState *state)
Gets the length of packet MAC values for a CipherState object.
Definition: cipherstate.c:202
#define NOISE_ERROR_NO_MEMORY
Insufficient memory to complete the operation.
NoiseCipherState *(* create)(void)
Creates a new CipherState of the same type as this one.
Definition: internal.h:84
#define NOISE_MAX_PROTOCOL_NAME
Maximum length of a protocol name string.
int hash_id
Definition: names.h:39
#define NOISE_ERROR_INVALID_LENGTH
Invalid length specified for a key, packet, etc.
NoiseCipherState * cipher
Points to the CipherState object for this SymmetricState.
Definition: internal.h:516
int noise_symmetricstate_free(NoiseSymmetricState *state)
Frees a SymmetricState object after destroying all sensitive material.
Internal structure of the NoiseSymmetricState type.
Definition: internal.h:500
int noise_hashstate_hkdf(NoiseHashState *state, const uint8_t *key, size_t key_len, const uint8_t *data, size_t data_len, uint8_t *output1, size_t output1_len, uint8_t *output2, size_t output2_len)
Hashes input data with a key to generate two output values.
Definition: hashstate.c:477
size_t noise_symmetricstate_get_mac_length(const NoiseSymmetricState *state)
Gets the current length of packet MAC values for a SymmetricState object.
int noise_symmetricstate_new_by_id(NoiseSymmetricState **state, const NoiseProtocolId *id)
Creates a new SymmetricState object from a protocol identifier.
int noise_symmetricstate_mix_hash(NoiseSymmetricState *state, const uint8_t *input, size_t size)
Mixes new input data into the handshake hash.
#define NOISE_ERROR_NOT_APPLICABLE
An option was supplied that was not applicable to the selected protocol.
Internal definitions for the library.
int noise_symmetricstate_encrypt_and_hash(NoiseSymmetricState *state, NoiseBuffer *buffer)
Encrypts a block of data with this SymmetricState object and adds the ciphertext to the handshake has...
size_t size
Definition: buffer.h:36
void noise_free(void *ptr, size_t size)
Destroys the contents of a block of memory and free it.
Definition: util.c:152
Internal structure of the NoiseCipherState type.
Definition: internal.h:58
int noise_hashstate_free(NoiseHashState *state)
Frees a HashState object after destroying all sensitive material.
Definition: hashstate.c:156
#define noise_new(type)
Allocates an object from the system and initializes it.
Definition: util.h:35
int noise_cipherstate_new_by_id(NoiseCipherState **state, int id)
Creates a new CipherState object by its algorithm identifier.
Definition: cipherstate.c:77
size_t noise_hashstate_get_hash_length(const NoiseHashState *state)
Gets the length of the hash output for a HashState object.
Definition: hashstate.c:192
int noise_protocol_id_to_name(char *name, size_t name_len, const NoiseProtocolId *id)
Formats a protocol name from a set of identifiers for the algorithms that make up the name...
Definition: names.c:437
int noise_hashstate_hash_two(NoiseHashState *state, const uint8_t *data1, size_t data1_len, const uint8_t *data2, size_t data2_len, uint8_t *hash, size_t hash_len)
Hashes the concatenation of two data buffers and returns the combined hash value. ...
Definition: hashstate.c:352
size_t size
Total size of the structure including subclass state.
Definition: internal.h:365
int noise_cipherstate_has_key(const NoiseCipherState *state)
Determine if the key has been set on a CipherState object.
Definition: cipherstate.c:247
size_t noise_cipherstate_get_key_length(const NoiseCipherState *state)
Gets the length of the encryption key for a CipherState object.
Definition: cipherstate.c:188
int noise_symmetricstate_split(NoiseSymmetricState *state, NoiseCipherState **c1, NoiseCipherState **c2)
Splits the transport encryption CipherState objects out of this SymmetricState object.
int noise_symmetricstate_new_by_name(NoiseSymmetricState **state, const char *name)
Creates a new SymmetricState object from a protocol name.
int noise_symmetricstate_decrypt_and_hash(NoiseSymmetricState *state, NoiseBuffer *buffer)
Decrypts a block of data with this SymmetricState object and adds the ciphertext to the handshake has...
Type that defines a region of memory for a data buffer.
Definition: buffer.h:33