]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
CryptoPkg: Add BigNum support
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Bn / CryptBn.c
1 /** @file Big number API implementation based on OpenSSL
2
3 Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 **/
7
8 #include "InternalCryptLib.h"
9 #include <openssl/bn.h>
10
11 /**
12 Allocate new Big Number.
13
14 @retval New BigNum opaque structure or NULL on failure.
15 **/
16 VOID *
17 EFIAPI
18 BigNumInit (
19 VOID
20 )
21 {
22 return BN_new ();
23 }
24
25 /**
26 Allocate new Big Number and assign the provided value to it.
27
28 @param[in] Buf Big endian encoded buffer.
29 @param[in] Len Buffer length.
30
31 @retval New BigNum opaque structure or NULL on failure.
32 **/
33 VOID *
34 EFIAPI
35 BigNumFromBin (
36 IN CONST UINT8 *Buf,
37 IN UINTN Len
38 )
39 {
40 return BN_bin2bn (Buf, (INT32)Len, NULL);
41 }
42
43 /**
44 Convert the absolute value of Bn into big-endian form and store it at Buf.
45 The Buf array should have at least BigNumBytes() in it.
46
47 @param[in] Bn Big number to convert.
48 @param[out] Buf Output buffer.
49
50 @retval The length of the big-endian number placed at Buf or -1 on error.
51 **/
52 INTN
53 EFIAPI
54 BigNumToBin (
55 IN CONST VOID *Bn,
56 OUT UINT8 *Buf
57 )
58 {
59 return BN_bn2bin (Bn, Buf);
60 }
61
62 /**
63 Free the Big Number.
64
65 @param[in] Bn Big number to free.
66 @param[in] Clear TRUE if the buffer should be cleared.
67 **/
68 VOID
69 EFIAPI
70 BigNumFree (
71 IN VOID *Bn,
72 IN BOOLEAN Clear
73 )
74 {
75 if (Clear) {
76 BN_clear_free (Bn);
77 } else {
78 BN_free (Bn);
79 }
80 }
81
82 /**
83 Calculate the sum of two Big Numbers.
84 Please note, all "out" Big number arguments should be properly initialized
85 by calling to BigNumInit() or BigNumFromBin() functions.
86
87 @param[in] BnA Big number.
88 @param[in] BnB Big number.
89 @param[out] BnRes The result of BnA + BnB.
90
91 @retval TRUE On success.
92 @retval FALSE Otherwise.
93 **/
94 BOOLEAN
95 EFIAPI
96 BigNumAdd (
97 IN CONST VOID *BnA,
98 IN CONST VOID *BnB,
99 OUT VOID *BnRes
100 )
101 {
102 return (BOOLEAN)BN_add (BnRes, BnA, BnB);
103 }
104
105 /**
106 Subtract two Big Numbers.
107 Please note, all "out" Big number arguments should be properly initialized
108 by calling to BigNumInit() or BigNumFromBin() functions.
109
110 @param[in] BnA Big number.
111 @param[in] BnB Big number.
112 @param[out] BnRes The result of BnA - BnB.
113
114 @retval TRUE On success.
115 @retval FALSE Otherwise.
116 **/
117 BOOLEAN
118 EFIAPI
119 BigNumSub (
120 IN CONST VOID *BnA,
121 IN CONST VOID *BnB,
122 OUT VOID *BnRes
123 )
124 {
125 return (BOOLEAN)BN_sub (BnRes, BnA, BnB);
126 }
127
128 /**
129 Calculate remainder: BnRes = BnA % BnB.
130 Please note, all "out" Big number arguments should be properly initialized
131 by calling to BigNumInit() or BigNumFromBin() functions.
132
133 @param[in] BnA Big number.
134 @param[in] BnB Big number.
135 @param[out] BnRes The result of BnA % BnB.
136
137 @retval TRUE On success.
138 @retval FALSE Otherwise.
139 **/
140 BOOLEAN
141 EFIAPI
142 BigNumMod (
143 IN CONST VOID *BnA,
144 IN CONST VOID *BnB,
145 OUT VOID *BnRes
146 )
147 {
148 BOOLEAN RetVal;
149 BN_CTX *Ctx;
150
151 Ctx = BN_CTX_new ();
152 if (Ctx == NULL) {
153 return FALSE;
154 }
155
156 RetVal = (BOOLEAN)BN_mod (BnRes, BnA, BnB, Ctx);
157 BN_CTX_free (Ctx);
158
159 return RetVal;
160 }
161
162 /**
163 Compute BnA to the BnP-th power modulo BnM.
164 Please note, all "out" Big number arguments should be properly initialized
165 by calling to BigNumInit() or BigNumFromBin() functions.
166
167 @param[in] BnA Big number.
168 @param[in] BnP Big number (power).
169 @param[in] BnM Big number (modulo).
170 @param[out] BnRes The result of (BnA ^ BnP) % BnM.
171
172 @retval TRUE On success.
173 @retval FALSE Otherwise.
174 **/
175 BOOLEAN
176 EFIAPI
177 BigNumExpMod (
178 IN CONST VOID *BnA,
179 IN CONST VOID *BnP,
180 IN CONST VOID *BnM,
181 OUT VOID *BnRes
182 )
183 {
184 BOOLEAN RetVal;
185 BN_CTX *Ctx;
186
187 Ctx = BN_CTX_new ();
188 if (Ctx == NULL) {
189 return FALSE;
190 }
191
192 RetVal = (BOOLEAN)BN_mod_exp (BnRes, BnA, BnP, BnM, Ctx);
193
194 BN_CTX_free (Ctx);
195 return RetVal;
196 }
197
198 /**
199 Compute BnA inverse modulo BnM.
200 Please note, all "out" Big number arguments should be properly initialized
201 by calling to BigNumInit() or BigNumFromBin() functions.
202
203 @param[in] BnA Big number.
204 @param[in] BnM Big number (modulo).
205 @param[out] BnRes The result, such that (BnA * BnRes) % BnM == 1.
206
207 @retval TRUE On success.
208 @retval FALSE Otherwise.
209 **/
210 BOOLEAN
211 EFIAPI
212 BigNumInverseMod (
213 IN CONST VOID *BnA,
214 IN CONST VOID *BnM,
215 OUT VOID *BnRes
216 )
217 {
218 BOOLEAN RetVal;
219 BN_CTX *Ctx;
220
221 Ctx = BN_CTX_new ();
222 if (Ctx == NULL) {
223 return FALSE;
224 }
225
226 RetVal = FALSE;
227 if (BN_mod_inverse (BnRes, BnA, BnM, Ctx) != NULL) {
228 RetVal = TRUE;
229 }
230
231 BN_CTX_free (Ctx);
232 return RetVal;
233 }
234
235 /**
236 Divide two Big Numbers.
237 Please note, all "out" Big number arguments should be properly initialized
238 by calling to BigNumInit() or BigNumFromBin() functions.
239
240 @param[in] BnA Big number.
241 @param[in] BnB Big number.
242 @param[out] BnRes The result, such that BnA / BnB.
243
244 @retval TRUE On success.
245 @retval FALSE Otherwise.
246 **/
247 BOOLEAN
248 EFIAPI
249 BigNumDiv (
250 IN CONST VOID *BnA,
251 IN CONST VOID *BnB,
252 OUT VOID *BnRes
253 )
254 {
255 BOOLEAN RetVal;
256 BN_CTX *Ctx;
257
258 Ctx = BN_CTX_new ();
259 if (Ctx == NULL) {
260 return FALSE;
261 }
262
263 RetVal = (BOOLEAN)BN_div (BnRes, NULL, BnA, BnB, Ctx);
264 BN_CTX_free (Ctx);
265
266 return RetVal;
267 }
268
269 /**
270 Multiply two Big Numbers modulo BnM.
271 Please note, all "out" Big number arguments should be properly initialized
272 by calling to BigNumInit() or BigNumFromBin() functions.
273
274 @param[in] BnA Big number.
275 @param[in] BnB Big number.
276 @param[in] BnM Big number (modulo).
277 @param[out] BnRes The result, such that (BnA * BnB) % BnM.
278
279 @retval TRUE On success.
280 @retval FALSE Otherwise.
281 **/
282 BOOLEAN
283 EFIAPI
284 BigNumMulMod (
285 IN CONST VOID *BnA,
286 IN CONST VOID *BnB,
287 IN CONST VOID *BnM,
288 OUT VOID *BnRes
289 )
290 {
291 BOOLEAN RetVal;
292 BN_CTX *Ctx;
293
294 Ctx = BN_CTX_new ();
295 if (Ctx == NULL) {
296 return FALSE;
297 }
298
299 RetVal = (BOOLEAN)BN_mod_mul (BnRes, BnA, BnB, BnM, Ctx);
300 BN_CTX_free (Ctx);
301
302 return RetVal;
303 }
304
305 /**
306 Compare two Big Numbers.
307
308 @param[in] BnA Big number.
309 @param[in] BnB Big number.
310
311 @retval 0 BnA == BnB.
312 @retval 1 BnA > BnB.
313 @retval -1 BnA < BnB.
314 **/
315 INTN
316 EFIAPI
317 BigNumCmp (
318 IN CONST VOID *BnA,
319 IN CONST VOID *BnB
320 )
321 {
322 return BN_cmp (BnA, BnB);
323 }
324
325 /**
326 Get number of bits in Bn.
327
328 @param[in] Bn Big number.
329
330 @retval Number of bits.
331 **/
332 UINTN
333 EFIAPI
334 BigNumBits (
335 IN CONST VOID *Bn
336 )
337 {
338 return BN_num_bits (Bn);
339 }
340
341 /**
342 Get number of bytes in Bn.
343
344 @param[in] Bn Big number.
345
346 @retval Number of bytes.
347 **/
348 UINTN
349 EFIAPI
350 BigNumBytes (
351 IN CONST VOID *Bn
352 )
353 {
354 return BN_num_bytes (Bn);
355 }
356
357 /**
358 Checks if Big Number equals to the given Num.
359
360 @param[in] Bn Big number.
361 @param[in] Num Number.
362
363 @retval TRUE iff Bn == Num.
364 @retval FALSE otherwise.
365 **/
366 BOOLEAN
367 EFIAPI
368 BigNumIsWord (
369 IN CONST VOID *Bn,
370 IN UINTN Num
371 )
372 {
373 return (BOOLEAN)BN_is_word (Bn, Num);
374 }
375
376 /**
377 Checks if Big Number is odd.
378
379 @param[in] Bn Big number.
380
381 @retval TRUE Bn is odd (Bn % 2 == 1).
382 @retval FALSE otherwise.
383 **/
384 BOOLEAN
385 EFIAPI
386 BigNumIsOdd (
387 IN CONST VOID *Bn
388 )
389 {
390 return (BOOLEAN)BN_is_odd (Bn);
391 }
392
393 /**
394 Copy Big number.
395
396 @param[out] BnDst Destination.
397 @param[in] BnSrc Source.
398
399 @retval BnDst on success.
400 @retval NULL otherwise.
401 **/
402 VOID *
403 EFIAPI
404 BigNumCopy (
405 OUT VOID *BnDst,
406 IN CONST VOID *BnSrc
407 )
408 {
409 return BN_copy (BnDst, BnSrc);
410 }
411
412 /**
413 Get constant Big number with value of "1".
414 This may be used to save expensive allocations.
415
416 @retval Big Number with value of 1.
417 **/
418 CONST VOID *
419 EFIAPI
420 BigNumValueOne (
421 VOID
422 )
423 {
424 return BN_value_one ();
425 }
426
427 /**
428 Shift right Big Number.
429 Please note, all "out" Big number arguments should be properly initialized
430 by calling to BigNumInit() or BigNumFromBin() functions.
431
432 @param[in] Bn Big number.
433 @param[in] N Number of bits to shift.
434 @param[out] BnRes The result.
435
436 @retval TRUE On success.
437 @retval FALSE Otherwise.
438 **/
439 BOOLEAN
440 EFIAPI
441 BigNumRShift (
442 IN CONST VOID *Bn,
443 IN UINTN N,
444 OUT VOID *BnRes
445 )
446 {
447 return (BOOLEAN)BN_rshift (BnRes, Bn, (INT32)N);
448 }
449
450 /**
451 Mark Big Number for constant time computations.
452 This function should be called before any constant time computations are
453 performed on the given Big number.
454
455 @param[in] Bn Big number
456 **/
457 VOID
458 EFIAPI
459 BigNumConstTime (
460 IN VOID *Bn
461 )
462 {
463 BN_set_flags (Bn, BN_FLG_CONSTTIME);
464 }
465
466 /**
467 Calculate square modulo.
468 Please note, all "out" Big number arguments should be properly initialized
469 by calling to BigNumInit() or BigNumFromBin() functions.
470
471 @param[in] BnA Big number.
472 @param[in] BnM Big number (modulo).
473 @param[out] BnRes The result, such that (BnA ^ 2) % BnM.
474
475 @retval TRUE On success.
476 @retval FALSE Otherwise.
477 **/
478 BOOLEAN
479 EFIAPI
480 BigNumSqrMod (
481 IN CONST VOID *BnA,
482 IN CONST VOID *BnM,
483 OUT VOID *BnRes
484 )
485 {
486 BOOLEAN RetVal;
487 BN_CTX *Ctx;
488
489 Ctx = BN_CTX_new ();
490 if (Ctx == NULL) {
491 return FALSE;
492 }
493
494 RetVal = (BOOLEAN)BN_mod_sqr (BnRes, BnA, BnM, Ctx);
495 BN_CTX_free (Ctx);
496
497 return RetVal;
498 }
499
500 /**
501 Create new Big Number computation context. This is an opaque structure
502 which should be passed to any function that requires it. The BN context is
503 needed to optimize calculations and expensive allocations.
504
505 @retval Big Number context struct or NULL on failure.
506 **/
507 VOID *
508 EFIAPI
509 BigNumNewContext (
510 VOID
511 )
512 {
513 return BN_CTX_new ();
514 }
515
516 /**
517 Free Big Number context that was allocated with BigNumNewContext().
518
519 @param[in] BnCtx Big number context to free.
520 **/
521 VOID
522 EFIAPI
523 BigNumContextFree (
524 IN VOID *BnCtx
525 )
526 {
527 BN_CTX_free (BnCtx);
528 }
529
530 /**
531 Set Big Number to a given value.
532
533 @param[in] Bn Big number to set.
534 @param[in] Val Value to set.
535
536 @retval TRUE On success.
537 @retval FALSE Otherwise.
538 **/
539 BOOLEAN
540 EFIAPI
541 BigNumSetUint (
542 IN VOID *Bn,
543 IN UINTN Val
544 )
545 {
546 return (BOOLEAN)BN_set_word (Bn, Val);
547 }
548
549 /**
550 Add two Big Numbers modulo BnM.
551
552 @param[in] BnA Big number.
553 @param[in] BnB Big number.
554 @param[in] BnM Big number (modulo).
555 @param[out] BnRes The result, such that (BnA + BnB) % BnM.
556
557 @retval TRUE On success.
558 @retval FALSE Otherwise.
559 **/
560 BOOLEAN
561 EFIAPI
562 BigNumAddMod (
563 IN CONST VOID *BnA,
564 IN CONST VOID *BnB,
565 IN CONST VOID *BnM,
566 OUT VOID *BnRes
567 )
568 {
569 BOOLEAN RetVal;
570 BN_CTX *Ctx;
571
572 Ctx = BN_CTX_new ();
573 if (Ctx == NULL) {
574 return FALSE;
575 }
576
577 RetVal = (BOOLEAN)BN_mod_add (BnRes, BnA, BnB, BnM, Ctx);
578 BN_CTX_free (Ctx);
579
580 return RetVal;
581 }