-
Notifications
You must be signed in to change notification settings - Fork 0
/
point_p.sx
944 lines (772 loc) · 25.1 KB
/
point_p.sx
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
.section .rodata
secp256k1_G: //Generator point G
secp256k1_Gx:
.quad 0x59F2815B16F81798, 0x029BFCDB2DCE28D9, 0x55A06295CE870B07, 0x79BE667EF9DCBBAC
secp256k1_Gy:
.quad 0x9C47D08FFB10D4B8, 0xFD17B448A6855419, 0x5DA4FBFC0E1108A8, 0x483ADA7726A3C465
.data
//Temporary storage for points and intermediary values of point addition
pointD:
pointDx: .quad 0,0,0,0
pointDy: .quad 0,0,0,0
pointA:
pointAx: .quad 0,0,0,0
pointAy: .quad 0,0,0,0
pointTemp:
pointTempX: .quad 0,0,0,0
pointTempY: .quad 0,0,0,0
temp256: .quad 0,0,0,0
lambda: .quad 0,0,0,0
// lambda²
lambda2: .quad 0,0,0,0
//Temp variables for ecdsa verification
//temporary storage for u = message * inverse(signature.s)
scalar_u: .quad 0,0,0,0
//temporary storage for v = signature.r * inverse(signature.s)
scalar_v: .quad 0,0,0,0
//temporary storage for Point u*Generator
point_uG: .quad 0,0,0,0,0,0,0,0
//temporary storage for Point v*P (P = public key of signer)
point_vP:
point_vPx: .quad 0,0,0,0
point_vPy: .quad 0,0,0,0
.text
.include "aliases"
.include "commonmacros"
FLAG_POINT_A .req io1
/**
Sets FLAG_POINT_A to zero.
*/
.macro INIT_FLAG_POINT_A
mov io1, xzr
.endm
//Stores content of registers r0 (least significant int), r1, r2, r3 (most
//significant int) into temp256. Uses tmp5 for the address.
.macro STORE_TEMP256_FROM r0 r1 r2 r3
adr tmp5, temp256
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
//Stores content of registers r0 (least significant int), r1, r2, r3 (most
//significant int) into lambda. Uses tmp5 for the address.
.macro STORE_LAMBDA_FROM r0 r1 r2 r3
adr tmp5, lambda
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
//Stores content of registers r0 (least significant int), r1, r2, r3 (most
//significant int) into lambda2. Uses tmp5 for the address.
.macro STORE_LAMBDA2_FROM r0 r1 r2 r3
adr tmp5, lambda2
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
//Stores content of registers r0 (least significant int), r1, r2, r3 (most
//significant int) into pointTempX. Uses tmp5 for the address.
.macro STORE_POINT_TEMPX_FROM r0 r1 r2 r3
adr tmp5, pointTempX
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
//Stores content of registers r0 (least significant int), r1, r2, r3 (most
//significant int) into pointTempY. Uses tmp5 for the address.
.macro STORE_POINT_TEMPY_FROM r0 r1 r2 r3
adr tmp5, pointTempY
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
//Loads u256 integer from temp256 in registers r0 (least significant int),
//r1, r2, r3 (most significant int). Uses tmp5 for the address.
.macro LOAD_TEMP256_INTO r0 r1 r2 r3
adr tmp5, temp256
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
//Loads u256 integer from lambda in registers r0 (least significant int),
//r1, r2, r3 (most significant int). Uses tmp5 for the address.
.macro LOAD_LAMBDA_INTO r0 r1 r2 r3
adr tmp5, lambda
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
//Loads u256 integer from lambda2 in registers r0 (least significant int),
//r1, r2, r3 (most significant int). Uses tmp5 for the address.
.macro LOAD_LAMBDA2_INTO r0 r1 r2 r3
adr tmp5, lambda2
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
/**
Macros for loading/storing points in/from temporary storage pointA and pointD
*/
.macro INIT_POINT_D_FROM reg=io0
ldp sa0, sa1, [\reg], #16
ldp sa2, sa3, [\reg], #16
STORE_POINT_DX_FROM sa0 sa1 sa2 sa3
ldp sa0, sa1, [\reg], #16
ldp sa2, sa3, [\reg]
STORE_POINT_DY_FROM sa0 sa1 sa2 sa3
.endm
.macro INIT_POINT_D_WITH_G
PUSH io1
adr io1 , secp256k1_G
ldp sa0, sa1, [io1], #16
ldp sa2, sa3, [io1], #16
STORE_POINT_DX_FROM sa0 sa1 sa2 sa3
ldp sa0, sa1, [io1], #16
ldp sa2, sa3, [io1]
STORE_POINT_DY_FROM sa0 sa1 sa2 sa3
POP io1
.endm
.macro INIT_POINT_A_FROM reg=io0
ldp sa0, sa1, [\reg], #16
ldp sa2, sa3, [\reg], #16
STORE_POINT_AX_FROM sa0 sa1 sa2 sa3
ldp sa0, sa1, [\reg], #16
ldp sa2, sa3, [\reg]
STORE_POINT_AY_FROM sa0 sa1 sa2 sa3
.endm
.macro INIT_POINT_VP_FROM reg=io0
adr tmp5, point_vP
LOAD_A \reg
stp sa0, sa1, [tmp5], #16
stp sa2, sa3, [tmp5], #16
add \reg, \reg, #32
LOAD_A \reg
stp sa0, sa1, [tmp5], #16
stp sa2, sa3, [tmp5]
.endm
.macro STORE_POINT_A_INTO reg=io1
LOAD_POINT_AX_INTO sa0 sa1 sa2 sa3
stp sa0, sa1, [\reg], #16
stp sa2, sa3, [\reg], #16
LOAD_POINT_AY_INTO sa0 sa1 sa2 sa3
stp sa0, sa1, [\reg], #16
stp sa2, sa3, [\reg]
.endm
.macro STORE_POINT_D_INTO reg=io1
LOAD_POINT_DX_INTO sa0 sa1 sa2 sa3
stp sa0, sa1, [\reg], #16
stp sa2, sa3, [\reg], #16
LOAD_POINT_DY_INTO sa0 sa1 sa2 sa3
stp sa0, sa1, [\reg], #16
stp sa2, sa3, [\reg]
.endm
.macro STORE_POINT_VP_INTO reg=io1
LOAD_POINT_VPX_INTO sa0 sa1 sa2 sa3
stp sa0, sa1, [\reg], #16
stp sa2, sa3, [\reg], #16
LOAD_POINT_VPY_INTO sa0 sa1 sa2 sa3
stp sa0, sa1, [\reg], #16
stp sa2, sa3, [\reg]
.endm
.macro STORE_POINT_DX_FROM r0 r1 r2 r3
adr tmp5, pointDx
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
.macro STORE_POINT_DY_FROM r0 r1 r2 r3
adr tmp5, pointDy
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
.macro STORE_POINT_AX_FROM r0 r1 r2 r3
adr tmp5, pointAx
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
.macro STORE_POINT_AY_FROM r0 r1 r2 r3
adr tmp5, pointAy
stp \r0, \r1, [tmp5], #16
stp \r2, \r3, [tmp5]
.endm
.macro COPY_POINT_A_INTO_POINT_VP
adr tmp5, pointA
ldp sa0, sa1, [tmp5], #16
ldp sa2, sa3, [tmp5], #16
ldp sb0, sb1, [tmp5], #16
ldp sb2,sb3,[tmp5]
adr tmp5, point_vP
stp sa0, sa1, [tmp5], #16
stp sa2, sa3, [tmp5], #16
stp sb0, sb1, [tmp5], #16
stp sb2, sb3, [tmp5]
.endm
.macro COPY_POINT_VP_INTO_POINT_D
adr tmp5, point_vP
ldp sa0, sa1, [tmp5], #16
ldp sa2, sa3, [tmp5], #16
ldp sb0, sb1, [tmp5], #16
ldp sb2,sb3,[tmp5]
adr tmp5, pointD
stp sa0, sa1, [tmp5], #16
stp sa2, sa3, [tmp5], #16
stp sb0, sb1, [tmp5], #16
stp sb2, sb3, [tmp5]
.endm
.macro LOAD_POINT_DX_INTO r0 r1 r2 r3
adr tmp5, pointDx
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
.macro LOAD_POINT_DY_INTO r0 r1 r2 r3
adr tmp5, pointDy
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
.macro LOAD_POINT_AX_INTO r0 r1 r2 r3
adr tmp5, pointAx
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
.macro LOAD_POINT_AY_INTO r0 r1 r2 r3
adr tmp5, pointAy
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
.macro LOAD_POINT_VPX_INTO r0 r1 r2 r3
adr tmp5, point_vPx
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
.macro LOAD_POINT_VPY_INTO r0 r1 r2 r3
adr tmp5, point_vPy
ldp \r0, \r1, [tmp5], #16
ldp \r2, \r3, [tmp5]
.endm
/*
The C-compatible function secp256k1_points_compare compares two points a and b.
The result is 0 if a == b, otherwise 1
Input:
Address of point a in io0
Address of point b in io1
Output:
Result in io0
*/
BEGIN_GLOBAL_FUNCTION secp256k1_compare_points
//load a.x and b.x
ldp io2, io3, [io0], #16
ldp sa0, sa1, [io1], #16
cmp io2, sa0
bne points_are_not_equal
cmp io3, sa1
bne points_are_not_equal
ldp io2, io3, [io0], #16
ldp sa0, sa1, [io1], #16
cmp io2, sa0
bne points_are_not_equal
cmp io3, sa1
bne points_are_not_equal
//load a.y and b.y
ldp io2, io3, [io0], #16
ldp sa0, sa1, [io1], #16
cmp io2, sa0
bne points_are_not_equal
cmp io3, sa1
bne points_are_not_equal
ldp io2, io3, [io0], #16
ldp sa0, sa1, [io1], #16
cmp io2, sa0
bne points_are_not_equal
cmp io3, sa1
bne points_are_not_equal
b points_are_equal
points_are_not_equal:
mov io0, #1
b end_of_point_comparison
points_are_equal:
mov io0, xzr
end_of_point_comparison:
END_GLOBAL_FUNCTION secp256k1_compare_points
//****************************** doubling point *******************************
/*
Macro double_point
adds a point to itself.
(see SEC 1, page 7, 5.)
input: a point in pointD.
x in memory at label pointDx, y in memory at label pointDy
result: in pointD
*/
.macro double_point
//----Calculating Lambda----
//double y1
LOAD_POINT_DY_INTO sa0 sa1 sa2 sa3
bl double_a_mod_p_asign_a //2y in regs. sa0-sa3
//inverse of 2y1
bl invert_a_mod_p_into_b //inv 2y in regs. sb0-sb3
STORE_TEMP256_FROM sb0 sb1 sb2 sb3 //store inv 2y in memory at temp256
//x²
LOAD_POINT_DX_INTO sa0 sa1 sa2 sa3
bl square_a_mod_p_asign_a //x² in regs. sa0-sa3
bl triple_a_mod_p_asign_a //3x² in sa0-sa3
//Calculate lambda = 3x² * inv 2y
LOAD_TEMP256_INTO sb0 sb1 sb2 sb3 //inv 2y in regs. sb0-sb3
bl mul_a_b_mod_p_asign_a //3x² * inv 2y in regs. sr0-sr3 and sa0-sa3
STORE_LAMBDA_FROM sr0 sr1 sr2 sr3
//Calculate lambda²
bl square_a_mod_p //lambda² in regs. sr0-sr3
STORE_LAMBDA2_FROM sr0 sr1 sr2 sr3
//------Calculate new_x = lambda² - 2x
LOAD_POINT_DX_INTO sa0 sa1 sa2 sa3
bl double_a_mod_p_asign_b //2x in regs. sb0-sb3
LOAD_LAMBDA2_INTO sa0 sa1 sa2 sa3 //lambda² is in sa0-sa3
bl sub_a_b_mod_p_asign_b //new_x = lambda² - 2x, in regs. sb0-sb3
STORE_TEMP256_FROM sb0 sb1 sb2 sb3 //new_x is in temporary memory
//Calculate new_y = lambda*(x - new_x) - y
//x-x_new
LOAD_POINT_DX_INTO sa0 sa1 sa2 sa3
bl sub_a_b_mod_p_asign_a //x-new_x in regs. sa0-sa3
LOAD_LAMBDA_INTO sb0 sb1 sb2 sb3
bl mul_a_b_mod_p_asign_a //lambda*(x-new_x) in regs. sa0-7
LOAD_POINT_DY_INTO sb0 sb1 sb2 sb3
bl sub_a_b_mod_p_asign_a //new_y = lambda*(x - new_x) - y in regs. sa0-sa3
//store new_y in pointDy
STORE_POINT_DY_FROM sa0 sa1 sa2 sa3
//load new_x from temporary memory
LOAD_TEMP256_INTO sa0 sa1 sa2 sa3 //new_x
//store new_x in pointDx
STORE_POINT_DX_FROM sa0 sa1 sa2 sa3
.endm
/** wrapper function */
BEGIN_GLOBAL_FUNCTION double_point
double_point
END_GLOBAL_FUNCTION double_point
/**
C function
*/
BEGIN_C_FUNCTION secp256k1_double_point
INIT_PRIME_P
INIT_POINT_D_FROM io0
double_point
STORE_POINT_D_INTO io1
END_C_FUNCTION secp256k1_double_point
/**
C function
*/
BEGIN_C_FUNCTION secp256k1_double_point_asign
INIT_PRIME_P
INIT_POINT_D_FROM io0
double_point
STORE_POINT_D_INTO io0
END_C_FUNCTION secp256k1_double_point_asign
///**************************adding different points***************************
/*
Macro ADD_DIFFERENT_POINTS
input:
first point a in memory at label pointA
second point d in memory at label pointD
result:
r = a+d, in pointA
*/
.macro ADD_DIFFERENT_POINTS
//Calculate lambda
//dx-ax
LOAD_POINT_DX_INTO sa0 sa1 sa2 sa3
LOAD_POINT_AX_INTO sb0 sb1 sb2 sb3
bl sub_a_b_mod_p_asign_a //dx-ax in sa0-sa3
//invert dx-ax
bl invert_a_mod_p_into_b //inv(dx-ax) in sb0-sb3
STORE_TEMP256_FROM sb0 sb1 sb2 sb3 //temp storage for inv(dx-ax)
//dy-ay
LOAD_POINT_DY_INTO sa0 sa1 sa2 sa3
LOAD_POINT_AY_INTO sb0 sb1 sb2 sb3
bl sub_a_b_mod_p_asign_a //dy-ay in sa0-sa3
//(dy-ay)*inv(dx-ax)
LOAD_TEMP256_INTO sb0 sb1 sb2 sb3
//lambda = (y2-y1)*inv(io2-io1)
bl mul_a_b_mod_p_asign_a
STORE_LAMBDA_FROM sa0 sa1 sa2 sa3
//lambda²
bl square_a_mod_p_asign_a
STORE_LAMBDA2_FROM sa0 sa1 sa2 sa3
//Calculate rx
LOAD_POINT_AX_INTO sb0 sb1 sb2 sb3
//lambda²-ax
bl sub_a_b_mod_p_asign_a
//rx=lambda²-ax-dx
LOAD_POINT_DX_INTO sb0 sb1 sb2 sb3
bl sub_a_b_mod_p_asign_b //rx=lambda²-ax-dx in regs. sb0-sb3
LOAD_POINT_AX_INTO sa0 sa1 sa2 sa3 //ax
STORE_POINT_AX_FROM sb0 sb1 sb2 sb3//rx -> pointAx
bl sub_a_b_mod_p_asign_b//ax-rx now in sb0-sb3
LOAD_LAMBDA_INTO sa0 sa1 sa2 sa3
bl mul_a_b_mod_p_asign_a //lambda*(ax-rx) in sa0-sa3
LOAD_POINT_AY_INTO sb0 sb1 sb2 sb3
bl sub_a_b_mod_p_asign_a //ry = lambda*(ax-rx)-ay in regs sa0-sa3
STORE_POINT_AY_FROM sa0 sa1 sa2 sa3
.endm
/** wrapper function */
BEGIN_GLOBAL_FUNCTION add_different_points
INIT_PRIME_P
ADD_DIFFERENT_POINTS
END_GLOBAL_FUNCTION add_different_points
/*
The C-compatible function secp256k1_add_different_points
adds two points p1 and p2
p3 = p1 + p2
Input:
Address of p1 in io0
Address of p2 in io1
Output:
Result in io2
*/
BEGIN_C_FUNCTION secp256k1_add_different_points
INIT_PRIME_P
INIT_POINT_A_FROM io0
INIT_POINT_D_FROM io1
ADD_DIFFERENT_POINTS
STORE_POINT_A_INTO io2
END_C_FUNCTION secp256k1_add_different_points
//******************************point multiplication****************************
/**
Macro POINT_MUL_U64 multiplies a point with an u64 integer.
The point is expected in pointD.
The macro performs the following algorithm:
for(int i = 64, i > 0, i--){
if( (u64 & 1) == 1) {
if (FLAG_POINT_A == 0){
pointA = pointD;
FLAG_POINT_A = 1;
}else{
pointA = pointA + pointD;
}
}
pointD = pointD + pointD
u64 >>= 1
}
*/
.macro POINT_MUL_U64 u64
mov io3, #64 //init loop index
loop_mul\@:
cbz io3, exit\@ //if loop index is 0 go to exit
and io2, \u64, #1 //(u64 & 1) test least significant bit of u64
cbz io2, double_pointD\@ //bit is zero->double pointD and loop
//first bit is one: a = a*d mod p
//but test FLAG_POINT_A, if 0 then pointA is 0 and pointD has to be moved
//into pointA instead of added.
//test flag, 0-> pointA is empty
cbz FLAG_POINT_A, move_pointD_into_pointA\@ //FLAG is io1 !
//here FLAG_POINT_A is 1 -> pointA has a valid value
//-> add pointA and pointD
//and asign sum to pointA, then double pointD and loop
bl add_different_points
b double_pointD\@
move_pointD_into_pointA\@:
LOAD_POINT_DX_INTO sa0 sa1 sa2 sa3
STORE_POINT_AX_FROM sa0 sa1 sa2 sa3
LOAD_POINT_DY_INTO sa0 sa1 sa2 sa3
STORE_POINT_AY_FROM sa0 sa1 sa2 sa3
//now set flag to 1 because pointA is no longer empy
mov FLAG_POINT_A, #1
double_pointD\@:
bl double_point
lsr \u64, \u64, #1 //right shift u64
sub io3, io3, #1 //count down index
b loop_mul\@
exit\@:
//clear u64 !
mov \u64, xzr
.endm
/**
Macro POINT_MUL_SCALAR multiplies a point with Scalar k.
The point is expected in pointD.
The scalar k is expected in register sk0-sk3
The resulting point is in pointA
*/
.macro POINT_MUL_SCALAR
PUSH io1 io2
PUSH io3
INIT_PRIME_P
INIT_FLAG_POINT_A
POINT_MUL_U64 sk0
POINT_MUL_U64 sk1
POINT_MUL_U64 sk2
POINT_MUL_U64 sk3
POP io3
POP io1 io2
.endm
/** wrapper function */
BEGIN_GLOBAL_FUNCTION point_mul_scalar
POINT_MUL_SCALAR
END_GLOBAL_FUNCTION point_mul_scalar
/** Public C functions */
/**
The public C function secp256k1_point_mul
multipies scalar k with a point pt
r = k*pt
Input:
Address of pt: in io0
Address of k: in io1
Address of r: in io2
*/
BEGIN_C_FUNCTION secp256k1_point_mul
PUSH io2
INIT_POINT_D_FROM io0
LOAD_K io1
POINT_MUL_SCALAR
POP io2
STORE_POINT_A_INTO io2
END_C_FUNCTION secp256k1_point_mul
/**
The public C function secp256k1_point_mul_asign
multipies scalar k with a point pt and asigns the resulting point to pt
pt = k*pt
Input:
Address of pt: in io0
Address of k: in io1
*/
BEGIN_C_FUNCTION secp256k1_point_mul_asign
PUSH io0
INIT_POINT_D_FROM io0
LOAD_K io1
POINT_MUL_SCALAR
POP io0
STORE_POINT_A_INTO io0
END_C_FUNCTION secp256k1_point_mul_asign
/**
The public C function secp256k1_generator_mul
multipies scalar k with the generator point g
r = k*g
Input:
Address of k: in io0
Address of r: in io1
*/
BEGIN_C_FUNCTION secp256k1_generator_mul
PUSH io1
INIT_POINT_D_WITH_G
LOAD_K io0
POINT_MUL_SCALAR
POP io1
STORE_POINT_A_INTO io1
END_C_FUNCTION secp256k1_generator_mul
/**
The public C compatible function secp256k1_keypair_from_private_key
takes a KeyPair kp with a valid private key prk, calculates the public key puk
and stores it in the KeyPair.
kp.private_key = prk
puk = kp.private_key*G
kp.public_key = puk
Input:
io0 with address of Keypair with set private key
Output:
io0 with address of Keypair, with stored private and public key
*/
BEGIN_C_FUNCTION secp256k1_keypair_from_private_key
INIT_POINT_D_WITH_G
LOAD_K io0
POINT_MUL_SCALAR
add io0, io0, #32 //address of public key in KeyPair
STORE_POINT_A_INTO io0
END_C_FUNCTION secp256k1_keypair_from_private_key
/**
The function secp256k1_is_point_on_curve
tests whether a Point is on the curve.
This is the case if
y² = x³ + 7
Input:
Address of point in io0
Result:
in io0: 0 if point is on the curve, other wise 1
*/
BEGIN_C_FUNCTION secp256k1_is_point_on_curve
INIT_PRIME_P
INIT_POINT_D_FROM io0
LOAD_POINT_DX_INTO sa0 sa1 sa2 sa3
bl cube_a_mod_p_asign_b
//x³ is now in b (sb0, sb1, sb2, sb3)
LOAD_POINT_DY_INTO sa0 sa1 sa2 sa3
bl square_a_mod_p
//y² is now in r (sr0, sr1, sr2, sr3)
//Copy y² into k for temporary storage
COPY_INTO_K_FROM sr0 sr1 sr2 sr3
//set a = 7, add to b (x³) -> a = x³+7
SET_A_TO_7
bl add_a_b_mod_p_asign_a
//x³+7 is now in a
//x³+7 - y² must be 0
//move y² from k to b
COPY_K_INTO sb0 sb1 sb2 sb3
//y² is now in b
bl sub_a_b_mod_p
cbnz sr0, not_equal
cbnz sr1, not_equal
cbnz sr2, not_equal
cbnz sr3, not_equal
mov io0, xzr
b end_is_on_curve
not_equal:
mov io0, #1
end_is_on_curve:
END_C_FUNCTION secp256k1_is_point_on_curve
/**
Macro CALCULATE_Y_COORDINATES_FROM_X
calculates the two possible y-coordinates from the x-coordinate.
Input:
a (sa0-sa3): x-coordinate
Output:
a (sa0-sa3): even y-coordinate
b (sb0-sb3): odd y-coordinate
*/
.macro CALCULATE_Y_COORDINATES_FROM_X
bl cube_a_mod_p_asign_b
//x³ is now in b sb0...sb3
//add 7 to x³
SET_A_TO_7
bl add_a_b_mod_p_asign_a
//x³+7 is now in a sa0...sa3
//Calculate square root
bl squareroot_a_mod_p_asign_b
//square root is now in b (sb0...sb3)
//calculate -y = p - root
//move p into a sa0....sa3
COPY_P_INTO sa0 sa1 sa2 sa3
bl sub_a_b_mod_p //-y
//-y now in r_lo (sr0...sr3)
//Test squareroot in b is odd
and tmp4, sb0, #1
cbz tmp4, is_even\@
//b is odd: leave it in b, copy r_lo in a
COPY_R_LO_TO_A
b end_calculate_y\@
//b is even:
is_even\@:
COPY_B_TO_A
COPY_R_LO_TO_B
end_calculate_y\@:
.endm
/** wrapper function for macro*/
BEGIN_GLOBAL_FUNCTION calculate_y_coordinates_from_x
CALCULATE_Y_COORDINATES_FROM_X
END_GLOBAL_FUNCTION calculate_y_coordinates_from_x
/**
Function get_odd_y_coordinate_from_x_coordinate
calculates the odd y-coordinate from the x-coordinate.
Input:
a (sa0-sa3): x-coordinate
Output:
a (sa0-sa3): odd y-coordinate
*/
BEGIN_GLOBAL_FUNCTION get_odd_y_coordinate_from_x_coordinate
CALCULATE_Y_COORDINATES_FROM_X
COPY_B_TO_A
END_GLOBAL_FUNCTION get_odd_y_coordinate_from_x_coordinate
/**
Function get_odd_y_coordinate_from_x_coordinate
calculates the odd y-coordinate from the x-coordinate.
Input:
a (sa0-sa3): x-coordinate
Output:
a (sa0-sa3): even y-coordinate
*/
BEGIN_GLOBAL_FUNCTION get_even_y_coordinate_from_x_coordinate
CALCULATE_Y_COORDINATES_FROM_X
END_GLOBAL_FUNCTION get_even_y_coordinate_from_x_coordinate
/**
Calculates the y-coordinates from the x-coordinate of a point on the curve.
Input:
io0: Address of coordinate x
io1: Address of even y to be calculated
io2: Address of odd y to be calculated
*/
BEGIN_C_FUNCTION secp256k1_calculate_y_coordinates_from_x
INIT_PRIME_P
PUSH io1 io2 //Adresses of even and odd y-coordinate
LOAD_A
CALCULATE_Y_COORDINATES_FROM_X
POP io1 io2
STORE_A io1
STORE_B io2
END_C_FUNCTION secp256k1_calculate_y_coordinates_from_x
//*************** Functions for ECDSA signing and verification *************
.macro LOAD_SCALAR_U_INTO_K
adr tmp5, scalar_u
ldp sk0, sk1, [tmp5], #16
ldp sk2, sk3, [tmp5]
.endm
.macro STORE_SCALAR_U_FROM_A
adr tmp5, scalar_u
stp sa0, sa1, [tmp5], #16
stp sa2, sa3, [tmp5]
.endm
.macro STORE_SCALAR_V_FROM_A
adr tmp5, scalar_v
stp sa0, sa1, [tmp5], #16
stp sa2, sa3, [tmp5]
.endm
.macro STORE_SIG_R_FROM_A
adr tmp5, sig_r
stp sa0, sa1, [tmp5], #16
stp sa2, sa3, [tmp5]
.endm
.macro COPY_B_INTO_K
mov sk0, sb0
mov sk1, sb1
mov sk2, sb2
mov sk3, sb3
.endm
/**
Function secp256k1_sign
signs a message
Input:
io0: Address of the private key of the signer
io1: Address of ephemeral KeyPair that must be used only once
io2: Address of message to be signed
io3: Address of Signature sig
*/
BEGIN_C_FUNCTION secp256k1_sign
INIT_ORDER_N
add tmp3, io1, #32 //address of ephemeral point.x
LOAD_B tmp3 //r = ephemeral point.x in b
mov tmp3, io3
STORE_B tmp3 //fill sig.r
LOAD_A io0 //private key in a
bl mul_a_b_mod_n_asign_a //private_key * point.x mod n in a
LOAD_B io2 //msg in b
bl add_a_b_mod_n_asign_a //msg + (private_key*point.x) mod n in a
PUSH sa0 sa1
PUSH sa2 sa3
LOAD_A io1 //ephemeral private_key in a
bl invert_a_mod_n_into_b //inverse of ephemeral private_key in b
POP sa2 sa3 //msg + (private_key*point.x) mod n in a
POP sa0 sa1
bl mul_a_b_mod_n_asign_a //s in a
bl normalize_s_in_a //Normalization of s: if s>n/2 -> s = n-s
add io3, io3, #32 //address of sig.s
STORE_A io3
END_C_FUNCTION secp256k1_sign
/**
Function secp256k1_verify
verifies a message
Input:
io0: Address of public key puk of signer
io1: Address of message msg to be verified
io2: Address of signature sig
Result:
io0: 0 -> message is verified, 1 -> message can not be verified
*/
BEGIN_C_FUNCTION secp256k1_verify
add tmp3, io2, #32 //address of sig.s
LOAD_A tmp3 // sig.s in a
bl invert_a_mod_n_into_b //s⁻¹ is now in b
LOAD_A io1 //msg in a
bl mul_a_b_mod_n_asign_a //u = msg*s⁻¹ in a
STORE_SCALAR_U_FROM_A //u in temporary storage scalar_u
LOAD_A io2 //sig.r in a
bl mul_a_b_mod_n_asign_b //v = sig.r*s⁻¹ in b
COPY_B_INTO_K //v now in k, ready for point mul
INIT_POINT_D_FROM io0 //puk now ready for multiplication with v
bl point_mul_scalar //the resulting point v*P is now in pointA
COPY_POINT_A_INTO_POINT_VP //temporary storage of v*P in point_vP
INIT_POINT_D_WITH_G //Prepare multiplication u*G
LOAD_SCALAR_U_INTO_K //u now in k, ready for point mul
bl point_mul_scalar //the resulting point u*G is now in pointA
COPY_POINT_VP_INTO_POINT_D //preparing addition of W = u*G + v*P
bl add_different_points //resulting point W is now in pointA
LOAD_POINT_AX_INTO sr0 sr1 sr2 sr3 //W.x in r_lo
bl reduce_r_mod_n //W.x mod n in r_lo
COPY_R_LO_TO_A //W.x in a
LOAD_B io2 //sig.r in b
bl sub_a_b_mod_n //diff = W.x - sig.r, in r_lo
//diff == 0 -> message can be verified
bl r_is_zero //result in io0: either 0 or 1
END_C_FUNCTION secp256k1_verify