LibItsSecurity_externals.cc 85 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/*!
 * \file      LibItsSecurity_Functions.cc
 * \brief     Source file for Security externl functions.
 * \author    ETSI STF525
 * \copyright ETSI Copyright Notification
 *            No part may be reproduced except as authorized by written permission.
 *            The copyright and the foregoing restriction extend to reproduction in all media.
 *            All rights reserved.
 * \version   0.1
 */
11
12
#include <memory>

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "LibItsSecurity_Functions.hh"

#include "sha256.hh"
#include "sha384.hh"
#include "hmac.hh"

#include "security_ecc.hh"

#include "security_services.hh"

#include <openssl/ec.h>
#include <openssl/ecdsa.h>

#include "loggers.hh"

namespace LibItsSecurity__Functions 
{

  // FIXME Unify code with security_services
  
  /**
   * \fn OCTETSTRING fx_hashWithSha256(const OCTETSTRING& p__toBeHashedData);
35
   * \brief Produces a 256-bit (32-bytes) hash value
36
37
38
39
40
41
42
   * \param[in] p__toBeHashedData The data to be used to calculate the hash value
   * \return  The hash value
   */
  OCTETSTRING fx__hashWithSha256(
                                 const OCTETSTRING& p__toBeHashedData
                                 ) {
    loggers::get_instance().log_msg(">>> fx__hashWithSha256: p__toBeHashedData= ", p__toBeHashedData); 
43

44
    sha256 hash;
45
46
47
48
    OCTETSTRING hashData;
    hash.generate(p__toBeHashedData, hashData);
    loggers::get_instance().log_msg("fx__hashWithSha256: hashData= ", hashData);
    return hashData;
49
50
51
52
  } // End of function fx__hashWithSha256

  /**
   * \fn OCTETSTRING fx_hashWithSha384(const OCTETSTRING& p__toBeHashedData);
53
   * \brief Produces a 384-bit (48-bytes) hash value
54
55
56
57
58
59
60
   * \param[in] p__toBeHashedData Data to be used to calculate the hash value
   * \return The hash value
   */
  OCTETSTRING fx__hashWithSha384(
                                 const OCTETSTRING& p__toBeHashedData
                                 ) {
    sha384 hash;
61
62
63
64
    OCTETSTRING hashData;
    hash.generate(p__toBeHashedData, hashData);
    loggers::get_instance().log_msg("fx__hashWithSha384: hashData= ", hashData);
    return hashData;
65
66
67
68
  } // End of function fx__hashWithSha384

  /**
   * \fn OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey);
Yann Garcia's avatar
Yann Garcia committed
69
   * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
70
   * \param[in] p__toBeSignedSecuredMessage The data to be signed
71
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
72
73
74
75
76
77
78
79
   * \param[in] p__privateKey The private key
   * \return The signature value
   */
  OCTETSTRING fx__signWithEcdsaNistp256WithSha256(
                                                  const OCTETSTRING& p__toBeSignedSecuredMessage,
                                                  const OCTETSTRING& p__certificateIssuer,
                                                  const OCTETSTRING& p__privateKey
                                                  ) {
garciay's avatar
garciay committed
80
81
82
83
    loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: data=", p__toBeSignedSecuredMessage); 
    loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: issuer=", p__certificateIssuer); 
    loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: private key=", p__privateKey); 
    
84
    // Sanity checks
85
    if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) {
86
      loggers::get_instance().log("fx__signWithEcdsaNistp256WithSha256: Wrong parameters");
87
      return OCTETSTRING(0, nullptr);
88
89
90
91
    }
    
    // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha256 hash;
92
93
94
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeSignedSecuredMessage, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
95
    if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input)
96
      hashData2 = p__certificateIssuer;
97
98
    } else {
      hashData2 = hash.get_sha256_empty_string(); // Hash of empty string
99
    }
100
101
102
103
104
    loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Signer identifier input)=", hashData2);
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Data input) || Hash (Signer identifier input)=", hashData1);
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
105
    hash.generate(hashData1, hashData);
106
    loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
107
    // Calculate the signature
108
109
110
    security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey);
    OCTETSTRING r_sig;
    OCTETSTRING s_sig;
111
    if (k.sign(hashData, r_sig, s_sig) == 0) {
112
113
114
115
      OCTETSTRING os = r_sig + s_sig;
      loggers::get_instance().log_msg("r_sig= ", r_sig);
      loggers::get_instance().log_msg("s_sig= ", s_sig);
      loggers::get_instance().log_msg("sig= ", os);
116
117
118
      return os;
    }

119
    return OCTETSTRING(0, nullptr);
120
121
  }

Yann Garcia's avatar
Yann Garcia committed
122
123
124
125
126
127
128
  /**
   * \fn OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey);
   * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on raw data
   * \param[in] p__toBeSignedSecuredMessage The data to be signed
   * \param[in] p__privateKey The private key
   * \return The signature value
   */
