dh.c
Go to the documentation of this file.
1 /**
2  * @file dh.c
3  * @brief Diffie-Hellman key exchange
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * The Diffie-Hellman key agreement protocol allows two users to exchange a
28  * secret key over an insecure medium without any prior secrets. Refer to
29  * PKCS #3 (Diffie-Hellman Key-Agreement Standard)
30  *
31  * @author Oryx Embedded SARL (www.oryx-embedded.com)
32  * @version 1.9.0
33  **/
34 
35 //Switch to the appropriate trace level
36 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
37 
38 //Dependencies
39 #include "core/crypto.h"
40 #include "pkc/dh.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (DH_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Initialize Diffie-Hellman context
49  * @param[in] context Pointer to the Diffie-Hellman context
50  **/
51 
52 void dhInit(DhContext *context)
53 {
54  //Initialize Diffie-Hellman parameters
55  mpiInit(&context->params.p);
56  mpiInit(&context->params.g);
57  //Initialize private and public values
58  mpiInit(&context->xa);
59  mpiInit(&context->ya);
60  mpiInit(&context->yb);
61 }
62 
63 
64 /**
65  * @brief Release Diffie-Hellman context
66  * @param[in] context Pointer to the Diffie-Hellman context
67  **/
68 
69 void dhFree(DhContext *context)
70 {
71  //Release Diffie-Hellman parameters
72  mpiFree(&context->params.p);
73  mpiFree(&context->params.g);
74  //Release private and public values
75  mpiFree(&context->xa);
76  mpiFree(&context->ya);
77  mpiFree(&context->yb);
78 }
79 
80 
81 /**
82  * @brief Diffie-Hellman key pair generation
83  * @param[in] context Pointer to the Diffie-Hellman context
84  * @param[in] prngAlgo PRNG algorithm
85  * @param[in] prngContext Pointer to the PRNG context
86  * @return Error code
87  **/
88 
90  const PrngAlgo *prngAlgo, void *prngContext)
91 {
92  error_t error;
93  uint_t k;
94 
95  //Debug message
96  TRACE_DEBUG("Generating Diffie-Hellman key pair...\r\n");
97 
98  //Get the length in bits of the prime p
99  k = mpiGetBitLength(&context->params.p);
100  //Ensure the length is valid
101  if(k == 0)
103 
104  //The private value shall be randomly generated
105  error = mpiRand(&context->xa, k, prngAlgo, prngContext);
106  //Any error to report?
107  if(error)
108  return error;
109 
110  //The private value shall be less than p
111  if(mpiComp(&context->xa, &context->params.p) >= 0)
112  {
113  //Shift value to the right
114  error = mpiShiftRight(&context->xa, 1);
115  //Any error to report?
116  if(error)
117  return error;
118  }
119 
120  //Debug message
121  TRACE_DEBUG(" Private value:\r\n");
122  TRACE_DEBUG_MPI(" ", &context->xa);
123 
124  //Calculate the corresponding public value (ya = g ^ xa mod p)
125  error = mpiExpMod(&context->ya, &context->params.g, &context->xa, &context->params.p);
126  //Any error to report?
127  if(error)
128  return error;
129 
130  //Debug message
131  TRACE_DEBUG(" Public value:\r\n");
132  TRACE_DEBUG_MPI(" ", &context->ya);
133 
134  //Check public value
135  error = dhCheckPublicKey(&context->params, &context->ya);
136  //Weak public value?
137  if(error)
138  return error;
139 
140  //Public value successfully generated
141  return NO_ERROR;
142 }
143 
144 
145 /**
146  * @brief Check Diffie-Hellman public value
147  * @param[in] params Pointer to the Diffie-Hellman parameters
148  * @param[in] publicKey Public value to be checked
149  * @return Error code
150  **/
151 
152 error_t dhCheckPublicKey(DhParameters *params, const Mpi *publicKey)
153 {
154  error_t error;
155  Mpi a;
156 
157  //Initialize multiple precision integer
158  mpiInit(&a);
159  //Precompute p - 1
160  error = mpiSubInt(&a, &params->p, 1);
161 
162  //Check status
163  if(!error)
164  {
165  //Reject weak public values 1 and p - 1
166  if(mpiCompInt(publicKey, 1) <= 0)
167  error = ERROR_ILLEGAL_PARAMETER;
168  else if(mpiComp(publicKey, &a) >= 0)
169  error = ERROR_ILLEGAL_PARAMETER;
170  }
171 
172  //Free previously allocated resources
173  mpiFree(&a);
174  //Return status code
175  return error;
176 }
177 
178 
179 /**
180  * @brief Compute Diffie-Hellman shared secret
181  * @param[in] context Pointer to the Diffie-Hellman context
182  * @param[out] output Buffer where to store the shared secret
183  * @param[in] outputSize Size of the buffer in bytes
184  * @param[out] outputLen Length of the resulting shared secret
185  * @return Error code
186  **/
187 
189  uint8_t *output, size_t outputSize, size_t *outputLen)
190 {
191  error_t error;
192  size_t k;
193  Mpi z;
194 
195  //Debug message
196  TRACE_DEBUG("Computing Diffie-Hellman shared secret...\r\n");
197 
198  //Get the length in octets of the prime modulus
199  k = mpiGetByteLength(&context->params.p);
200 
201  //Make sure that the output buffer is large enough
202  if(outputSize < k)
203  return ERROR_INVALID_LENGTH;
204 
205  //The multiple precision integer must be initialized before it can be used
206  mpiInit(&z);
207 
208  //Start of exception handling block
209  do
210  {
211  //Calculate the shared secret key (k = yb ^ xa mod p)
212  error = mpiExpMod(&z, &context->yb, &context->xa, &context->params.p);
213  //Any error to report?
214  if(error)
215  break;
216 
217  //Convert the resulting integer to an octet string
218  error = mpiWriteRaw(&z, output, k);
219  //Conversion failed?
220  if(error)
221  break;
222 
223  //Length of the resulting shared secret
224  *outputLen = k;
225 
226  //Debug message
227  TRACE_DEBUG(" Shared secret (%" PRIuSIZE " bytes):\r\n", *outputLen);
228  TRACE_DEBUG_ARRAY(" ", output, *outputLen);
229 
230  //End of exception handling block
231  } while(0);
232 
233  //Release previously allocated resources
234  mpiFree(&z);
235  //Return status code
236  return error;
237 }
238 
239 #endif
error_t mpiRand(Mpi *r, uint_t length, const PrngAlgo *prngAlgo, void *prngContext)
Generate a random value.
Definition: mpi.c:460
Mpi xa
One&#39;s own private value.
Definition: dh.h:60
#define mpiWriteRaw(a, data, length)
Definition: crypto_legacy.h:34
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:60
Arbitrary precision integer.
Definition: mpi.h:67
Debugging facilities.
error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation.
Definition: mpi.c:1492
General definitions for cryptographic algorithms.
Invalid parameter.
Definition: error.h:45
int_t mpiComp(const Mpi *a, const Mpi *b)
Compare two multiple precision integers.
Definition: mpi.c:287
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:99
uint16_t z
Definition: dns_common.h:173
uint8_t a
Definition: ndp.h:407
Diffie-Hellman context.
Definition: dh.h:57
Mpi g
Generator.
Definition: dh.h:49
#define TRACE_DEBUG_MPI(p, a)
Definition: debug.h:101
error_t dhGenerateKeyPair(DhContext *context, const PrngAlgo *prngAlgo, void *prngContext)
Diffie-Hellman key pair generation.
Definition: dh.c:89
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:190
DhParameters params
Definition: dh.h:59
Diffie-Hellman key exchange.
Mpi ya
One&#39;s own public value.
Definition: dh.h:61
error_t dhCheckPublicKey(DhParameters *params, const Mpi *publicKey)
Check Diffie-Hellman public value.
Definition: dh.c:152
Success.
Definition: error.h:42
error_t mpiSubInt(Mpi *r, const Mpi *a, int_t b)
Subtract an integer from a multiple precision integer.
Definition: mpi.c:796
error_t
Error codes.
Definition: error.h:40
int_t mpiCompInt(const Mpi *a, int_t b)
Compare a multiple precision integer with an integer.
Definition: mpi.c:331
unsigned int uint_t
Definition: compiler_port.h:43
#define PRIuSIZE
Definition: compiler_port.h:72
Common interface for pseudo-random number generators.
Definition: crypto.h:1091
void dhInit(DhContext *context)
Initialize Diffie-Hellman context.
Definition: dh.c:52
error_t dhComputeSharedSecret(DhContext *context, uint8_t *output, size_t outputSize, size_t *outputLen)
Compute Diffie-Hellman shared secret.
Definition: dh.c:188
Mpi yb
Peer&#39;s public value.
Definition: dh.h:62
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:46
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:154
Diffie-Hellman parameters.
Definition: dh.h:46
void dhFree(DhContext *context)
Release Diffie-Hellman context.
Definition: dh.c:69
Mpi p
Prime modulus.
Definition: dh.h:48
#define TRACE_DEBUG(...)
Definition: debug.h:98
error_t mpiShiftRight(Mpi *r, uint_t n)
Right shift operation.
Definition: mpi.c:1041