security_libcrypto.c
Go to the documentation of this file.
1 
9 #include "security_libcrypto.h"
10 #include "base64.h"
11 #include "string_util.h"
12 #include "mcl_core/mcl_assert.h"
13 #include "mcl_core/mcl_memory.h"
14 #include <openssl/bn.h>
15 #include <openssl/bio.h>
16 #include <openssl/pem.h>
17 #include <openssl/rsa.h>
18 #include <openssl/md5.h>
19 #include <openssl/sha.h>
20 #include <openssl/crypto.h>
21 #include <openssl/rand.h>
22 
23 #define KEY_LENGTH_BITS 3072
24 
25 // This function is used for base64 encoding a big number such as RSA modulus, public exponent and private exponent.
26 static mcl_error_t _base64_encode_big_number(const BIGNUM *big_number, char **encoded);
27 
28 // This function is used to get the public key in PEM format from OpenSSL RSA structure.
29 static mcl_error_t _get_rsa_public_key(RSA *rsa, char **public_key);
30 
31 // This function is used to get the private key in PEM format from OpenSSL RSA structure.
32 static mcl_error_t _get_rsa_private_key(RSA *rsa, char **private_key);
33 
34 // Memory function wrappers for OpenSSL.
35 static void *_libcrypto_malloc(size_t size, const char *file, int line);
36 static void *_libcrypto_realloc(void *p, size_t size, const char *file, int line);
37 static void _libcrypto_free(void *p, const char *file, int line);
38 
40 {
41  mcl_error_t code;
42 
43  MCL_DEBUG_ENTRY("void");
44 
45  // Set memory functions.
46  if (1 == CRYPTO_set_mem_functions(_libcrypto_malloc, _libcrypto_realloc, _libcrypto_free))
47  {
48  code = MCL_OK;
49  }
50  else
51  {
52  code = MCL_FAIL;
53  }
54 
55  MCL_DEBUG_LEAVE("retVal = <%d>", code);
56  return code;
57 }
58 
59 mcl_error_t security_hash_sha256(const mcl_uint8_t *data, mcl_size_t data_size, mcl_uint8_t **hash, mcl_size_t *hash_size)
60 {
61  MCL_DEBUG_ENTRY("const mcl_uint8_t *data = <%p>, mcl_size_t data_size = <%u>, mcl_uint8_t **hash = <%p>, mcl_size_t *hash_size = <%p>",
62  data, data_size, hash, hash_size);
63 
64  // Set hash size to zero.
65  *hash_size = 0;
66 
67  // Allocate memory to store SHA256 result.
68  *hash = MCL_CALLOC(1, SHA256_DIGEST_LENGTH);
69  MCL_ASSERT_CODE_MESSAGE(MCL_NULL != *hash, MCL_OUT_OF_MEMORY, "Memory allocation for SHA256 failed!");
70 
71  *hash_size = SHA256_DIGEST_LENGTH;
72 
73  // Perform SHA256 calculation.
74  MCL_DEBUG("Calculating SHA256 with OpenSSL.");
75  SHA256(data, data_size, *hash);
76 
77  MCL_DEBUG("Calculated SHA256 *hash = <%p>, hash_size = <%u>", *hash, hash_size);
78  MCL_DEBUG_LEAVE("retVal = <%d>", MCL_OK);
79  return MCL_OK;
80 }
81 
82 mcl_error_t security_rsa_sign(char *rsa_key, char *data, mcl_size_t data_size, mcl_uint8_t **signature, mcl_size_t *signature_size)
83 {
84  mcl_error_t code = MCL_OK;
85  RSA *rsa = MCL_NULL;
86  unsigned int sign_length = 0;
87  mcl_uint8_t *hash = MCL_NULL;
88  mcl_size_t hash_size = 0;
89  mcl_bool_t ok;
90  mcl_size_t length;
91  BIO *bio;
92 
93  MCL_DEBUG_ENTRY("char *rsa_key = <%p>, char *data = <%p>, mcl_size_t data_size = <%u>, mcl_uint8_t **signature = <%p>, mcl_size_t *signature_size = <%p>",
94  rsa_key, data, data_size, signature, signature_size);
95 
96  length = string_util_strlen(rsa_key);
97  bio = BIO_new_mem_buf(rsa_key, (int) length);
98  MCL_ASSERT_CODE_MESSAGE(MCL_NULL != bio, MCL_OUT_OF_MEMORY, "Memory can not be allocated for BIO.");
99 
100  rsa = PEM_read_bio_RSAPrivateKey(bio, &rsa, 0, MCL_NULL);
101  MCL_ASSERT_STATEMENT_CODE_MESSAGE(MCL_NULL != rsa, BIO_free(bio), MCL_FAIL, "RSA structure can not be generated.");
102 
103  ok = (MCL_NULL != (*signature = MCL_MALLOC(RSA_size(rsa))));
104  ok = (MCL_TRUE == ok) && (MCL_OK == security_hash_sha256((mcl_uint8_t *)data, data_size, &hash, &hash_size));
105  ok = (MCL_TRUE == ok) && (1 == RSA_sign(NID_sha256, hash, (unsigned int) hash_size, *signature, &sign_length, rsa));
106  *signature_size = sign_length;
107 
108  if (MCL_FALSE == ok)
109  {
110  MCL_FREE(*signature);
111  code = MCL_FAIL;
112  }
113 
114  MCL_FREE(hash);
115  RSA_free(rsa);
116  BIO_free(bio);
117 
118  MCL_DEBUG_LEAVE("retVal = <%d>", code);
119  return code;
120 }
121 
122 mcl_error_t security_generate_rsa_key(char **public_key, char **private_key)
123 {
124  RSA * rsa;
125  BIGNUM *exponent = MCL_NULL;
126  int result = 0;
127  mcl_error_t code = MCL_FAIL;
128 
129  MCL_DEBUG_ENTRY("char **public_key = <%p>, char **private_key = <%p>", public_key, private_key);
130 
131  // Allocate for RSA structure.
132  rsa = RSA_new();
133  MCL_ASSERT_CODE_MESSAGE(MCL_NULL != rsa, MCL_OUT_OF_MEMORY, "OpenSSL RSA structure can not be allocated.");
134 
135  // Allocate for the public exponent (e).
136  exponent = BN_new();
137  MCL_ASSERT_STATEMENT_CODE_MESSAGE(MCL_NULL != exponent, RSA_free(rsa), MCL_OUT_OF_MEMORY, "OpenSSL big number for exponent can not be allocated.");
138 
139  // Set the value of public exponent.
140  BN_set_word(exponent, RSA_F4);
141 
142  // Generate RSA structure containing public/private key pair.
143  result = RSA_generate_key_ex(rsa, KEY_LENGTH_BITS, exponent, MCL_NULL);
144 
145  // Free public exponent.
146  BN_free(exponent);
147 
148  // Get private key.
149  if (0 != result)
150  {
151  code = _get_rsa_private_key(rsa, private_key);
152  }
153 
154  // Get public key.
155  if (MCL_OK == code)
156  {
157  code = _get_rsa_public_key(rsa, public_key);
158  }
159 
160  if (MCL_OK != code)
161  {
162  MCL_FREE(*private_key);
163  MCL_FREE(*public_key);
164  }
165 
166  RSA_free(rsa);
167 
168  MCL_DEBUG_LEAVE("retVal = <%d>", code);
169  return code;
170 }
171 
172 mcl_error_t security_rsa_get_modulus_and_exponent(char *public_key, char **modulus, char **exponent)
173 {
174  mcl_error_t code;
175  RSA *rsa = MCL_NULL;
176  mcl_size_t length;
177  BIO *bio;
178  const BIGNUM *n;
179  const BIGNUM *e;
180 
181  MCL_DEBUG_ENTRY("char *public_key = <%s>, char **modulus = <%p>, char **exponent = <%p>", public_key, modulus, exponent);
182 
183  length = string_util_strlen(public_key);
184  bio = BIO_new_mem_buf(public_key, (int) length);
185  MCL_ASSERT_CODE_MESSAGE(MCL_NULL != bio, MCL_OUT_OF_MEMORY, "Memory can not be allocated for BIO.");
186 
187  rsa = PEM_read_bio_RSA_PUBKEY(bio, &rsa, 0, MCL_NULL);
188  MCL_ASSERT_STATEMENT_CODE_MESSAGE(MCL_NULL != rsa, BIO_free(bio), MCL_FAIL, "RSA structure can not be generated.");
189 
190  // Get modulus and exponent.
191  RSA_get0_key(rsa, &n, &e, MCL_NULL);
192 
193  code = _base64_encode_big_number(n, modulus);
194 
195  if (MCL_OK == code)
196  {
197  code = _base64_encode_big_number(e, exponent);
198  }
199 
200  if (MCL_OK != code)
201  {
202  MCL_FREE(*modulus);
203  MCL_FREE(*exponent);
204  }
205 
206  RSA_free(rsa);
207  BIO_free(bio);
208 
209  MCL_DEBUG_LEAVE("retVal = <%d>", code);
210  return code;
211 }
212 
214 {
215  mcl_error_t code = MCL_FAIL;
216 
217  MCL_DEBUG_ENTRY("unsigned char *buffer = <%p>, mcl_size_t size = <%u>", buffer, size);
218 
219  if (1 == RAND_bytes(buffer, (int) size))
220  {
221  code = MCL_OK;
222  }
223 
224  MCL_DEBUG_LEAVE("retVal = <%d>", code);
225  return code;
226 }
227 
228 static mcl_error_t _base64_encode_big_number(const BIGNUM *big_number, char **encoded)
229 {
230  mcl_error_t code;
231  int binary_length;
232  char *binary_encoded = MCL_NULL;
233  mcl_uint8_t *binary;
234 
235  MCL_DEBUG_ENTRY("const BIGNUM *big_number = <%p>, char **encoded = <%p>", big_number, encoded);
236 
237  binary = MCL_MALLOC(BN_num_bytes(big_number));
239 
240  binary_length = BN_bn2bin(big_number, binary);
241  code = base64_url_encode(binary, binary_length, &binary_encoded);
242 
243  if (MCL_OK == code)
244  {
245  *encoded = binary_encoded;
246  }
247 
248  MCL_FREE(binary);
249 
250  MCL_DEBUG_LEAVE("retVal = <%d>", code);
251  return code;
252 }
253 
254 static mcl_error_t _get_rsa_private_key(RSA *rsa, char **private_key)
255 {
256  mcl_error_t code = MCL_OK;
257  BIO *bio;
258  int key_length = 0;
259 
260  MCL_DEBUG_ENTRY("RSA *rsa = <%p>, char **private_key = <%p>", rsa, private_key);
261 
262  bio = BIO_new(BIO_s_mem());
263  MCL_ASSERT_CODE_MESSAGE(MCL_NULL != bio, MCL_OUT_OF_MEMORY, "Memory can not allocated for BIO.");
264 
265  if (0 == PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, NULL, NULL))
266  {
267  BIO_free_all(bio);
268  MCL_ERROR_RETURN(MCL_FAIL, "Private key can not be written from RSA struct to BIO.");
269  }
270 
271  key_length = BIO_pending(bio);
272 
273  *private_key = MCL_MALLOC(key_length + 1);
274  MCL_ASSERT_STATEMENT_CODE_MESSAGE(MCL_NULL != *private_key, BIO_free_all(bio), MCL_OUT_OF_MEMORY, "Memory can not be allocated for private key.");
275 
276  if (key_length != BIO_read(bio, *private_key, key_length))
277  {
278  MCL_DEBUG("Private key can not be read from BIO.");
279  code = MCL_FAIL;
280  MCL_FREE(*private_key);
281  }
282  else
283  {
284  (*private_key)[key_length] = MCL_NULL_CHAR;
285  }
286 
287  BIO_free_all(bio);
288 
289  MCL_DEBUG_LEAVE("retVal = <%d>", code);
290  return code;
291 }
292 
293 static mcl_error_t _get_rsa_public_key(RSA *rsa, char **public_key)
294 {
295  mcl_error_t code = MCL_OK;
296  BIO *bio;
297  int key_length = 0;
298 
299  MCL_DEBUG_ENTRY("RSA *rsa = <%p>, char **public_key = <%p>", rsa, public_key);
300 
301  bio = BIO_new(BIO_s_mem());
302  MCL_ASSERT_CODE_MESSAGE(MCL_NULL != bio, MCL_OUT_OF_MEMORY, "Memory can not allocated for BIO.");
303 
304  if (0 == PEM_write_bio_RSA_PUBKEY(bio, rsa))
305  {
306  BIO_free_all(bio);
307  MCL_ERROR_RETURN(MCL_FAIL, "Public key can not be written from RSA struct to BIO.");
308  }
309 
310  key_length = BIO_pending(bio);
311 
312  *public_key = MCL_MALLOC(key_length + 1);
313  MCL_ASSERT_STATEMENT_CODE_MESSAGE(MCL_NULL != *public_key, BIO_free_all(bio), MCL_OUT_OF_MEMORY, "Memory can not be allocated for public key.");
314 
315  if (key_length != BIO_read(bio, *public_key, key_length))
316  {
317  MCL_DEBUG("Public key can not be read from BIO.");
318  code = MCL_FAIL;
319  MCL_FREE(*public_key);
320  }
321  else
322  {
323  (*public_key)[key_length] = MCL_NULL_CHAR;
324  }
325 
326  BIO_free_all(bio);
327 
328  MCL_DEBUG_LEAVE("retVal = <%d>", code);
329  return code;
330 }
331 
332 static void *_libcrypto_malloc(size_t size, const char *file, int line)
333 {
334  void *p = MCL_NULL;
335 
336  MCL_VERBOSE_ENTRY("size_t size = <%lu>, const char *file = <%s>, int line = <%d>", size, file, line);
337 
338 #if !MCL_LOG_ENABLED_COMPILE_TIME(MCL_LOG_LEVEL_VERBOSE)
339  // Unused parameters.
340  (void) file;
341  (void) line;
342 #endif
343 
344  p = mcl_memory_malloc(size);
345 
346  MCL_VERBOSE_LEAVE("retVal = <%p>", p);
347  return p;
348 }
349 
350 static void *_libcrypto_realloc(void *p, size_t size, const char *file, int line)
351 {
352  void *memory_reallocated;
353 
354  MCL_VERBOSE_ENTRY("void *p = <%p>, size_t size = <%lu>, const char *file = <%s>, int line = <%d>", p, size, file, line);
355 
356 #if !MCL_LOG_ENABLED_COMPILE_TIME(MCL_LOG_LEVEL_VERBOSE)
357  // Unused parameters.
358  (void) file;
359  (void) line;
360 #endif
361 
362  memory_reallocated = mcl_memory_realloc(p, size);
363 
364  MCL_VERBOSE_LEAVE("retVal = <%p>", memory_reallocated);
365  return memory_reallocated;
366 }
367 
368 static void _libcrypto_free(void *p, const char *file, int line)
369 {
370  MCL_VERBOSE_ENTRY("void *p = <%p>, const char *file = <%s>, int line = <%d>", p, file, line);
371 
372 #if !MCL_LOG_ENABLED_COMPILE_TIME(MCL_LOG_LEVEL_VERBOSE)
373  // Unused parameters.
374  (void) file;
375  (void) line;
376 #endif
377 
378  mcl_memory_free(p);
379 
380  MCL_VERBOSE_LEAVE("retVal = <void>");
381 }
size_t mcl_size_t
Assert module header file.
mcl_error_t security_rsa_sign(char *rsa_key, char *data, mcl_size_t data_size, mcl_uint8_t **signature, mcl_size_t *signature_size)
Success.
#define SHA256_DIGEST_LENGTH
#define MCL_DEBUG(...)
Definition: mcl_log_util.h:114
#define MCL_CALLOC(count, bytes)
Definition: mcl_memory.h:56
mcl_int32_t mcl_error_t
Security libcrypto module header file.
#define MCL_DEBUG_ENTRY(...)
Definition: mcl_log_util.h:115
#define MCL_FALSE
String utility module header file.
MCL_CORE_EXPORT void * mcl_memory_realloc(void *p, mcl_size_t bytes)
Definition: memory.c:34
static mcl_error_t _base64_encode_big_number(const BIGNUM *big_number, char **encoded)
#define MCL_ASSERT_CODE_MESSAGE(condition, return_code,...)
Definition: mcl_assert.h:77
#define MCL_NULL
static void * _libcrypto_realloc(void *p, size_t size, const char *file, int line)
#define MCL_VERBOSE_LEAVE(...)
Definition: mcl_log_util.h:104
mcl_error_t security_rsa_get_modulus_and_exponent(char *public_key, char **modulus, char **exponent)
#define MCL_FREE(p)
Definition: mcl_memory.h:59
mcl_error_t security_initialize(void)
mcl_error_t security_generate_random_bytes(unsigned char *buffer, mcl_size_t size)
MCL_CORE_EXPORT void mcl_memory_free(void *p)
Definition: memory.c:45
uint8_t mcl_uint8_t
#define MCL_ASSERT_STATEMENT_CODE_MESSAGE(condition, statement, return_code,...)
Definition: mcl_assert.h:93
mcl_error_t base64_url_encode(const mcl_uint8_t *data, mcl_size_t data_size, char **encoded_data)
Definition: base64.c:131
static void _libcrypto_free(void *p, const char *file, int line)
#define MCL_ASSERT_CODE(condition, return_code)
Definition: mcl_assert.h:69
#define MCL_ERROR_RETURN(return_value,...)
Definition: mcl_assert.h:26
Base64 module header file.
static mcl_error_t _get_rsa_public_key(RSA *rsa, char **public_key)
static mcl_error_t _get_rsa_private_key(RSA *rsa, char **private_key)
mcl_uint8_t mcl_bool_t
mcl_error_t security_generate_rsa_key(char **public_key, char **private_key)
#define KEY_LENGTH_BITS
Memory allocation fail.
mcl_error_t security_hash_sha256(const mcl_uint8_t *data, mcl_size_t data_size, mcl_uint8_t **hash, mcl_size_t *hash_size)
#define MCL_MALLOC(bytes)
Definition: mcl_memory.h:54
#define MCL_DEBUG_LEAVE(...)
Definition: mcl_log_util.h:116
#define MCL_TRUE
MCL_CORE_EXPORT void * mcl_memory_malloc(mcl_size_t size)
Definition: memory.c:14
#define MCL_VERBOSE_ENTRY(...)
Definition: mcl_log_util.h:103
Internal failure in MCL.
mcl_size_t string_util_strlen(const char *buffer)
Definition: string_util.c:35
#define MCL_NULL_CHAR
static void * _libcrypto_malloc(size_t size, const char *file, int line)
Memory module interface header file.