Yann Garcia's avatar
Yann Garcia committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  OCTETSTRING fx__test__signWithEcdsaNistp256WithSha256(
                                                        const OCTETSTRING& p__toBeSignedSecuredMessage,
                                                        const OCTETSTRING& p__privateKey
                                                        ) {
    loggers::get_instance().log_msg(">>> fx__test__signWithEcdsaNistp256WithSha256: data=", p__toBeSignedSecuredMessage); 
    loggers::get_instance().log_msg(">>> fx__test__signWithEcdsaNistp256WithSha256: private key=", p__privateKey); 
    
    // Sanity checks
    if (p__privateKey.lengthof() != 32) {
      loggers::get_instance().log("fx__test__signWithEcdsaNistp256WithSha256: Wrong parameters");
      return OCTETSTRING(0, nullptr);
    }
    
    // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha256 hash;
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeSignedSecuredMessage, hashData1);
    loggers::get_instance().log_msg("fx__test__signWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1);
    // Calculate the signature
    security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey);
    OCTETSTRING r_sig;
    OCTETSTRING s_sig;
    if (k.sign(hashData1, r_sig, s_sig) == 0) {
      OCTETSTRING os = r_sig + s_sig;
      loggers::get_instance().log_msg("r_sig= ", r_sig);
      loggers::get_instance().log_msg("s_sig= ", s_sig);
      loggers::get_instance().log_msg("sig= ", os);
      return os;
    }

    return OCTETSTRING(0, nullptr);
  }

162
  /**
163
   * \fn OCTETSTRING fx__signWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey);
Yann Garcia's avatar
Yann Garcia committed
164
   * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
165
   * \param[in] p__toBeSignedSecuredMessage The data to be signed
166
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
167
168
169
   * \param[in] p__privateKey The private key
   * \return The signature value
   */
170
  OCTETSTRING fx__signWithEcdsaBrainpoolp256r1WithSha256(
171
172
173
174
175
                                                       const OCTETSTRING& p__toBeSignedSecuredMessage,
                                                       const OCTETSTRING& p__certificateIssuer,
                                                       const OCTETSTRING& p__privateKey
                                                       ) {
    // Sanity checks
176
    if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) {
177
      loggers::get_instance().log("fx__signWithEcdsaBrainpoolp256r1WithSha256: Wrong parameters");
178
      return OCTETSTRING(0, nullptr);
179
180
181
182
    }
    
    // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha256 hash;
183
184
185
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeSignedSecuredMessage, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
186
    if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input)
187
      hashData2 = p__certificateIssuer;
188
189
    } else {
      hashData2 = hash.get_sha256_empty_string(); // Hash of empty string
190
    }
191
192
    loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash (Signer identifier input)=", hashData2);
193
194
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
195
    hash.generate(hashData1, hashData);
196
    loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
197
    // Calculate the signature
198
199
200
    security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__privateKey);
    OCTETSTRING r_sig;
    OCTETSTRING s_sig;
201
    if (k.sign(hashData, r_sig, s_sig) == 0) {
202
203
204
205
      OCTETSTRING os = r_sig + s_sig;
      loggers::get_instance().log_msg("r_sig= ", r_sig);
      loggers::get_instance().log_msg("s_sig= ", s_sig);
      loggers::get_instance().log_msg("sig= ", os);
206
207
208
      return os;
    }

209
    return OCTETSTRING(0, nullptr);
210
211
212
  }

  /**
213
   * \fn OCTETSTRING fx__signWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey);
Yann Garcia's avatar
Yann Garcia committed
214
   * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
215
   * \param[in] p__toBeSignedSecuredMessage The data to be signed
216
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
217
218
219
   * \param[in] p__privateKey The private key
   * \return The signature value
   */
220
  OCTETSTRING fx__signWithEcdsaBrainpoolp384r1WithSha384(
221
222
223
224
225
                                                       const OCTETSTRING& p__toBeSignedSecuredMessage,
                                                       const OCTETSTRING& p__certificateIssuer,
                                                       const OCTETSTRING& p__privateKey
                                                       ) {
    // Sanity checks
226
	    if ((p__certificateIssuer.lengthof() != 48) || (p__privateKey.lengthof() != 48)) {
227
      loggers::get_instance().log("fx__signWithEcdsaBrainpoolp384r1WithSha384: Wrong parameters");
228
      return OCTETSTRING(0, nullptr);
229
230
231
232
    }
    
    // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha384 hash;
233
234
235
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeSignedSecuredMessage, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
236
    if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input)
237
      hashData2 = p__certificateIssuer;
238
239
    } else {
      hashData2 = hash.get_sha384_empty_string(); // Hash of empty string
240
    }
241
242
    loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2);
243
244
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
245
    hash.generate(hashData1, hashData);
246
    loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
247
    // Calculate the signature
248
249
250
    security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__privateKey);
    OCTETSTRING r_sig;
    OCTETSTRING s_sig;
251
    if (k.sign(hashData, r_sig, s_sig) == 0) {
252
      OCTETSTRING os = r_sig + s_sig;
253
254
255
      loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: r_sig= ", r_sig);
      loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: s_sig= ", s_sig);
      loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: sig= ", os);
256
257
258
      return os;
    }

259
    return OCTETSTRING(0, nullptr);
260
261
262
263
  }

  /**
   * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaNistp256PublicKeyCompressed);
Yann Garcia's avatar
Yann Garcia committed
264
   * \brief Verify the signature of the specified data based on standard IEEE 1609.2
265
   * \param[in] p__toBeVerifiedData The data to be verified
266
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
267
268
269
270
271
272
273
274
   * \param[in] p__signature The signature
   * \param[in] p__ecdsaNistp256PublicKeyCompressed The compressed public key (x coordinate only)
   * \return true on success, false otherwise
   */
  BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(
                                                const OCTETSTRING& p__toBeVerifiedData,
                                                const OCTETSTRING& p__certificateIssuer,
                                                const OCTETSTRING& p__signature,
275
                                                const OCTETSTRING& p__ecdsaNistp256PublicKeyCompressed,
276
                                                const INTEGER& p__compressedMode
277
                                                ) {
278
    // Sanity checks
279
    if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyCompressed.lengthof() != 32)) {
280
281
282
283
284
285
      loggers::get_instance().log("fx__verifyWithEcdsaNistp256WithSha256: Wrong parameters");
      return FALSE;
    }

    // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha256 hash;
