Noise-C
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
dhstate.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 
68 {
69  /* The "state" argument must be non-NULL */
70  if (!state)
72 
73  /* Create the DHState object for the "id" */
74  *state = 0;
75  switch (id) {
77  *state = noise_curve25519_new();
78  break;
79 
80  case NOISE_DH_CURVE448:
81  *state = noise_curve448_new();
82  break;
83 
84  case NOISE_DH_NEWHOPE:
85  *state = noise_newhope_new();
86  break;
87 
88  default:
90  }
91 
92  /* Bail out if insufficient memory */
93  if (!(*state))
94  return NOISE_ERROR_NO_MEMORY;
95 
96  /* Ready to go */
97  return NOISE_ERROR_NONE;
98 }
99 
116 int noise_dhstate_new_by_name(NoiseDHState **state, const char *name)
117 {
118  int id;
119 
120  /* The "state" and "name" arguments must be non-NULL */
121  if (!state)
123  *state = 0;
124  if (!name)
126 
127  /* Map the name and create the corresponding object */
128  id = noise_name_to_id(NOISE_DH_CATEGORY, name, strlen(name));
129  if (id)
130  return noise_dhstate_new_by_id(state, id);
131 
132  /* We don't know what this is */
134 }
135 
147 {
148  /* Bail out if no DH state */
149  if (!state)
151 
152  /* Call the backend-specific destroy function if necessary */
153  if (state->destroy)
154  (*(state->destroy))(state);
155 
156  /* Clean and free the memory */
157  noise_free(state, state->size);
158  return NOISE_ERROR_NONE;
159 }
160 
169 {
170  return state ? state->dh_id : NOISE_DH_NONE;
171 }
172 
184 {
185  return state ? state->public_key_len : 0;
186 }
187 
199 {
200  return state ? state->private_key_len : 0;
201 }
202 
214 {
215  return state ? state->shared_key_len : 0;
216 }
217 
231 {
232  return state ? state->ephemeral_only : 0;
233 }
234 
248 {
249  if (state)
250  return state->key_type == NOISE_KEY_TYPE_KEYPAIR;
251  else
252  return 0;
253 }
254 
268 {
269  if (state)
270  return state->key_type != NOISE_KEY_TYPE_NO_KEY;
271  else
272  return 0;
273 }
274 
290 {
291  int err;
292 
293  /* Validate the parameter */
294  if (!state)
296 
297  /* Generate the new keypair */
298  err = (*(state->generate_keypair))(state, 0);
299  if (err == NOISE_ERROR_NONE)
301  return err;
302 }
303 
332  (NoiseDHState *state, const NoiseDHState *other)
333 {
334  int err;
335 
336  /* Validate the parameters */
337  if (!state)
339  if (other && state->dh_id != other->dh_id)
341 
342  /* Generate the new keypair */
343  err = (*(state->generate_keypair))(state, other);
344  if (err == NOISE_ERROR_NONE)
346  return err;
347 }
348 
374  (NoiseDHState *state, const uint8_t *private_key, size_t private_key_len,
375  const uint8_t *public_key, size_t public_key_len)
376 {
377  int err;
378 
379  /* Validate the parameters */
380  if (!state || !private_key || !public_key)
382  if (private_key_len != state->private_key_len)
384  if (public_key_len != state->public_key_len)
386 
387  /* Set the keypair */
388  err = (*(state->set_keypair))(state, private_key, public_key);
389  if (err != NOISE_ERROR_NONE) {
391  return err;
392  }
394  return NOISE_ERROR_NONE;
395 }
396 
423  (NoiseDHState *state, const uint8_t *private_key, size_t private_key_len)
424 {
425  int err;
426 
427  /* Validate the parameters */
428  if (!state || !private_key)
430  if (private_key_len != state->private_key_len)
432 
433  /* Set the private key and derive the public key from the private key */
434  err = (*(state->set_keypair_private))(state, private_key);
435  if (err != NOISE_ERROR_NONE) {
437  return err;
438  }
440  return NOISE_ERROR_NONE;
441 }
442 
462  (const NoiseDHState *state, uint8_t *private_key, size_t private_key_len,
463  uint8_t *public_key, size_t public_key_len)
464 {
465  /* Validate the parameters */
466  if (!state || !private_key || !public_key)
468  if (private_key_len != state->private_key_len)
470  if (public_key_len != state->public_key_len)
472 
473  /* Is this actually a keypair? */
474  if (state->key_type != NOISE_KEY_TYPE_KEYPAIR) {
475  memset(private_key, 0, private_key_len);
476  memset(public_key, 0, public_key_len);
478  }
479 
480  /* Copy the keypair out */
481  memcpy(private_key, state->private_key, private_key_len);
482  memcpy(public_key, state->public_key, public_key_len);
483  return NOISE_ERROR_NONE;
484 }
485 
511  (NoiseDHState *state, const uint8_t *public_key, size_t public_key_len)
512 {
513  int is_null, err;
514 
515  /* Validate the parameters */
516  if (!state || !public_key)
518  if (public_key_len != state->public_key_len)
520 
521  /* Validate the public key with the back end and then ignore the
522  result if the public key is the special null value */
523  is_null = state->nulls_allowed & noise_is_zero(public_key, public_key_len);
524  err = (*(state->validate_public_key))(state, public_key);
525  err &= (is_null - 1);
526  if (err != NOISE_ERROR_NONE)
527  return err;
528 
529  /* Copy the public key into place and clear the private key */
530  memset(state->private_key, 0, state->private_key_len);
531  memcpy(state->public_key, public_key, public_key_len);
533  return NOISE_ERROR_NONE;
534 }
535 
551  (const NoiseDHState *state, uint8_t *public_key, size_t public_key_len)
552 {
553  /* Validate the parameters */
554  if (!state || !public_key)
556  if (public_key_len != state->public_key_len)
558 
559  /* Copy the public key out */
560  memcpy(public_key, state->public_key, public_key_len);
561  return NOISE_ERROR_NONE;
562 }
563 
577 {
578  /* Validate the parameter */
579  if (!state || !state->nulls_allowed)
581 
582  /* Clear the key to all-zeroes */
583  memset(state->public_key, 0, state->public_key_len);
584  memset(state->private_key, 0, state->private_key_len);
585 
586  /* We have a public key but no private key */
588  return NOISE_ERROR_NONE;
589 }
590 
603 {
604  if (state && state->key_type != NOISE_KEY_TYPE_NO_KEY) {
605  return state->nulls_allowed &&
606  noise_is_zero(state->public_key, state->public_key_len);
607  } else {
608  return 0;
609  }
610 }
611 
623 {
624  /* Validate the parameter */
625  if (!state)
627 
628  /* Clear the key to all-zeroes */
629  memset(state->public_key, 0, state->public_key_len);
630  memset(state->private_key, 0, state->private_key_len);
631 
632  /* There is no key in the object now */
634  return NOISE_ERROR_NONE;
635 }
636 
645 static void noise_cmove_zero(uint8_t *data, size_t len, int condition)
646 {
647  /* Turn the condition into an all-zeroes or all-ones mask.
648  If the condition is set, then we want all-zeroes in the mask.
649  If the condition is not set, then we want all-ones in the mask. */
650  uint8_t mask = ~((uint8_t)(-condition));
651 
652  /* AND the contents of the data buffer with the mask */
653  while (len > 0) {
654  *data++ &= mask;
655  --len;
656  }
657 }
658 
686  (const NoiseDHState *private_key_state,
687  const NoiseDHState *public_key_state,
688  uint8_t *shared_key, size_t shared_key_len)
689 {
690  int is_null, err;
691 
692  /* Validate the parameters */
693  if (!private_key_state || !public_key_state || !shared_key)
695  if (private_key_state->dh_id != public_key_state->dh_id)
697  if (shared_key_len != private_key_state->shared_key_len)
699  if (private_key_state->key_type != NOISE_KEY_TYPE_KEYPAIR)
701 
702  /* If the public key is null, then the output must be null too.
703  We check for null now, but still perform the normal evaluation.
704  At the end we will null out the result in constant time */
705  is_null = public_key_state->nulls_allowed & noise_is_zero
706  (public_key_state->public_key, public_key_state->public_key_len);
707 
708  /* Perform the calculation */
709  err = (*(private_key_state->calculate))
710  (private_key_state, public_key_state, shared_key);
711 
712  /* If the public key was null, then we need to set the shared key
713  to null and replace any error we got from the back end with "none" */
714  noise_cmove_zero(shared_key, shared_key_len, is_null);
715  err &= (is_null - 1);
716  return err;
717 }
718 
731 {
732  int err;
733 
734  /* Validate the parameters */
735  if (!state || !from)
737  if (state->dh_id != from->dh_id)
739  if (state == from)
740  return NOISE_ERROR_NONE;
741 
742  /* Copy the key information across */
743  err = (*(state->copy))(state, from, 0);
744  if (err != NOISE_ERROR_NONE)
745  return err;
746  state->key_type = from->key_type;
747  return err;
748 }
749 
776  (const NoiseDHState *state, int fingerprint_type, char *buffer, size_t len)
777 {
778  /* Validate the parameters */
779  if (!buffer)
781  if (!len)
783  *buffer = '\0'; /* In case we bail out with an error later */
784  if (!state)
786  if (state->key_type == NOISE_KEY_TYPE_NO_KEY)
788 
789  /* Format the fingerprint */
791  (fingerprint_type, buffer, len,
792  state->public_key, state->public_key_len);
793 }
794 
806 {
807  return state ? state->role : 0;
808 }
809 
836 {
837  if (!state)
839  if (role != NOISE_ROLE_INITIATOR && role != NOISE_ROLE_RESPONDER && role)
841  state->role = role;
842  if (state->change_role)
843  (*(state->change_role))(state);
844  return NOISE_ERROR_NONE;
845 }
846 
int noise_dhstate_get_public_key(const NoiseDHState *state, uint8_t *public_key, size_t public_key_len)
Gets the public key value from a DHState object.
Definition: dhstate.c:551
uint8_t nulls_allowed
Non-zero if null public keys are allowed with this algorithm.
Definition: internal.h:231
#define NOISE_ERROR_UNKNOWN_ID
Algorithm identifier is unknown.
int noise_dhstate_clear_key(NoiseDHState *state)
Clears the key in a DHState object.
Definition: dhstate.c:622
size_t noise_dhstate_get_public_key_length(const NoiseDHState *state)
Gets the length of the public key for a DHState object.
Definition: dhstate.c:183
int noise_dhstate_get_keypair(const NoiseDHState *state, uint8_t *private_key, size_t private_key_len, uint8_t *public_key, size_t public_key_len)
Gets the keypair from within a DHState object.
Definition: dhstate.c:462
#define NOISE_ERROR_INVALID_STATE
Operation cannot be performed in the current state.
#define NOISE_ERROR_INVALID_PARAM
Invalid parameter to function; e.g. a NULL value.
uint8_t * public_key
Points to the public key in the subclass state.
Definition: internal.h:246
size_t noise_dhstate_get_shared_key_length(const NoiseDHState *state)
Gets the length of the shared key for a DHState object.
Definition: dhstate.c:213
int noise_dhstate_get_dh_id(const NoiseDHState *state)
Gets the algorithm identifier for a DHState object.
Definition: dhstate.c:168
int noise_dhstate_format_fingerprint(const NoiseDHState *state, int fingerprint_type, char *buffer, size_t len)
Formats the public key fingerprint for the key within a DHState.
Definition: dhstate.c:776
#define NOISE_ERROR_NONE
Success, no error.
#define NOISE_KEY_TYPE_NO_KEY
Definition: internal.h:206
int(* validate_public_key)(const NoiseDHState *state, const uint8_t *public_key)
Validates a public key.
Definition: internal.h:300
void(* destroy)(NoiseDHState *state)
Destroys this DHState prior to the memory being freed.
Definition: internal.h:356
int noise_dhstate_get_role(const NoiseDHState *state)
Gets the role that a DHState object will play in a handshake.
Definition: dhstate.c:805
void(* change_role)(NoiseDHState *state)
Changes the role for this object.
Definition: internal.h:342
int noise_is_zero(const void *data, size_t size)
Determine if a block of memory consists of all zero bytes.
Definition: util.c:211
int noise_dhstate_new_by_id(NoiseDHState **state, int id)
Creates a new DHState object by its algorithm identifier.
Definition: dhstate.c:67
int noise_format_fingerprint(int fingerprint_type, char *buffer, size_t len, const uint8_t *public_key, size_t public_key_len)
Formats the fingerprint for a raw public key value.
Definition: util.c:246
int(* set_keypair_private)(NoiseDHState *state, const uint8_t *private_key)
Sets a keypair using only the private key.
Definition: internal.h:287
#define NOISE_DH_CATEGORY
Category for Diffie-Hellman algorithms.
int(* set_keypair)(NoiseDHState *state, const uint8_t *private_key, const uint8_t *public_key)
Sets a keypair.
Definition: internal.h:273
#define NOISE_DH_CURVE448
Diffie-Hellman identifier for "448".
#define NOISE_KEY_TYPE_KEYPAIR
Definition: internal.h:207
uint16_t shared_key_len
Length of the shared key for this algorithm in bytes.
Definition: internal.h:240
Internal structure of the NoiseDHState type.
Definition: internal.h:213
#define NOISE_ERROR_NO_MEMORY
Insufficient memory to complete the operation.
int noise_dhstate_is_ephemeral_only(const NoiseDHState *state)
Determine if a DHState object only supports ephemeral keys.
Definition: dhstate.c:230
#define NOISE_ERROR_UNKNOWN_NAME
Algorithm name is unknown.
size_t size
Total size of the structure including subclass state.
Definition: internal.h:216
#define NOISE_ERROR_INVALID_LENGTH
Invalid length specified for a key, packet, etc.
#define NOISE_DH_NEWHOPE
Diffie-Hellman identifier for "NewHope" (post-quantum, ephemeral key exchanges only).
uint8_t key_type
The type of key stored within this DHState object.
Definition: internal.h:225
uint8_t ephemeral_only
Non-zero if this algorithm only supports ephemeral keys.
Definition: internal.h:228
#define NOISE_ERROR_INVALID_PRIVATE_KEY
Invalid private key value.
int noise_dhstate_has_keypair(const NoiseDHState *state)
Determine if a DHState object contains a keypair.
Definition: dhstate.c:247
#define NOISE_ROLE_INITIATOR
This end of the communications is the initiator.
int noise_dhstate_set_null_public_key(NoiseDHState *state)
Sets the public key in a DHState object to the special null value.
Definition: dhstate.c:576
int noise_dhstate_calculate(const NoiseDHState *private_key_state, const NoiseDHState *public_key_state, uint8_t *shared_key, size_t shared_key_len)
Performs a Diffie-Hellman calculation.
Definition: dhstate.c:686
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
int noise_dhstate_set_keypair(NoiseDHState *state, const uint8_t *private_key, size_t private_key_len, const uint8_t *public_key, size_t public_key_len)
Sets the keypair within a DHState object.
Definition: dhstate.c:374
#define NOISE_ERROR_NOT_APPLICABLE
An option was supplied that was not applicable to the selected protocol.
int(* calculate)(const NoiseDHState *private_key_state, const NoiseDHState *public_key_state, uint8_t *shared_key)
Performs a Diffie-Hellman calculation.
Definition: internal.h:330
Internal definitions for the library.
#define NOISE_ROLE_RESPONDER
This end of the communications is the responder.
int noise_dhstate_free(NoiseDHState *state)
Frees a DHState object after destroying all sensitive material.
Definition: dhstate.c:146
#define NOISE_DH_CURVE25519
Diffie-Hellman identifier for "25519".
void noise_free(void *ptr, size_t size)
Destroys the contents of a block of memory and free it.
Definition: util.c:152
int noise_dhstate_generate_keypair(NoiseDHState *state)
Generates a new key pair within a DHState object.
Definition: dhstate.c:289
#define NOISE_DH_NONE
Diffie-Hellman identifier that indicates "no DH".
int(* copy)(NoiseDHState *state, const NoiseDHState *from, const NoiseDHState *other)
Copies another key into this object.
Definition: internal.h:310
int noise_dhstate_has_public_key(const NoiseDHState *state)
Determine if a DHState object contains a public key.
Definition: dhstate.c:267
#define NOISE_KEY_TYPE_PUBLIC
Definition: internal.h:208
int noise_dhstate_is_null_public_key(const NoiseDHState *state)
Determine if the public key in a DHState object has the special null value.
Definition: dhstate.c:602
int noise_dhstate_new_by_name(NoiseDHState **state, const char *name)
Creates a new DHState object by its algorithm name.
Definition: dhstate.c:116
uint16_t private_key_len
Length of the private key for this algorithm in bytes.
Definition: internal.h:234
int(* generate_keypair)(NoiseDHState *state, const NoiseDHState *other)
Generates a new key pair for this Diffie-Hellman algorithm.
Definition: internal.h:257
short dh_id
Algorithm identifier for the Diffie-Hellman operation.
Definition: internal.h:219
int noise_dhstate_copy(NoiseDHState *state, const NoiseDHState *from)
Copies the keys from one DHState object to another.
Definition: dhstate.c:730
size_t noise_dhstate_get_private_key_length(const NoiseDHState *state)
Gets the length of the private key for a DHState object.
Definition: dhstate.c:198
int noise_dhstate_set_keypair_private(NoiseDHState *state, const uint8_t *private_key, size_t private_key_len)
Sets the keypair within a DHState object based on a private key only.
Definition: dhstate.c:423
int noise_dhstate_set_public_key(NoiseDHState *state, const uint8_t *public_key, size_t public_key_len)
Sets the public key in a DHState object.
Definition: dhstate.c:511
int noise_dhstate_set_role(NoiseDHState *state, int role)
Sets the role that a DHState object will play in a handshake.
Definition: dhstate.c:835
int noise_dhstate_generate_dependent_keypair(NoiseDHState *state, const NoiseDHState *other)
Generates a new key pair within a DHState object that may depend upon the parameters from another DHS...
Definition: dhstate.c:332
uint8_t * private_key
Points to the private key in the subclass state.
Definition: internal.h:243
short role
The role; either initiator or responder or zero.
Definition: internal.h:222
uint16_t public_key_len
Length of the public key for this algorithm in bytes.
Definition: internal.h:237