]> git.cryptolib.org Git - avr-crypto-lib.git/blob - ecdsa/nist_p192.c
nist P-192 optimized recude for ecdsa
[avr-crypto-lib.git] / ecdsa / nist_p192.c
1 /* p192.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006-2012 Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <inttypes.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "bigint.h"
25
26 /*
27  * p = 6277101735386680763835789423207666416083908700390324961279
28  *   = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF
29  */
30
31 static
32 uint8_t nist_curve_p192_p_w[] = {
33         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
34         0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
35         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
36 };
37
38 bigint_t nist_curve_p192_p = {
39         .length_W = 192 / BIGINT_WORD_SIZE,
40         .wordv = nist_curve_p192_p_w,
41         .info = 7
42 };
43
44 /*
45  * A = ( A5 || A4 || A3 || A2 || A1 || A0 ) ; An if 64-bit
46  * A mod p = B = T + S1 + S2 + S3 mod p
47  *
48  * T  = ( A2 || A1 || A0 )
49  * S1 = ( A3 || A3 )
50  * S2 = ( A4 || A4 || 0 )
51  * S3 = ( A5 || A5 || A5 )
52  *
53  */
54
55 int bigint_reduce_p192(bigint_t *a){
56
57     bigint_word_t s_w[3 * 64 / BIGINT_WORD_SIZE];
58     bigint_t s;
59     uint16_t o_length;
60
61     o_length = a->length_W;
62
63     if(o_length < 192 / BIGINT_WORD_SIZE){
64         return 0;
65     }
66
67     if(o_length > 192 * 2 / BIGINT_WORD_SIZE){
68         bigint_reduce(a, &nist_curve_p192_p);
69     }
70
71     if(o_length > 192 / BIGINT_WORD_SIZE){
72         s.wordv = s_w;
73         s.length_W = 2 * 64 / BIGINT_WORD_SIZE;
74
75         /*
76          * copy A3 twice in s
77          */
78         if(o_length >= 4 * 64 / BIGINT_WORD_SIZE){
79             memcpy(s.wordv, a->wordv + 3 * 64 / BIGINT_WORD_SIZE, 64 / 8);
80         }else{
81             memset(s.wordv, 0, 8);
82             memcpy(s.wordv, a->wordv + 3 * 64 / BIGINT_WORD_SIZE,
83                     o_length * BIGINT_WORD_SIZE / 8 - 3 * 64 / 8);
84         }
85
86         memcpy(s.wordv + 64 / BIGINT_WORD_SIZE, s.wordv, 64 / 8);
87         bigint_adjust(&s);
88
89         /*
90          * Set A3 to zero so we can use a as T
91          */
92         memset(a->wordv + 3 * 64 / BIGINT_WORD_SIZE, 0, BIGINT_WORD_SIZE / 8);
93         a->length_W = 3 * 64 / BIGINT_WORD_SIZE;
94         bigint_adjust(a);
95
96         /*
97          * Add s (alias S1) to a (alias T)
98          */
99         bigint_add_u(a, a, &s);
100
101
102         if(o_length > 4 * 64 / BIGINT_WORD_SIZE){
103             /*
104              * copy A4 twice in s
105              */
106             if(o_length >= 5 * 64 / BIGINT_WORD_SIZE){
107                 memcpy(s.wordv, a->wordv + 4 * 64 / BIGINT_WORD_SIZE, 64 / 8);
108             }else{
109                 memset(s.wordv, 0, 8);
110                 memcpy(s.wordv, a->wordv + 4 * 64 / BIGINT_WORD_SIZE,
111                         o_length * BIGINT_WORD_SIZE / 8 - 4 * 64 / 8);
112             }
113             memcpy(s.wordv + 64 / BIGINT_WORD_SIZE, s.wordv, 64 / 8);
114             bigint_adjust(&s);
115
116             /*
117              * Add s (alias S2) to a (alias T + S1)
118              */
119             bigint_add_scale_u(a, &s, 8);
120
121
122             if(o_length > 5 * 64 / BIGINT_WORD_SIZE){
123                 /*
124                  * copy A5 three times in s
125                  */
126                 if(o_length == 6 * 64 / BIGINT_WORD_SIZE){
127                     memcpy(s.wordv, a->wordv + 5 * 64 / BIGINT_WORD_SIZE, 64 / 8);
128                 } else {
129                     memset(s.wordv, 0, 8);
130                     memcpy(s.wordv, a->wordv + 5 * 64 / BIGINT_WORD_SIZE,
131                             o_length * BIGINT_WORD_SIZE / 8 - 5 * 64 / 8);
132                 }
133                 memcpy(s.wordv + 64 / BIGINT_WORD_SIZE, s.wordv, 64 / 8);
134                 memcpy(s.wordv + 2 * 64 / BIGINT_WORD_SIZE, s.wordv, 64 / 8);
135                 s.length_W = 3 * 64 / BIGINT_WORD_SIZE;
136                 bigint_adjust(&s);
137
138                 /*
139                  * Add s (alias S2) to a (alias T + S1)
140                  */
141                 bigint_add_u(a, a, &s);
142             }
143         }
144
145     }
146     while(bigint_cmp_u(a, &nist_curve_p192_p) >= 0){
147         bigint_sub_u(a, a, &nist_curve_p192_p);
148     }
149
150     return 0;
151 }
152