286
287
288
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeVerifiedData, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
289
    if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input)
290
      hashData2 = p__certificateIssuer;
291
292
    } else {
      hashData2 = hash.get_sha256_empty_string(); // Hash of empty string
293
    }
294
295
296
297
    loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash (Signer identifier input)=", hashData2);
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
298
    hash.generate(hashData1, hashData);
299
    loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
300
    // Check the signature
301
302
    security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyCompressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1);
    if (k.sign_verif(hashData, p__signature) == 0) {
303
304
305
306
307
308
      return TRUE;
    }

    return FALSE;
  }
  
Yann Garcia's avatar
Yann Garcia committed
309
310
311
312
313
314
315
316
  /**
   * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__ecdsaNistp256PublicKeyCompressed);
   * \brief Verify the signature of the specified data based on raw data
   * \param[in] p__toBeVerifiedData The data to be verified
   * \param[in] p__signature The signature
   * \param[in] p__ecdsaNistp256PublicKeyCompressed The compressed public key (x coordinate only)
   * \return true on success, false otherwise
   */
Yann Garcia's avatar
Yann Garcia committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  BOOLEAN fx__test__verifyWithEcdsaNistp256WithSha256(
                                                      const OCTETSTRING& p__toBeVerifiedData,
                                                      const OCTETSTRING& p__signature,
                                                      const OCTETSTRING& p__ecdsaNistp256PublicKeyCompressed,
                                                      const INTEGER& p__compressedMode
                                                      ) {
    // Sanity checks
    if ((p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyCompressed.lengthof() != 32)) {
      loggers::get_instance().log("fx__test__verifyWithEcdsaNistp256WithSha256: Wrong parameters");
      return FALSE;
    }

    // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha256 hash;
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeVerifiedData, hashData1);
    loggers::get_instance().log_msg("fx__test__verifyWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1);
    // Check the signature
    security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyCompressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1);
    if (k.sign_verif(hashData1, p__signature) == 0) {
      return TRUE;
    }

    return FALSE;
  }
  
343
344
  /**
   * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaNistp256PublicKeyX, const OCTETSTRING& p__ecdsaNistp256PublicKeyY);
Yann Garcia's avatar
Yann Garcia committed
345
   * \brief Verify the signature of the specified data based on standard IEEE 1609.2
346
   * \param[in] p__toBeVerifiedData The data to be verified
347
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
348
349
350
351
352
353
354
355
356
357
358
359
360
   * \param[in] p__signature The signature
   * \param[in] p__ecdsaNistp256PublicKeyX The public key (x coordinate)
   * \param[in] p__ecdsaNistp256PublicKeyY The public key (y coordinate)
   * \return true on success, false otherwise
   */
  BOOLEAN fx__verifyWithEcdsaNistp256WithSha256__1(
                                                   const OCTETSTRING& p__toBeVerifiedData,
                                                   const OCTETSTRING& p__certificateIssuer,
                                                   const OCTETSTRING& p__signature,
                                                   const OCTETSTRING& p__ecdsaNistp256PublicKeyX,
                                                   const OCTETSTRING& p__ecdsaNistp256PublicKeyY
                                                   ) {
    // Sanity checks
Yann Garcia's avatar
Yann Garcia committed
361
    if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyX.lengthof() != 32) || (p__ecdsaNistp256PublicKeyY.lengthof() != 32)) {
362
363
364
365
366
367
      loggers::get_instance().log("fx__verifyWithEcdsaNistp256WithSha256__1: Wrong parameters");
      return FALSE;
    }

    // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha256 hash;
368
369
370
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeVerifiedData, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
371
    if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input)
372
      hashData2 = p__certificateIssuer;
373
374
    } else {
      hashData2 = hash.get_sha256_empty_string(); // Hash of empty string
375
    }
376
377
378
379
    loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash (Signer identifier input)=", hashData2);
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
380
    hash.generate(hashData1, hashData);
381
    loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
382
    // Check the signature
383
    security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyX, p__ecdsaNistp256PublicKeyY);
384
    //security_ecc k(ec_elliptic_curves::nist_p_256);
385
    if (k.sign_verif(hashData, p__signature) == 0) {
386
387
388
389
390
391
392
      return TRUE;
    }

    return FALSE;
  }

  /**
393
   * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyCompressed);
Yann Garcia's avatar
Yann Garcia committed
394
   * \brief Verify the signature of the specified data based on standard IEEE 1609.2
395
   * \param[in] p__toBeVerifiedData The data to be verified
396
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
397
398
399
400
   * \param[in] p__signature The signature
   * \param[in] p__ecdsaBrainpoolp256PublicKeyCompressed The compressed public key (x coordinate only)
   * \return true on success, false otherwise
   */
401
  BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256(
402
403
404
405
406
407
408
                                                     const OCTETSTRING& p__toBeVerifiedData,
                                                     const OCTETSTRING& p__certificateIssuer,
                                                     const OCTETSTRING& p__signature,
                                                     const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyCompressed,
                                                     const INTEGER& p__compressedMode
                                                     ) {
    // Sanity checks
409
    if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaBrainpoolp256PublicKeyCompressed.lengthof() != 32)) {
410
      loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Wrong parameters");
411
412
413
414
415
      return FALSE;
    }

    // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha256 hash;
