Noise-C
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
cipherstate.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 
54 #define NOISE_MAX_KEY_LEN 32
55 
57 #define NOISE_MAX_MAC_LEN 16
58 
78 {
79  /* The "state" argument must be non-NULL */
80  if (!state)
82 
83  /* Create the CipherState object for the "id" */
84  *state = 0;
85  switch (id) {
87  *state = noise_chachapoly_new();
88  break;
89 
91  *state = noise_aesgcm_new();
92  break;
93 
94  default:
96  }
97 
98  /* Bail out if insufficient memory */
99  if (!(*state))
100  return NOISE_ERROR_NO_MEMORY;
101 
102  /* Ready to go */
103  return NOISE_ERROR_NONE;
104 }
105 
122 int noise_cipherstate_new_by_name(NoiseCipherState **state, const char *name)
123 {
124  int id;
125 
126  /* The "state" and "name" arguments must be non-NULL */
127  if (!state)
129  *state = 0;
130  if (!name)
132 
133  /* Map the name and create the corresponding object */
134  id = noise_name_to_id(NOISE_CIPHER_CATEGORY, name, strlen(name));
135  if (id)
136  return noise_cipherstate_new_by_id(state, id);
137 
138  /* We don't know what this is */
140 }
141 
153 {
154  /* Bail out if no cipher state */
155  if (!state)
157 
158  /* Call the backend-specific destroy function if necessary */
159  if (state->destroy)
160  (*(state->destroy))(state);
161 
162  /* Clean and free the memory */
163  noise_free(state, state->size);
164  return NOISE_ERROR_NONE;
165 }
166 
175 {
176  return state ? state->cipher_id : NOISE_CIPHER_NONE;
177 }
178 
189 {
190  return state ? state->key_len : 0;
191 }
192 
203 {
204  return state ? state->mac_len : 0;
205 }
206 
222  (NoiseCipherState *state, const uint8_t *key, size_t key_len)
223 {
224  /* Validate the parameters */
225  if (!state || !key)
227  if (key_len != state->key_len)
229 
230  /* Set the key */
231  (*(state->init_key))(state, key);
232  state->has_key = 1;
233  state->n = 0;
234  return NOISE_ERROR_NONE;
235 }
236 
248 {
249  return state ? state->has_key : 0;
250 }
251 
294  (NoiseCipherState *state, const uint8_t *ad, size_t ad_len,
295  NoiseBuffer *buffer)
296 {
297  int err;
298 
299  /* Validate the parameters */
300  if (!state || (!ad && ad_len) || !buffer || !(buffer->data))
302  if (buffer->size > buffer->max_size)
304 
305  /* If the key hasn't been set yet, return the plaintext as-is */
306  if (!state->has_key) {
307  if (buffer->size > NOISE_MAX_PAYLOAD_LEN)
309  return NOISE_ERROR_NONE;
310  }
311 
312  /* Make sure that there is room for the MAC */
313  if (buffer->size > (size_t)(NOISE_MAX_PAYLOAD_LEN - state->mac_len))
315  if ((buffer->max_size - buffer->size) < state->mac_len)
317 
318  /* If the nonce has overflowed, then further encryption is impossible.
319  The value 2^64 - 1 is reserved (Noise specification revision 30),
320  so if the nonce has reached that value then overflow has occurred. */
321  if (state->n == 0xFFFFFFFFFFFFFFFFULL)
323 
324  /* Encrypt the plaintext and authenticate it */
325  err = (*(state->encrypt))(state, ad, ad_len, buffer->data, buffer->size);
326  ++(state->n);
327  if (err != NOISE_ERROR_NONE)
328  return err;
329 
330  /* Adjust the output length for the MAC and return */
331  buffer->size += state->mac_len;
332  return NOISE_ERROR_NONE;
333 }
334 
374  (NoiseCipherState *state, const uint8_t *ad, size_t ad_len,
375  NoiseBuffer *buffer)
376 {
377  int err;
378 
379  /* Validate the parameters */
380  if (!state || (!ad && ad_len) || !buffer || !(buffer->data))
382  if (buffer->size > buffer->max_size || buffer->size > NOISE_MAX_PAYLOAD_LEN)
384 
385  /* If the key hasn't been set yet, return the ciphertext as-is */
386  if (!state->has_key)
387  return NOISE_ERROR_NONE;
388 
389  /* Make sure there are enough bytes for the MAC */
390  if (buffer->size < state->mac_len)
392 
393  /* If the nonce has overflowed, then further decryption is impossible.
394  The value 2^64 - 1 is reserved (Noise specification revision 30),
395  so if the nonce has reached that value then overflow has occurred. */
396  if (state->n == 0xFFFFFFFFFFFFFFFFULL)
398 
399  /* Decrypt the ciphertext and check the MAC */
400  err = (*(state->decrypt))
401  (state, ad, ad_len, buffer->data, buffer->size - state->mac_len);
402  ++(state->n);
403  if (err != NOISE_ERROR_NONE)
404  return err;
405 
406  /* Adjust the output length for the MAC and return */
407  buffer->size -= state->mac_len;
408  return NOISE_ERROR_NONE;
409 }
410 
452 {
453  return noise_cipherstate_encrypt_with_ad(state, NULL, 0, buffer);
454 }
455 
494 {
495  return noise_cipherstate_decrypt_with_ad(state, NULL, 0, buffer);
496 }
497 
518 {
519  /* Bail out if the state is NULL */
520  if (!state)
522 
523  /* If the key hasn't been set yet, we cannot do this */
524  if (!state->has_key)
526 
527  /* Reject the value if the nonce would go backwards */
528  if (state->n > nonce)
530 
531  /* Set the nonce and return */
532  state->n = nonce;
533  return NOISE_ERROR_NONE;
534 }
535 
542 {
543  return NOISE_MAX_KEY_LEN;
544 }
545 
552 {
553  return NOISE_MAX_MAC_LEN;
554 }
555 
#define NOISE_MAX_PAYLOAD_LEN
Maximum payload length for Noise packets.
int noise_cipherstate_decrypt(NoiseCipherState *state, NoiseBuffer *buffer)
Decrypts a block of data with this CipherState object.
Definition: cipherstate.c:493
int(* decrypt)(NoiseCipherState *state, const uint8_t *ad, size_t ad_len, uint8_t *data, size_t len)
Decrypts data with this CipherState.
Definition: internal.h:130
#define NOISE_ERROR_UNKNOWN_ID
Algorithm identifier is unknown.
uint8_t mac_len
Length of the MAC for this cipher in bytes.
Definition: internal.h:73
int(* encrypt)(NoiseCipherState *state, const uint8_t *ad, size_t ad_len, uint8_t *data, size_t len)
Encrypts data with this CipherState.
Definition: internal.h:113
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
#define NOISE_ERROR_INVALID_STATE
Operation cannot be performed in the current state.
size_t max_size
Definition: buffer.h:37
int noise_cipherstate_get_cipher_id(const NoiseCipherState *state)
Gets the algorithm identifier for a CipherState object.
Definition: cipherstate.c:174
#define NOISE_ERROR_INVALID_PARAM
Invalid parameter to function; e.g. a NULL value.
NoiseCipherState * noise_aesgcm_new(void)
Creates a new AES-GCM CipherState object.
Definition: internal.c:40
#define NOISE_ERROR_NONE
Success, no error.
#define NOISE_CIPHER_AESGCM
Cipher identifier for "AESGCM".
int noise_cipherstate_set_nonce(NoiseCipherState *state, uint64_t nonce)
Sets the nonce value for this cipherstate object.
Definition: cipherstate.c:517
uint8_t has_key
Non-zero if the key has been set on this cipher.
Definition: internal.h:67
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_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_cipherstate_get_max_mac_length(void)
Gets the maximum MAC length for the supported algorithms.
Definition: cipherstate.c:551
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
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.
uint8_t key_len
Length of the key for this cipher in bytes.
Definition: internal.h:70
#define NOISE_ERROR_UNKNOWN_NAME
Algorithm name is unknown.
#define NOISE_CIPHER_CHACHAPOLY
Cipher identifier for "ChaChaPoly".
uint64_t n
The nonce value for the next packet.
Definition: internal.h:76
#define NOISE_ERROR_INVALID_LENGTH
Invalid length specified for a key, packet, etc.
int cipher_id
Algorithm identifier for the cipher.
Definition: internal.h:64
int noise_name_to_id(int category, const char *name, size_t name_len)
Maps an algorithm name to the corresponding identifier.
Definition: names.c:146
#define NOISE_CIPHER_CATEGORY
Category for cipher algorithms.
Internal definitions for the library.
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
size_t size
Total size of the structure including subclass state.
Definition: internal.h:61
Internal structure of the NoiseCipherState type.
Definition: internal.h:58
void(* destroy)(NoiseCipherState *state)
Destroys this CipherState prior to the memory being freed.
Definition: internal.h:145
int noise_cipherstate_get_max_key_length(void)
Gets the maximum key length for the supported algorithms.
Definition: cipherstate.c:541
#define NOISE_ERROR_INVALID_NONCE
Invalid nonce value.
int noise_cipherstate_new_by_name(NoiseCipherState **state, const char *name)
Creates a new CipherState object by its algorithm name.
Definition: cipherstate.c:122
void(* init_key)(NoiseCipherState *state, const uint8_t *key)
Sets the key for this CipherState.
Definition: internal.h:95
int noise_cipherstate_new_by_id(NoiseCipherState **state, int id)
Creates a new CipherState object by its algorithm identifier.
Definition: cipherstate.c:77
int noise_cipherstate_encrypt(NoiseCipherState *state, NoiseBuffer *buffer)
Encrypts a block of data with this CipherState object.
Definition: cipherstate.c:451
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
#define NOISE_CIPHER_NONE
Cipher identifier that indicates "no cipher".
Type that defines a region of memory for a data buffer.
Definition: buffer.h:33