-
Notifications
You must be signed in to change notification settings - Fork 14
/
pka.h
1198 lines (1139 loc) · 53.3 KB
/
pka.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
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
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//
// BSD LICENSE
//
// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Mellanox Technologies nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///
/// @file
///
/// This file forms an interface to the BlueField PK Accelerator based
/// on EIP-154. The API is refered to as "northbound interface" for
/// communication between user application and PKA hardware Rings.
///
/// The PKA hardware makes available a number of basic arithmetic (e.g.,
/// add and multipy) and complex arithmetic (e.g., modular exponentiation
/// and modular inversion) as well as high-level operations such as RSA,
/// Diffie-Hallman, Elliptic Curve Cryptography, and the Federal Digital
/// Signature Algorithm (DSA as documented in FIPS 186) public-private key
/// systems.
///
/// The API consists of an interface which allows user applications to
/// accelerate PK operations. The API allows user application to open and
/// release a PK instance. A PK instance refers to an execution context,
/// i.e. parameters and hardware configuration which allows to process PK
/// operations. It then encapsulates the PK global information structure.
///
/// @note Almost all functions are asynchronous and require a 'handle'
/// argument to be passed to them. Typically, a 'handle' encapsulates
/// all the parameters, status of an execution context of a given user
/// application.
///
/// @note An application running multiple threads has as many handles
/// as threads.
///
/// For example to use this module to do a single RSA encryption, one could
/// do the following:
///
/// @code
/// // 64-bit RSA encryption example.
/// //
/// // Note that the following code does not provide application's function
/// // definition (e.g., from_hex_string(), to_hex_string()). It also omits
/// // macros definition and error checking.
///
/// pka_instance_t instance;
/// pka_handle_t handle;
/// pka_operand_t encrypt_key, n, msg;
/// pka_results_t results;
/// uint8_t result_buf[8];
/// char* key_string = "0x633649F8F2228670";
/// char* modulus_string = "0x87C1F8442909789F";
/// char* plaintext = "0x4869207468657265"; // hex "Hi there"
/// char ciphertext[20];
///
/// memset(&encrypt_key, 0, sizeof(pka_operand_t));
/// memset(&n, 0, sizeof(pka_operand_t));
/// memset(&msg, 0, sizeof(pka_operand_t));
/// memset(&results, 0, sizeof(pka_results_t));
/// results.results[0].buf_ptr = result_buf;
/// results.results[0].buf_len = sizeof(result_buf);
///
/// from_hex_string(key_string, &encrypt_key);
/// from_hex_string(modulus_string, &n);
/// from_hex_string(plaintext, &msg);
///
/// // Global PKA initialization. This function must be called once per
/// // instance before calling any other PKA API functions.
/// instance = pka_init_global(“pka_app”,
/// PKA_F_PROCESS_MODE_SINGLE | PKA_F_SYNC_MODE_NONE,
/// PKA_RING_CNT, PKA_QUEUE_CNT,
/// CMD_QUEUE_SIZE, RSLT_QUEUE_SIZE);
///
/// // Thread local PKA initialization. The instance parameter specifies which
/// // PKA instance the thread joins. It Returns a valid handle for it.
/// handle = pka_init_local(instance);
///
/// pka_rsa(handle, NULL, &encrypt_key, &n, &msg);
///
/// //
/// // Here we can do other stuff
/// //
///
/// pka_get_rslt(handle, &results);
///
/// //
/// // Here we can process other PK commands
/// //
///
/// // Release the given handle.
/// pka_term_local(handle);
/// // Release the PK instance
/// pka_term_global(instance);
///
/// to_hex_string(&results.results[0], ciphertext, 20);
/// printf("plaintext='%s'\nciphertext='%s'\n", plaintext, ciphertext);
///
/// // ciphertext should be '9F5E3B6F177E25B6'
/// @endcode
///
#ifndef __PKA_H__
#define __PKA_H__
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <stdint.h>
#include <stdbool.h>
#endif
/// PK instance type.
typedef uint64_t pka_instance_t;
/// Define value for invalid PK instance.
#define PKA_INSTANCE_INVALID 0
/// PK handle (opaque) type that encapsulates local information.
typedef struct pka_local_info_t* pka_handle_t;
/// Define value for invalid PK handle.
#define PKA_HANDLE_INVALID NULL
/// PK flags that are supplied during PK instance initialization.
typedef enum
{
/// Single process mode:
/// A PK instance runs over one process. The process ID is stored as PK global
/// information. A single process instance might create as many worker threads
/// as needed to process PK operations.
PKA_F_PROCESS_MODE_SINGLE = 0x1,
///
/// Multi process mode:
/// A PK instance runs over mult-processes. The main process ID is stored as
/// PK global information. Each process might create as many worker threads
/// as needed to process PK operations. Only the main process should call the
/// pka_init_global() and pka_term_global() functions.
///
/// @note Currently multi_process_mode is not fully supported.
PKA_F_PROCESS_MODE_MULTI = 0x2,
///
/// None of the PK operations are synchronized :
/// The application will make sure that only one thread will make a PK call
/// at a given time. These calls could come from threads at different times.
/// PK library will ignore synchronization issues.
PKA_F_SYNC_MODE_DISABLE = 0x4,
///
/// All PK operations are synchronized :
/// The PK library uses internal lock to ensure that multiple threads making
/// PK calls are properly synchronized.
PKA_F_SYNC_MODE_ENABLE = 0x8
} pka_flags_t;
/// Global PKA initialization. This function must be called once (per instance)
/// before calling any other PKA API functions. A successful call creates a new
/// PKA instance into the system and outputs a pointer to it. The pointer is
/// used in other calls (e.g. pka_init_local()) and holds a reference to the
/// PK global information.
///
/// @param name Name of the PK instance. Also specifies the shared
/// memory object to be created.
/// @param flags Flags used to select the processing mode and the
/// synchronization mechanism. See pka_flags_t above.
/// @param ring_cnt Number of HW rings requested.
/// @param queue_cnt Number of queues that will be assigned to the
/// worker threads. It might also refer to the number
/// of threads allowed to request PK operation.
/// @param cmd_queue_size Size of a software request queue (in bytes).
/// @param result_queue_size Size of a software reply queue (in bytes).
///
/// @return A valid PK instance on success,
/// PKA_INSTANCE_INVALID on failure.
pka_instance_t pka_init_global(const char* name,
uint8_t flags,
uint32_t ring_cnt,
uint32_t queue_cnt,
uint32_t cmd_queue_size,
uint32_t result_queue_size);
/// Global PKA termination. This function MUST be the last PKA call made when
/// terminating a PKA application in a controlled way.
///
/// @param instance A PK instance handle.
void pka_term_global(pka_instance_t instance);
/// Return the number of rings allocated to a PK instance.
///
/// @param instance A PK instance handle.
///
/// @return The number of allocated HW rings.
uint32_t pka_get_rings_count(pka_instance_t instance);
/// Return the bitmask of HW rings allocated to a PK instance.
///
/// @param instance A PK instance handle.
///
/// @return The bitmask(array of uint8_t) of allocated HW rings.
uint8_t* pka_get_rings_bitmask(pka_instance_t instance);
/// Thread local PKA initialization. All threads must call this function before
/// calling any other PKA API functions. The instance parameter specifies which
/// PKA instance the thread joins. A thread may be part of at most one PKA
/// instance at any given time.
///
/// @param instance A PK instance handle.
///
/// @return A valid PK handle on success,
/// PKA_HANDLE_INVALID on failure.
pka_handle_t pka_init_local(pka_instance_t instance);
/// Thread local PKA termination. This function is the last PKA call made by
/// a given thread, other than the final call to pka_term_global().
///
/// @param handle An initialized PKA handle.
void pka_term_local(pka_handle_t handle);
/// Return Rings byte order, whether BE(1) or LE(0). This function returns
/// PKA_RING_BYTE_ORDER if the PKA handle is invalid.
///
/// @param handle An initialized PKA handle.
uint8_t pka_get_rings_byte_order(pka_handle_t handle);
/// MAX_OPERAND_CNT defines the largest number of big integer operands used by
/// any operation in this API.
#define MAX_OPERAND_CNT 11
/// MAX_RESULT_CNT defines the largest number of big integers returned by any
/// operation in this API. In particular, a given asynchronous request
/// function always returns the same number of result big integers, but
/// depending on the operation this can be either 0, 1 or 2 big integers.
#define MAX_RESULT_CNT 2
/// The MAX_BYTE_LEN constant defines the byte length of the largest operand
/// that the current PKA hardware supports.
#define MAX_BYTE_LEN 520 // 130 * 4 bytes
/// The OTHER_MAX_BYTE_LEN constant defines the byte length of the largest
/// operand supported for certain operations like "modular exponentiation
/// using the chinese remainder theorem".
#define OTHER_MAX_BYTE_LEN 264 // 66 * 4 bytes
/// Defines the largest number of big integers returned by any operation
/// in this API. In particular, a given asynchronous request function
/// always returns the same number of result big integers, but depending
/// on the operation this can be either 0, 1 or 2 big integers.
#define MAX_RESULT_CNT 2
/// The pka_operand_t is the record type used to represent big integer numbers.
/// Despite its name, it is used to represent all big integers including the
/// results.
typedef struct // 16 bytes long
{
uint16_t buf_len; ///< Size of the buffer holding the big integer.
uint16_t actual_len; ///< Actual minimum # of bytes used by the operand.
uint8_t is_encrypted; ///< Reserved for future use.
uint8_t big_endian; ///< Indicates byte order of the big integer operand
uint8_t internal_use; ///< Internal use. Must be set to 0 by users.
uint8_t pad; ///< Reserved for future use.
uint8_t* buf_ptr; ///< Pointer to the buffer holding the big integer.
} pka_operand_t;
/// PKA Command Code Values.
typedef enum
{
/// Add (basic arithmetic).
CC_ADD = 0x01,
/// Subtract (basic arithmetic).
CC_SUBTRACT = 0x02,
/// Add/Subtract combination (basic arithmetic).
CC_ADD_SUBTRACT = 0x03,
/// Multiply/Square (basic arithmetic).
/// @note The Square operation is a Multiply where the inputs 'A' and 'B'
/// point to the same.
CC_MULTIPLY = 0x04,
/// Divide (basic arithmetic).
CC_DIVIDE = 0x05,
/// Modulo (basic arithmetic).
CC_MODULO = 0x06,
/// Shift left (basic arithmetic).
CC_SHIFT_LEFT = 0x07,
/// Shift right (basic arithmetic).
CC_SHIFT_RIGHT = 0x08,
/// Compare (basic arithmetic).
CC_COMPARE = 0x09,
/// Copy (basic arithmetic).
CC_COPY = 0xA0,
/// Modular Exponentiation without CRT (complex arithmetic).
CC_MODULAR_EXP = 0x10,
/// Modular Exponentiation with CRT (complex arithmetic).
CC_MOD_EXP_CRT = 0x11,
/// Modular Inversion (complex arithmetic).
CC_MODULAR_INVERT = 0x12,
/// ECC point multiplication on Montgomery Curves (complex arithmetic)
CC_MONT_ECDH_MULTIPLY = 0x13,
/// ECC point addition/doubling (complex arithmetic).
CC_ECC_PT_ADD = 0x14,
/// ECC point multiplication (complex arithmetic).
CC_ECC_PT_MULTIPLY = 0x15,
/// ECDSA signature generation (high-level PKA operations).
CC_ECDSA_GENERATE = 0x20,
/// ECDSA signature verification with r'' write-back (high-level PKA
/// operations).
CC_ECDSA_VERIFY = 0x21,
/// DSA signature generation (high-level PKA operations).
CC_DSA_GENERATE = 0x22,
/// DSA signature verification with r'' write-back (high-level PKA
/// operations).
CC_DSA_VERIFY = 0x23,
/// ECDSA signature verification without r'' write-back (high-level
/// PKA operations).
CC_ECDSA_VERIFY_NO_WRITE = 0x25,
/// DSA signature verification without r'' write-back (high-level PKA
/// operations).
CC_DSA_VERIFY_NO_WRITE = 0x27,
} pka_opcode_t;
/// PKA Result Code Values.
typedef enum
{
/// No error – Normal command completion.
RC_NO_ERROR = 0x00,
/// Modulus was even.
RC_EVEN_MODULUS = 0x81,
/// Exponent was 0 (for a modular exponentiation).
RC_ZERO_EXPONENT = 0x82,
/// Modulus was too short (less than 9 significant bits).
RC_SHORT_MODULUS = 0x83,
/// Exponent was 1 (for a modular exponentiation).
RC_ONE_EXPONENT = 0x84,
/// Odd powers not in range 1 … 16.
RC_BAD_ODD_POWERS = 0x85,
/// Result point of ECC operation is 'at infinity' -not a real error.
RC_RESULT_IS_PAI = 0x86, // Not a real error?
/// Unknown command
RC_UNKNOWN_COMMAND = 0x87,
/// Intermediate result of ECC operation is 'at infinity' -not a real error.
RC_INTERMEDIATE_PAI = 0x89, // PAI = Point At Infinity
/// Modular inverse does not exist.
RC_NO_MODULAR_INVERSE = 0x8B,
/// Result of ECC operation is not on the curve.
RC_ECC_RESULT_OFF_CURVE = 0x8D,
/// Operand length error.
RC_OPERAND_LENGTH_ERR = 0x8F,
/// Host used undefined trigger.
RC_UNDEFINED_TRIGGER = 0x90,
/// Invalid argument.
RC_INVALID_ARGUMENT = 0x91,
/// Operand value error.
RC_OPERAND_VALUE_ERR = 0xA0,
/// Calculated value error.
RC_CALCULATION_ERR = 0xA1,
/// Address is invalid.
RC_INVALID_ADDRESS = 0xA2,
/// Illegal encrypted parameter use.
RC_ENCRYPTED_PARAM_ERR = 0xA3,
/// Farm memory too small for operation.
RC_TOO_LITTLE_MEMORY = 0xC0,
/// Memory deadlock error.
RC_MEMORY_DEADLOCK = 0xC1
} pka_result_code_t;
/// PKA Compare Result Code Values.
typedef enum
{
/// Both operands are equal ('A' = 'B').
RC_COMPARE_EQUAL = 0x1,
/// Left operand is smaller than right operand ('A' < 'B').
RC_LEFT_IS_SMALLER = 0x2,
/// Right operand is smaller than left operand ('A' > 'B').
RC_RIGHT_IS_SMALLER = 0x4
} pka_cmp_code_t;
/// The pka_results_t record type is used to package up the entire set of
/// output vectors (of which there can be 0, 1 or 2) as well as other result
/// values like the compare_result (only used for compare op), the result_cnt
/// and the overall status.
typedef struct // 50 bytes long
{
void* user_data; ///< Opaque data pointer.
pka_opcode_t opcode; ///< Opcode of the associated request.
uint8_t result_cnt; ///< Result cnt must be 0, 1 or 2.
pka_result_code_t status; ///< Same as result_code.
pka_cmp_code_t compare_result; ///< Result of a comparison.
pka_operand_t results[MAX_RESULT_CNT]; ///< Actual result operand descs.
} pka_results_t;
/// Return results pending in queue.
///
/// @param handle An initialized PKA handle.
/// @param results The results structure to store the PK results.
///
/// @return 0 on success, and 1 on failure.
int pka_get_result(pka_handle_t handle, pka_results_t* results);
/// Return if there is pending results in queue.
///
/// @param handle An initialized PKA handle.
///
/// @return Whether there is an available result.
bool pka_has_avail_result(pka_handle_t handle);
/// Return the number of outstanding command requests.
///
/// @param handle An initialized PKA handle.
///
/// @return The number of outstanding requests.
uint32_t pka_request_count(pka_handle_t handle);
/// Big Integer Add function.
///
/// This function computes "value + addend".
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value One of the two big integers whose sum is requested.
/// @param addend The other of the two big integers whose sum is
/// requested.
///
/// @return 0 on success, a negative error code on failure.
int pka_add(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
pka_operand_t* addend);
/// Big Integer Subtraction function.
///
/// This functions computes "value - subtrahend".
///
/// @note This function must yield a positive result and so the value
/// MUST be >= than the subtrahend.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value The LARGEST of the two big integers whose difference
/// is requested.
/// @param subtrahend The SMALLEST of the two big integers whose difference
/// is requested.
///
/// @return 0 on success, a negative error code on failure.
int pka_subtract(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
pka_operand_t* subtrahend);
/// Big Integer Add/Substract combination.
///
/// This functions computes "value + addend - subtrahend".
///
/// @note The result of this function must be positive, so the value plus the
/// addend MUST be >= than the subtrahend.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value The LARGEST of the three big integers whose addition
/// and subtraction are requested.
/// @param addend The other of the three big integers whose sum is
/// requested.
/// @param subtrahend The SMALLEST of the three big integers whose difference
/// is requested.
///
/// @return 0 on success, a negative error code on failure.
int pka_add_subtract(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
pka_operand_t* addend,
pka_operand_t* subtrahend);
/// Big Integer Multiply function.
///
/// This function computes "value * multiplier".
///
/// @note To compute a square operation, the inputs, value and multiplier must
/// to the same data.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value One of the two big integers whose product is requested.
/// @param multiplier The other of the two big integers whose product is
/// requested.
///
/// @return 0 on success, a negative error code on failure.
int pka_multiply(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
pka_operand_t* multiplier);
/// Big Integer Divide function.
///
/// This function computes BOTH "value / divisor", and "value mod divisor".
///
/// @note the final results returned will always have result_cnt = 2.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value The big integer whose quotient and remainder is desired.
/// @param divisor The big integer divisor. Must not be zero.
///
/// @return 0 on success, a negative error code on failure.
int pka_divide(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
pka_operand_t* divisor);
/// Big Integer Modulo function.
///
/// The function implements the modulo function on big integers, i.e. computes
/// "value mod modulus".
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value The big integer whose mod is desired.
/// @param modulus The big integer modulus. Must be odd and be larger
/// than 2^32 (5 bytes).
///
/// @return 0 on success, a negative error code on failure.
int pka_modulo(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
pka_operand_t* modulus);
/// Big Integer Shift Left function.
///
/// Computes "value << shift_cnt".
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value The big integer that is to be shifted left.
/// @param shift_cnt The amount that the big integer 'value' is to be
/// shifted by (range 0...31 bits).
///
/// @return 0 on success, a negative error code on failure.
int pka_shift_left(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
uint32_t shift_cnt);
/// Big Integer Shift Right function.
///
/// Computes "value >> shift_cnt".
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value The big integer that is to be shifted right.
/// @param shift_cnt The amount that the big integer 'value' is to be
/// shifted by (range 0...31 bits).
///
/// @return 0 on success, a negative error code on failure.
int pka_shift_right(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
uint32_t shift_cnt);
/// Traditional Diffie-Hellman(DH).
///
/// This function provide Diffie-Hellman algorithm implementation,
/// which is essentially nothing but Modular Exponentiation without CRT.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param private_key The big integer exponent, which is always the local private
/// key in case of DH.
/// @param modulus The big integer modulus. Must be an odd prime (i.e. the
/// LSB must be ONE). Must be larger than 2^32 (5 bytes).
/// @param value The big integer whose modular power is requested. Must
/// be inferior to the 'modulus'.
///
/// @return 0 on success, a negative error code on failure.
int pka_dh(pka_handle_t handle,
void* user_data,
pka_operand_t* private_key,
pka_operand_t* modulus,
pka_operand_t* value);
/// Modular Exponentiation function without Chinese Remainder Theorem (CRT).
///
/// This function implements the mathematical expression
/// "value^exponent mod modulus".
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param exponent The big integer exponent.
/// @param modulus The big integer modulus. Must be an odd prime (i.e. the
/// LSB must be ONE). Must be larger than 2^32 (5 bytes).
/// @param value The big integer whose modular power is requested. Must
/// be inferior to the 'modulus'.
///
/// @return 0 on success, a negative error code on failure.
int pka_modular_exp(pka_handle_t handle,
void* user_data,
pka_operand_t* exponent,
pka_operand_t* modulus,
pka_operand_t* value);
/// Modular Exponentiation with Chinese Remainder Theorem (CRT).
///
/// The function makes use of the Chinese Remainder Theorem in order
/// to implement a modular exponentiation using two smaller (half-sized)
/// modular exponentiation, plus a big integer subtraction, multiplication
/// and addition.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value A big integer representing the message to be decrypted.
/// @param p A big integer prime number.
/// @param q A big integer prime number.
/// @param d_p The big integer value 'd mod (p-1)' where d is the
/// private key.
/// @param d_q The big integer value 'd mod (q-1)' where d is the
/// private key.
/// @param qinv The big integer value 'q^-1 mod p' - i.e. the modular
/// inverse of q, using modulus p.
///
/// @return 0 on success, a negative error code on failure.
int pka_modular_exp_crt(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
pka_operand_t* p,
pka_operand_t* q,
pka_operand_t* d_p,
pka_operand_t* d_q,
pka_operand_t* qinv);
/// RSA - Modular Exponentiation function.
///
/// This function implements the mathematical
/// expression "value^exponent mod modulus".
///
/// It is the basis for both RSA encryption and decryption. For example RSA
/// is defined by:
///
/// @code
/// // Pick two large distinct random prime numbers p and q.
/// // Pick a random integer e such that 1 < e < (p-1)*(q-1) AND
/// // gcd(e, (p-1)*(q-1)) = 1.
/// n = p * q;
/// d = (e^-1) mod ((p-1)*(q-1));
/// // I.e. find d such that '(e * d) mod ((p-1)*(q-1)) = 1'.
/// // Then publish (e, n) as the public key. (d, n) is the private key.
/// @endcode
///
/// where the encryption and decryption operations are defined as:
///
/// @code
/// ciphertext = (plaintext^e) mod n; // encryption
/// plaintext = (ciphertext^e) mod n; // decryption
/// @endcode
///
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param exponent The big integer exponent. For RSA, this exponent could
/// be either the e or d part of the public or private key.
/// @param modulus The big integer modulus. Must be odd. Must be the product
/// of two big prime numbers.
/// @param value The big integer whose modular power is requested.
///
/// @return 0 on success, a negative error code on failure.
int pka_rsa(pka_handle_t handle,
void* user_data,
pka_operand_t* exponent,
pka_operand_t* modulus,
pka_operand_t* value);
/// Optimized Modular Exponentiation function for RSA.
///
/// The function makes use of the Chinese Remainder Theorem in order to
/// implement a full RSA modular exponentiation using two smaller (half-sized)
/// modular exponentiation, plus a big integer subtraction, multiplication and
/// addition.
/// Since the performance of the modular exponentiation is very roughly cubic
/// in the size of the operands, each smaller modular exponentation runs roughly
/// 4 times faster (but there are now twice as many of them), and in total can
/// give a 3x speed up.
///
/// @note that this function is only useful to the side that has both the
/// public AND private RSA keys, since it requires as input some of the
/// intermediate values used when creating a RSA public-private key pair.
///
/// In addition, it is assumed that the following values have been precomputed:
///
/// @code
/// d_p = d mod (p-1);
/// d_q = d mod (q-1);
/// qinv = q^-1 mod p; // I.e. Find qinv such that '(qinv * q) mod p = 1'
/// @endcode
///
/// Specifically this function implements the mathematical expression
/// "c^d mod p*q" by doing the following computation:
///
/// @code
/// m1 = (c^d_p) mod p;
/// m2 = (c^d_q) mod q;
/// h = (q_inv * (m1 - m2)) mod p;
/// return m2 + (h * q);
/// @endcode
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param p A big integer prime number. RSA modulus = 'p*q', where
/// p is larger than q.
/// @param q A big integer prime number. RSA modulus = 'p*q', where
/// q is smaller than p.
/// @param c A big integer representing the message to be decrypted.
/// @param d_p The big integer value 'd mod (p-1)' where d is the private
/// key.
/// @param d_q The big integer value 'd mod (q-1)' where d is the private
/// key.
/// @param qinv The big integer value 'q^-1 mod p' - i.e. the modular
/// inverse of q, using modulus p.
///
/// @return 0 on success, a negative error code on failure.
int pka_rsa_crt(pka_handle_t handle,
void* user_data,
pka_operand_t* p,
pka_operand_t* q,
pka_operand_t* c,
pka_operand_t* d_p,
pka_operand_t* d_q,
pka_operand_t* qinv);
/// Modular Inversion Function.
///
/// Implements "value^(-1) mod modulus", i.e. finds a big integer such that
/// when it is multiplied by 'value mod modulus' results in the value 1.
/// If the modulus is a prime, then such an inverse value must exist (as long
/// as value != 0) and must be unique.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param value The big integer whose modular inverse is requested.
/// @param modulus The big integer modulus. Must be odd (i.e. the least
/// significant bit must be ONE). May not have value 1.
///
/// @return 0 on success, a negative error code on failure.
int pka_modular_inverse(pka_handle_t handle,
void* user_data,
pka_operand_t* value,
pka_operand_t* modulus);
/// The ecc_point_t record type is used to represent a point on an elliptic
/// curve defined over a finite field.
typedef struct
{
pka_operand_t x; ///< big integer x coordinate of a point on a EC curve
pka_operand_t y; ///< big integer y coordinate of a point on a EC curve
} ecc_point_t;
/// The ecc_curve_t record type is used to represent an elliptic curve.
///
/// It holds all of the parameters defining an elliptic curve over a large
/// prime number finite field. The prime used as the modulus is called 'p'.
/// The parameters of the general curve are called 'a' and 'b'. The formula
/// defining the curve is:
/// @code
/// // The curve is defined as all possible (x,y) values such that
/// // x,y are integers in the range 0..p-1 (where p must be an odd prime).
/// // and the x,y values also satisfy:
/// y^2 mod p = (x^3 + a*x + b) mod p
/// @endcode
typedef struct
{
pka_operand_t p; ///< large integer prime defining the finite field
pka_operand_t a; ///< coefficient of x in the defining equation
pka_operand_t b; ///< constant coefficient in defining equation
} ecc_curve_t;
typedef enum
{
PKA_CURVE_NULL = 0,
PKA_CURVE_25519,
PKA_CURVE_448
}pka_mont_curve_t;
/// The ecc_mont_curve_t record type is used to represent an elliptic
/// curve in Montgomery form.
///
/// It holds all of the parameters defining an elliptic curve over a large
/// prime number finite field. The prime used as the modulus is called 'p'.
/// The parameter of the general curve is called 'A'. The formula defining
/// the curve is:
/// @code
/// // The curve is defined as all possible (u,v) values such that
/// // u,v are integers in the range 0..p-1 (where p must be an odd prime).
/// // and the u,v values also satisfy:
/// v^2 mod p = (u^3 + A*u^2 + u) mod p
///
/// Note that a more general equation for Montgomery curves is
/// B*v*2 mod p = (u^3 + A*u^2 + u) mod p
/// but for our purposes B will always be 1.
/// @endcode
typedef struct
{
pka_operand_t p; ///< large integer prime defining the finite field
pka_operand_t A; ///< coefficient of u^2 in the defining equation
pka_mont_curve_t type; ///< type to depict curve.
} ecc_mont_curve_t;
/// Montgomery Elliptic Curve Cryptography (ECC) point multiplication.
///
/// Implements modular elliptic curve multiplication for points on a Montgomery
/// curve like Curve25519 and Curve448. In particular, given a point on a
/// Montgomery elliptic curve and a 'scalar' m, multiply the point by the
/// scalar giving a new result point. Scalar multiplication is defined to be
/// equivalent to repeated elliptic curve addition. Note that this specific
/// function is ONLY given the x-coordinate of the point, and ONLY returns the
/// x-coordinate of the result point!
///
/// @note: The curve parameter passed in currently MUST be one of curve25519 or
/// curve448!
/// @note: The multiplier is subsequently modified according to RFC7748.
/// For curve25519 the two MSB bits are set to "0b01" and the three LSB
/// bits are cleared. For curve448 the MSB bit is set and the two LSB
/// bits are cleared. This is done internally and does not change the
/// value the user passed in.
/// @note Elliptic curves using a modulus of 2^m are NOT supported.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param curve A pointer to an ecc_mont_curve_t object, which
/// supplies the curve parameters A and p where p must be
/// prime.
/// @param point_x A pointer to the x coordinate of an ecc_point_t object.
/// @param multiplier A big integer indicating the number of times that point_x
/// should be added to itself.
///
/// @return 0 on success, a negative error code on failure.
int pka_mont_ecdh_mult(pka_handle_t handle,
void* user_data,
ecc_mont_curve_t* curve,
pka_operand_t* point_x,
pka_operand_t* multiplier);
/// Elliptic Curve Cryptography (ECC) point addition.
///
/// Implements modular elliptic curve addition. In particular, given two points
/// on an elliptic curve defined using a finite field defined by a large prime
/// number, determine their sum.
///
/// @note Elliptic curves using a modulus of 2^m (a.k.a binary fields) are
/// NOT supported.
///
/// The elliptic curve is assumed to be defined by the set
/// of all points '(x,y)' such that x and y are integers in the range 0..p-1
/// and such that they satisfy the equation:
///
/// @code
/// y^2 = x^3 + a*x + b mod p;
/// // where x and y are in the range 0..p-1 and p is a big prime number.
/// @endcode
///
/// The elliptic curve is then defined by the three big integer parameters,
/// a, b and p. These three parameters are not completely independent.
/// In particular, the discriminant defined below must be non-zero.
///
/// @code
/// // Definition of the discriminant. Must be non-zero.
/// discriminant = -16 * ((4 * a^3) + (27 * b^2));
/// @endcode
///
/// The definition of elliptic curve point addition leads to the following
/// equations for computing the result point. Notice that the result from
/// this operation has a result_cnt of 2 because it returns two large integers,
/// namely the x and y coordinate of the result point.
///
/// @code
/// if pointA.x == pointB.x then
/// s = (3 * pointA.x^2 + curve.a) / (2 * pointA.y) mod curve.p;
/// result.x = s * s - 2 * pointA.x mod curve.p;
/// else
/// s = ((pointA.y - pointB.y) / (pointA.x - pointB.x)) mod curve.p;
/// result.x = s * s - (pointA.x + pointB.x) mod curve.p;
/// endif
/// result.y = pointA.y + s * (result.x - pointA.x) mod curve.p;
/// @endcode
///
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param curve A pointer to an ecc_curve_t object, which supplies the
/// curve parameters a, b, and p where p must be prime.
/// @param pointA A pointer to an ecc_point_t object, which supplies the
/// x and y coordinates (as big integer) for the first point.
/// @param pointB A pointer to an ecc_point_t object, which supplies the
/// x and y coordinates (as big integer) for the second point.
///
/// @return 0 on success, a negative error code on failure.
int pka_ecc_pt_add(pka_handle_t handle,
void* user_data,
ecc_curve_t* curve,
ecc_point_t* pointA,
ecc_point_t* pointB);
/// Elliptic Curve Cryptography (ECC) point multiplication.
///
/// Implements modular elliptic curve multiplication. In particular, given
/// a point on an elliptic curve and a 'scalar' m, multiply the point by the
/// scalar giving a new result point. Scalar multiplication is defined to be
/// equivalent to repeated elliptic curve addition (see pka_ecc_pt_add above
/// for details of elliptic curve addition).
///
/// @note Elliptic curves using a modulus of 2^m are NOT supported.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param curve A pointer to an ecc_curve_t object, which supplies the
/// curve parameters a, b, and p where p must be prime.
/// @param pointA A pointer to an ecc_point_t object, which supplies the
/// x and y coordinates (as big integer) for the first point.
/// @param multiplier A big integer indicating the number of times that pointA
/// should be added to itself.
///
/// @return 0 on success, a negative error code on failure.
int pka_ecc_pt_mult(pka_handle_t handle,
void* user_data,
ecc_curve_t* curve,
ecc_point_t* pointA,
pka_operand_t* multiplier);
/// Elliptic Curve Diffie-Hellman (ECDH) on Montgomery curves.
///
/// ECDH is based on ECC point multiplication and essentially uses the
/// API of the same.
///
/// @note: The curve parameter passed in currently MUST be one of curve25519 or
/// curve448!
/// @note Elliptic curves using a modulus of 2^m are NOT supported.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param curve A pointer to an ecc_mont_curve_t object, which supplies
/// the curve parameters A and p where p must be prime.
/// MUST be a pointer to either the curve25519 or the
/// curve448 object.
/// @param point_x The x coordinate of a point on a Montgomery ECC curve.
/// This is either a base point for the curve or a remote
/// public key.
/// @param private_key big integer indicating the number of times that point
/// should be added to itself. In case of ECDH this the local
/// private key.
///
/// @return 0 on success, a negative error code on failure.
int pka_mont_ecdh(pka_handle_t handle,
void* user_data,
ecc_mont_curve_t* curve,
pka_operand_t* point_x,
pka_operand_t* private_key);
/// Elliptic Curve Diffie-Hellman (ECDH).
///
/// ECDH is based on ECC point multiplication and essentially uses the
/// API of the same.
///
/// @note Elliptic curves using a modulus of 2^m are NOT supported.
///
/// @param handle An initialized PKA handle to use for this command.
/// @param user_data Opaque user pointer that is returned with the result.
/// @param curve A pointer to an ecc_curve_t object, which supplies the
/// curve parameters a, b, and p where p must be prime.
/// @param point A pointer to an ecc_point_t object, which supplies the
/// x and y coordinates (as big integer) for the first point.
/// This is either a base point for the curve or remote public key.
/// @param private_key big integer indicating the number of times that point
/// should be added to itself. In case of ECDH this the local
/// private key.
///
/// @return 0 on success, a negative error code on failure.
int pka_ecdh(pka_handle_t handle,
void* user_data,
ecc_curve_t* curve,
ecc_point_t* point,
pka_operand_t* private_key);
/// Elliptic Curve DSA (ECSDA) Signature Generation.