416
417
418
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeVerifiedData, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
419
    if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input)
420
      hashData2 = p__certificateIssuer;
421
422
    } else {
      hashData2 = hash.get_sha256_empty_string(); // Hash of empty string
423
    }
424
425
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash (Signer identifier input)=", hashData2);
426
427
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
428
    hash.generate(hashData1, hashData);
429
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
430
    // Check the signature
431
432
    security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__ecdsaBrainpoolp256PublicKeyCompressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1);
    if (k.sign_verif(hashData, p__signature) == 0) {
433
434
435
436
437
438
439
      return TRUE;
    }

    return FALSE;
  }

  /**
440
   * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyY);
Yann Garcia's avatar
Yann Garcia committed
441
   * \brief Verify the signature of the specified data based on standard IEEE 1609.2
442
   * \param[in] p__toBeVerifiedData The data to be verified
443
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
444
445
446
447
448
   * \param[in] p__signature The signature
   * \param[in] p__ecdsaBrainpoolp256PublicKeyX The public key (x coordinate)
   * \param[in] p__ecdsaBrainpoolp256PublicKeyY The public key (y coordinate)
   * \return true on success, false otherwise
   */
449
  BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1(
450
                                                        const OCTETSTRING& p__toBeVerifiedData,
451
                                                        const OCTETSTRING& p__certificateIssuer,
452
453
454
455
456
                                                        const OCTETSTRING& p__signature,
                                                        const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyX,
                                                        const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyY
                                                        ) {
    // Sanity checks
Yann Garcia's avatar
Yann Garcia committed
457
    if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaBrainpoolp256PublicKeyX.lengthof() != 32) || (p__ecdsaBrainpoolp256PublicKeyY.lengthof() != 32)) {
458
      loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Wrong parameters");
459
460
461
462
463
      return FALSE;
    }

    // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha256 hash;
464
465
466
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeVerifiedData, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
467
    if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input)
468
      hashData2 = p__certificateIssuer;
469
470
    } else {
      hashData2 = hash.get_sha256_empty_string(); // Hash of empty string
471
    }
472
473
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash (Signer identifier input)=", hashData2);
474
475
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
476
    hash.generate(hashData1, hashData);
477
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
478
    // Check the signature
479
480
    security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__ecdsaBrainpoolp256PublicKeyX, p__ecdsaBrainpoolp256PublicKeyY);
    if (k.sign_verif(hashData, p__signature) == 0) {
481
482
483
484
485
486
487
      return TRUE;
    }

    return FALSE;
  }

  /**
488
   * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyCompressed);
Yann Garcia's avatar
Yann Garcia committed
489
   * \brief Verify the signature of the specified data based on standard IEEE 1609.2
490
   * \param[in] p__toBeVerifiedData The data to be verified
491
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
492
493
494
495
   * \param[in] p__signature The signature
   * \param[in] p__ecdsaBrainpoolp384PublicKeyCompressed The compressed public key (x coordinate only)
   * \return true on success, false otherwise
   */
496
  BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384(
497
498
499
500
501
502
503
                                                     const OCTETSTRING& p__toBeVerifiedData,
                                                     const OCTETSTRING& p__certificateIssuer,
                                                     const OCTETSTRING& p__signature,
                                                     const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyCompressed,
                                                     const INTEGER& p__compressedMode
                                                     ) {
    // Sanity checks
504
    if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaBrainpoolp384PublicKeyCompressed.lengthof() != 48)) {
505
      loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Wrong parameters");
506
507
508
509
510
      return FALSE;
    }

    // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha384 hash;
511
512
513
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeVerifiedData, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
514
    if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input)
515
      hashData2 = p__certificateIssuer;
516
517
    } else {
      hashData2 = hash.get_sha384_empty_string(); // Hash of empty string
518
    }
519
520
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2);
521
522
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
523
    hash.generate(hashData1, hashData);
524
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
525
    // Check the signature
526
527
    security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__ecdsaBrainpoolp384PublicKeyCompressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1);
    if (k.sign_verif(hashData, p__signature) == 0) {
528
529
530
531
532
533
534
      return TRUE;
    }

    return FALSE;
  }

  /**
535
   * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY);
Yann Garcia's avatar
Yann Garcia committed
536
   * \brief Verify the signature of the specified data based on standard IEEE 1609.2
537
   * \param[in] p__toBeVerifiedData The data to be verified
538
   * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
539
540
541
542
543
   * \param[in] p__signature The signature
   * \param[in] p__ecdsaBrainpoolp384PublicKeyX The public key (x coordinate)
   * \param[in] p__ecdsaBrainpoolp384PublicKeyY The public key (y coordinate)
   * \return true on success, false otherwise
   */
544
  BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384__1(
545
                                                        const OCTETSTRING& p__toBeVerifiedData,
546
                                                        const OCTETSTRING& p__certificateIssuer,
547
548
549
550
551
                                                        const OCTETSTRING& p__signature,
                                                        const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyX,
                                                        const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY
                                                        ) {
    // Sanity checks
Yann Garcia's avatar
Yann Garcia committed
552
    if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaBrainpoolp384PublicKeyX.lengthof() != 48) || (p__ecdsaBrainpoolp384PublicKeyY.lengthof() != 48)) {
553
      loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp384r1WithSha384__1: Wrong parameters");
554
555
556
557
558
      return FALSE;
    }

    // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) )
    sha384 hash;
559
560
561
    OCTETSTRING hashData1; // Hash (Data input)
    hash.generate(p__toBeVerifiedData, hashData1);
    OCTETSTRING hashData2; // Hash (Signer identifier input)
562
    if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input)
563
      hashData2 = p__certificateIssuer;
564
565
    } else {
      hashData2 = hash.get_sha384_empty_string(); // Hash of empty string
566
    }
567
568
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1);
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2);
569
570
    hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input)
    OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) )
571
    hash.generate(hashData1, hashData);
572
    loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData);
573
    // Check the signature
574
575
    security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__ecdsaBrainpoolp384PublicKeyX, p__ecdsaBrainpoolp384PublicKeyY);
    if (k.sign_verif(hashData, p__signature) == 0) {
576
577
578
579
580
581
582
      return TRUE;
    }

    return FALSE;
  }

  /**
Yann Garcia's avatar
Yann Garcia committed
583
   * \fn OCTETSTRING fx__hmac__sha256(const OCTETSTRING& p__k, const OCTETSTRING& p__m);
584
585
586
587
588
   * \brief Generate a HMAC-SHA256 value based on the provided secret key
   * \param[in] p__k The secret key used for the HMAC calculation
   * \param[in] p__m The message
   * \return The HMAC value resized to 16-byte
   */
Yann Garcia's avatar
Yann Garcia committed
589
  OCTETSTRING fx__hmac__sha256(const OCTETSTRING& p__k, const OCTETSTRING& p__m) {
YannGarcia's avatar
YannGarcia committed
590
591
    loggers::get_instance().log_msg(">>> fx__hmac__sha256: p__k=", p__k);
    loggers::get_instance().log_msg(">>> fx__hmac__sha256: p__m=", p__m);
592
593

    hmac h(hash_algorithms::sha_256); // TODO Use ec_encryption_algorithm
594
595
    OCTETSTRING t;
    if (h.generate(p__m, p__k, t) == -1) {
Yann Garcia's avatar
Yann Garcia committed
596
      loggers::get_instance().warning("fx__hmac__sha256: Failed to generate HMAC");
597
      return OCTETSTRING(0, nullptr);
598
599
    }

YannGarcia's avatar
YannGarcia committed
600
    loggers::get_instance().log_msg("<<< fx__hmac__sha256: HMAC: ", t);
601
    return t;
602
603
604
  }

  /**
Yann Garcia's avatar
Yann Garcia committed
605
   * \fn OCTETSTRING fx__encrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt);
606
607
608
609
610
611
   * \brief Encrypt the message using AES 128 CCM algorithm
   * \param[in] p__k The symmetric encryption key
   * \param[in] p__n The initial vector, nonce vector
   * \param[in] p__pt The message to encrypt
   * \return The encrypted message concatenated to the AES 128 CCM tag
   */
Yann Garcia's avatar
Yann Garcia committed
612
613
  OCTETSTRING fx__encrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt) {
    loggers::get_instance().log(">>> fx__encrypt__aes__128__ccm__test");
614
615
    
    security_ecc ec(ec_elliptic_curves::nist_p_256);
616
617
    OCTETSTRING enc_message;
    if (ec.encrypt(encryption_algotithm::aes_128_ccm, p__k, p__n, p__pt, enc_message) == -1) {
Yann Garcia's avatar
Yann Garcia committed
618
      loggers::get_instance().warning("fx__encrypt__aes__128__ccm__test: Failed to encrypt message");
619
      return OCTETSTRING(0, nullptr);
620
    }
621
    OCTETSTRING os(enc_message + ec.tag());
Yann Garcia's avatar
Yann Garcia committed
622
    loggers::get_instance().log_msg("fx__encrypt__aes__128__ccm__test: encrypted message: ", os);
623
624
625
626

    return os;
  }
  
Yann Garcia's avatar
Yann Garcia committed
627
628
629
630
631
632
633
634
635
636
  /**
   * \fn OCTETSTRING fx__encrypt__aes__128__gcm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt);
   * \brief Encrypt the message using AES 128 GCM algorithm
   * \param[in] p__k The symmetric encryption key
   * \param[in] p__n The initial vector, nonce vector
   * \param[in] p__pt The message to encrypt
   * \return The encrypted message concatenated to the AES 128 CCM tag
   */
  OCTETSTRING fx__encrypt__aes__128__gcm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt) {
    loggers::get_instance().log(">>> fx__encrypt__aes__128__gcm__test");
637
638
639
640
    
    security_ecc ec(ec_elliptic_curves::nist_p_256);
    OCTETSTRING enc_message;
    if (ec.encrypt(encryption_algotithm::aes_128_gcm, p__k, p__n, p__pt, enc_message) == -1) {
Yann Garcia's avatar
Yann Garcia committed
641
      loggers::get_instance().warning("fx__encrypt__aes__128__gcm__test: Failed to encrypt message");
642
643
644
      return OCTETSTRING(0, nullptr);
    }
    OCTETSTRING os(enc_message + ec.tag());
Yann Garcia's avatar
Yann Garcia committed
645
    loggers::get_instance().log_msg("fx__encrypt__aes__128__gcm__test: encrypted message: ", os);
646
647
648
649

    return os;
  }
  
650
  /**
Yann Garcia's avatar
Yann Garcia committed
651
   * \fn OCTETSTRING fx__decrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__ct);
652
653
654
655
656
657
   * \brief Encrypt the message using AES 128 CCM algorithm
   * \param[in] p__k The symmetric encryption key
   * \param[in] p__n The initial vector, nonce vector
   * \param[in] p__ct The encrypted message concatenated to the AES 128 CCM tag
   * \return The original message
   */
Yann Garcia's avatar
Yann Garcia committed
658
659
660
661
  OCTETSTRING fx__decrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__ct) {
    loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__k: ", p__k);
    loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__n: ", p__n);
    loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__ct: ", p__ct);
662
663
664
    
    security_ecc ec(ec_elliptic_curves::nist_p_256);
    // Extract the tag
665
    OCTETSTRING tag(16, p__ct.lengthof() - 16 + static_cast<const unsigned char*>(p__ct));
Yann Garcia's avatar
Yann Garcia committed
666
    loggers::get_instance().log_msg("fx__decrypt__aes__128__ccm__test: tag: ", tag);
667
    // Remove the tag from the end of the encrypted message
668
    OCTETSTRING ct(p__ct.lengthof() - 16, static_cast<const unsigned char*>(p__ct));
Yann Garcia's avatar
Yann Garcia committed
669
    loggers::get_instance().log_msg("fx__decrypt__aes__128__ccm__test: ct: ", ct);
670
    
671
    OCTETSTRING message;
672
    if (ec.decrypt(encryption_algotithm::aes_128_ccm, p__k, p__n, tag, ct, message) == -1) {
Yann Garcia's avatar
Yann Garcia committed
673
      loggers::get_instance().warning("fx__decrypt__aes__128__ccm__test: Failed to decrypt message");
674
      return OCTETSTRING(0, nullptr);
675
    }
Yann Garcia's avatar
Yann Garcia committed
676
    loggers::get_instance().log_to_hexa("fx__decrypt__aes__128__ccm__test: decrypted message: ", message);
677
    
678
    return message;
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
  }
  
  /**
   * \fn OCTETSTRING fx__encryptWithEciesNistp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyX, const OCTETSTRING& p__recipientsPublicKeyY, OCTETSTRING& p__publicEphemeralKeyX, OCTETSTRING& p__publicEphemeralKeyY, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce);
   * \brief Encrypt the message using ECIES algorithm to encrypt AES 128 CCM symmetric key, as defined in IEEE Std 1609.2-2017
   * \param[in] p__toBeEncryptedSecuredMessage The message to be encrypted
   * \param[in] p__recipientsPublicKeyCompressed The Recipient's compressed public key
   * \param[in] p__compressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
   * \param[out] p__publicEphemeralKeyCompressed The public ephemeral compressed key
   * \param[out] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
   * \param[out] p__encrypted__sym__key The encrypted AES 128 symmetric key
   * \param[out] p__authentication__vector The tag of the encrypted AES 128 symmetric key
   * \param[out] p__nonce The nonce vector
   * \return The original message
   * \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
   * \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
   * \see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
   */
  // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function
698
  OCTETSTRING fx__encryptWithEciesNistp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyCompressed, const INTEGER& p__compressedMode, const OCTETSTRING& p__salt, OCTETSTRING& p__publicEphemeralKeyCompressed, INTEGER& p__ephemeralCompressedMode,OCTETSTRING& p__aes__sym__key, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce) {
699
    loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage);
700
    loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed);
701
    loggers::get_instance().log(">>> fx__encryptWithEciesNistp256WithSha256: p__compressedMode: %d", static_cast<int>(p__compressedMode));
702
    loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__salt: ", p__salt);
703
    
704
705
    // 1. Generate new Private/Public Ephemeral key
    std::unique_ptr<security_ecc> ec;
706
707
708
709
    ec.reset(new security_ecc(ec_elliptic_curves::nist_p_256));
    if (ec->generate() == -1) {
      loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to generate ephemeral keys");
      return OCTETSTRING(0, nullptr);
710
    }
711
    // 2. Generate and derive shared secret based on recipient's private keys
712
    security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__recipientsPublicKeyCompressed, (static_cast<int>(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1);
713
    if (ec->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) {
714
      loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to generate and derive secret key");
715
      return OCTETSTRING(0, nullptr);
716
    }
717
718
719
720
721
    
    // Set the AES symmetric key
    loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: AES symmetric key: ", ec->symmetric_encryption_key());
    p__aes__sym__key = ec->symmetric_encryption_key();
    loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__aes__sym__key: ", p__aes__sym__key);
722
    // Set the encrypted symmetric key
723
724
    loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: Encrypted symmetric key: ", ec->encrypted_symmetric_key());
    p__encrypted__sym__key = ec->encrypted_symmetric_key();
725
    loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key);
726
    // Set the tag of the symmetric key encryption
727
    p__authentication__vector = ec->tag();
728
    loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector);
729
    // Set ephemeral public keys
730
731
732
733
    p__publicEphemeralKeyCompressed = ec->public_key_compressed();
    loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed);
    p__ephemeralCompressedMode = (ec->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1;
    loggers::get_instance().log("fx__encryptWithEciesNistp256WithSha256: Ephemeral public compressed mode: %d: ", p__ephemeralCompressedMode);
734
    // 3. Retrieve AES 128 parameters
735
    p__nonce = ec->nonce();
736
    loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce);
737
    // 4. Encrypt the data using AES-128 CCM
738
    OCTETSTRING enc_message;
739
    if (ec->encrypt(encryption_algotithm::aes_128_ccm, ec->symmetric_encryption_key(), ec->nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) {
740
      loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to encrypt message");
741
      return OCTETSTRING(0, nullptr);
742
    }
743
    enc_message += ec->tag();
744
    loggers::get_instance().log_to_hexa("fx__encryptWithEciesNistp256WithSha256: enc message||Tag: ", enc_message);
745

746
    return enc_message;
747
  }
748

749
750
751
752
  /**
   * @desc Test function for ECIES NIST P-256 Encryption with SHA-256
   * @remark For the purpose of testing, the content of p__toBeEncryptedSecuredMessage is the AES 128 symmetric key to be encrypted
   */
753
  OCTETSTRING fx__test__encryptWithEciesNistp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__privateEphemeralKey, const OCTETSTRING& p__recipientPublicKeyX, const OCTETSTRING& p__recipientPublicKeyY, const OCTETSTRING& p__salt, OCTETSTRING& p__publicEphemeralKeyX, OCTETSTRING& p__publicEphemeralKeyY, OCTETSTRING& p__aes__sym__key, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce) {
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
    
    // 1. Generate new ephemeral Private/Public keys
    security_ecc ec(ec_elliptic_curves::nist_p_256, p__privateEphemeralKey);
    p__publicEphemeralKeyX = ec.public_key_x();
    p__publicEphemeralKeyY = ec.public_key_y();
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Vx=", p__publicEphemeralKeyX);
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Vy=", p__publicEphemeralKeyY);
    
    // 2. Generate and derive shared secret
    security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__recipientPublicKeyX, p__recipientPublicKeyY);
    ec.symmetric_encryption_key(p__toBeEncryptedSecuredMessage);
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: ", ec.encrypted_symmetric_key());
    if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) {
      loggers::get_instance().warning("fx__test__encryptWithEciesNistp256WithSha256: Failed to generate and derive secret key");
      return OCTETSTRING(0, nullptr);
    }
770
771
772
773
774
    
    // Set the AES symmetric key
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: AES symmetric key: ", ec.symmetric_encryption_key());
    p__aes__sym__key = ec.symmetric_encryption_key();
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__aes__sym__key: ", p__aes__sym__key);
775
    // Set the encrypted symmetric key
776
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Encrypted symmetric key: ", ec.encrypted_symmetric_key());
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
    p__encrypted__sym__key = ec.encrypted_symmetric_key();
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key);
    // Set the tag of the symmetric key encryption
    p__authentication__vector = ec.tag();
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector);
    // 3. Retrieve AES 128 parameters
    p__nonce = ec.nonce();
    loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce);
    // 4. Encrypt the data using AES-128 CCM
    OCTETSTRING enc_message;
    if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) {
      loggers::get_instance().warning("fx__test__encryptWithEciesNistp256WithSha256: Failed to encrypt message");
      return OCTETSTRING(0, nullptr);
    }
    enc_message += ec.tag();
    loggers::get_instance().log_to_hexa("fx__test__encryptWithEciesNistp256WithSha256: enc message||Tag: ", enc_message);
    
    return enc_message;
  }
  
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
  /**
   * \fn OCTETSTRING fx__decryptWithEciesNistp256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const OCTETSTRING& p__publicEphemeralKeyX, const OCTETSTRING& p__publicEphemeralKeyY, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& p__authentication__vector, const OCTETSTRING& p__nonce);
   * \brief Decrypt the message using ECIES algorithm to decrypt AES 128 CCM symmetric key, as defined in IEEE Std 1609.2-2017
   * \param[in] p__encryptedSecuredMessage The encrypted message
   * \param[in] p__privateEncKey The private encryption key
   * \param[in] p__publicEphemeralKeyCompressed The public ephemeral compressed key
   * \param[in] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
   * \param[in] p__encrypted__sym__key The encrypted AES 128 symmetric key
   * \param[in] p__authentication__vector The tag of the encrypted AES 128 symmetric key
   * \param[in] p__nonce The nonce vector
   * \return The original message
   * \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
   * \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
   * \see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
   */
  // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function
Yann Garcia's avatar
Yann Garcia committed
813
  OCTETSTRING fx__decryptWithEciesNistp256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const OCTETSTRING& p__publicEphemeralKeyCompressed, const INTEGER& p__ephemeralCompressedMode, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& p__authentication__vector, const OCTETSTRING& p__nonce, const OCTETSTRING& p__salt, OCTETSTRING& p__aes__sym__enc__key) {
814
815
816
817
818
819
820
    loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage);
    loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__privateEncKey: ", p__privateEncKey);
    loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__publicEphemeralKeyCompressed: ", p__publicEphemeralKeyCompressed);
    loggers::get_instance().log(">>> fx__decryptWithEciesNistp256WithSha256: p__ephemeralCompressedMode: %d", static_cast<int>(p__ephemeralCompressedMode));
    loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce);
    loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector);
    loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key);
821
    loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__salt", p__salt);
822

823
    // 1. Create security_ecc instance based on recipient's private key
824
825
    security_ecc ec(ec_elliptic_curves::nist_p_256, p__privateEncKey);
    security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__publicEphemeralKeyCompressed, (static_cast<int>(p__ephemeralCompressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1);
826
    
827
828
    // 2. Generate the shared secret value based on public ephemeral keys will be required
    if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__encrypted__sym__key, p__nonce, p__authentication__vector, p__salt) == -1) {
829
      loggers::get_instance().warning("fx__decryptWithEciesNistp256WithSha256: Failed to generate shared secret");
830
      return OCTETSTRING(0, nullptr);
831
832
833
    }
    
    // Decrypt the message
834
835
    OCTETSTRING enc_message(p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof(), static_cast<const unsigned char*>(p__encryptedSecuredMessage)); // Extract the encrypted message
    loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: enc_message: ", enc_message); // Extract the ctag value
836
    OCTETSTRING tag(ec.tag().lengthof(), static_cast<const unsigned char*>(p__encryptedSecuredMessage) + p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof());
837
838
    loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: tag: ", tag);
    OCTETSTRING message;
839
840
    if (ec.decrypt(tag, enc_message, message) == -1) {
      loggers::get_instance().warning("fx__decryptWithEciesNistp256WithSha256: Failed to generate shared secret");
841
      return OCTETSTRING(0, nullptr);
842
    }
843
    loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: dec message: ", message);
Yann Garcia's avatar
Yann Garcia committed
844
845
    p__aes__sym__enc__key = ec.symmetric_encryption_key();
    loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: AES 128 encryption key: ", p__aes__sym__enc__key);
846
    
847
    return message;
848
849
  }
  
850
851
852
853
854
  OCTETSTRING fx__encryptWithEciesBrainpoolp256r1WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyCompressed, const INTEGER& p__compressedMode, const OCTETSTRING& p__salt, OCTETSTRING& p__publicEphemeralKeyCompressed, INTEGER& p__ephemeralCompressedMode,OCTETSTRING& p__aes__sym__key, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce) {
    loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage);
    loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed);
    loggers::get_instance().log(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__compressedMode: %d", static_cast<int>(p__compressedMode));
    loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__salt: ", p__salt);
855
856
857
    
    // 1. Generate new Private/Public Ephemeral key
    std::unique_ptr<security_ecc> ec;
858
859
860
861
    ec.reset(new security_ecc(ec_elliptic_curves::brainpool_p_256_r1));
    if (ec->generate() == -1) {
      loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate ephemeral keys");
      return OCTETSTRING(0, nullptr);
862
    }
863
    // 2. Generate and derive shared secret based on recipient's private keys
864
    security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientsPublicKeyCompressed, (static_cast<int>(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1);
865
    if (ec->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) {
866
      loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate and derive secret key");
867
      return OCTETSTRING(0, nullptr);
868
    }
869
    
870
    // Set the AES symmetric key
871
    loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: AES symmetric key: ", ec->symmetric_encryption_key());
872
    p__aes__sym__key = ec->symmetric_encryption_key();
873
    loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__aes__sym__key: ", p__aes__sym__key);
874
    // Set the encrypted symmetric key
875
    loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: Encrypted symmetric key: ", ec->encrypted_symmetric_key());
876
    p__encrypted__sym__key = ec->encrypted_symmetric_key();
877
    loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key);
878
    // Set the tag of the symmetric key encryption
879
    p__authentication__vector = ec->tag();
880
    loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__authentication__vector: ", p__authentication__vector);
881
    // Set ephemeral public keys
882
    p__publicEphemeralKeyCompressed = ec->public_key_compressed();
883
    loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed);
884
    p__ephemeralCompressedMode = (ec->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1;
885
    loggers::get_instance().log("fx__encryptWithEciesBrainpoolp256r1WithSha256: Ephemeral public compressed mode: %d: ", p__ephemeralCompressedMode);
886
    // 3. Retrieve AES 128 parameters
887
    p__nonce = ec->nonce();
888
    loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__nonce: ", p__nonce);
889
    // 4. Encrypt the data using AES-128 CCM
890
    OCTETSTRING enc_message;
891
    if (ec->encrypt(encryption_algotithm::aes_128_ccm, ec->symmetric_encryption_key(), ec->nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) {
892
      loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to encrypt message");
893
      return OCTETSTRING(0, nullptr);
894
    }
895
    enc_message += ec->tag();
896
    loggers::get_instance().log_to_hexa("fx__encryptWithEciesBrainpoolp256r1WithSha256: enc message||Tag: ", enc_message);
897

898
    return enc_message;
899
900
  }

901
902
903
904
  /**
   * @desc Test function for ECIES BRAINPOOL P-256r1 Encryption with SHA-256
   * @remark For the purpose of testing, the content of p__toBeEncryptedSecuredMessage is the AES 128 symmetric key to be encrypted
   */
905
  OCTETSTRING fx__test__encryptWithEciesBrainpoolp256r1WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__privateEphemeralKey, const OCTETSTRING& p__recipientPublicKeyX, const OCTETSTRING& p__recipientPublicKeyY, const OCTETSTRING& p__salt, OCTETSTRING& p__publicEphemeralKeyX, OCTETSTRING& p__publicEphemeralKeyY, OCTETSTRING& p__aes__sym__key, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce) {
906
907
908
909
910
    
    // 1. Generate new ephemeral Private/Public keys
    security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1, p__privateEphemeralKey);
    p__publicEphemeralKeyX = ec.public_key_x();
    p__publicEphemeralKeyY = ec.public_key_y();
911
912
    loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Vx=", p__publicEphemeralKeyX);
    loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Vy=", p__publicEphemeralKeyY);
913
914
915
916
    
    // 2. Generate and derive shared secret
    security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientPublicKeyX, p__recipientPublicKeyY);
    ec.symmetric_encryption_key(p__toBeEncryptedSecuredMessage);
917
    loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: ", ec.encrypted_symmetric_key());
918
    if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) {
919
      loggers::get_instance().warning("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate and derive secret key");
920
921
922
923
      return OCTETSTRING(0, nullptr);
    }
    
    // Set the AES symmetric key
924
    loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: AES symmetric key: ", ec.symmetric_encryption_key());
925
    p__aes__sym__key = ec.symmetric_encryption_key();
926
    loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__aes__sym__key: ", p__aes__sym__key);
927
    // Set the encrypted symmetric key