blob: 542589f6678ddfc6527f8daa991324a6bf1b8de8 [file] [log] [blame]
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +01001/*
2 * Elliptic curves over GF(p): curve-specific data and functions
3 *
4 * Copyright (C) 2006-2013, Brainspark B.V.
5 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#include "polarssl/config.h"
27
28#if defined(POLARSSL_ECP_C)
29
30#include "polarssl/ecp.h"
31
Paul Bakker498fd352013-12-02 22:17:24 +010032#if defined(_MSC_VER) && !defined(inline)
33#define inline _inline
34#else
35#if defined(__ARMCC_VERSION) && !defined(inline)
36#define inline __inline
37#endif /* __ARMCC_VERSION */
38#endif /*_MSC_VER */
39
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +010040/*
41 * Domain parameters for secp192r1
42 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +010043static unsigned char secp192r1_p[] = {
44 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
45 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
46static unsigned char *secp192r1_a = NULL;
47static unsigned char secp192r1_b[] = {
48 0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB,
49 0x72, 0x24, 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1 };
50static unsigned char secp192r1_gx[] = {
51 0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB,
52 0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12 };
53static unsigned char secp192r1_gy[] = {
54 0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78, 0x63, 0x10, 0x11, 0xED,
55 0x6B, 0x24, 0xCD, 0xD5, 0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11 };
56static unsigned char secp192r1_n[] = {
57 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
58 0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +010059
60/*
61 * Domain parameters for secp224r1
62 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +010063static unsigned char secp224r1_p[] = {
64 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
65 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x01 };
67static unsigned char *secp224r1_a = NULL;
68static unsigned char secp224r1_b[] = {
69 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
70 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
71 0x23, 0x55, 0xFF, 0xB4 };
72static unsigned char secp224r1_gx[] = {
73 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
74 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
75 0x11, 0x5C, 0x1D, 0x21 };
76static unsigned char secp224r1_gy[] = {
77 0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6,
78 0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99,
79 0x85, 0x00, 0x7E, 0x34 };
80static unsigned char secp224r1_n[] = {
81 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
82 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
83 0x5C, 0x5C, 0x2A, 0x3D };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +010084
85/*
86 * Domain parameters for secp256r1
87 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +010088static unsigned char secp256r1_p[] = {
89 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
91 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
92static unsigned char *secp256r1_a = NULL;
93static unsigned char secp256r1_b[] = {
94 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
95 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
96 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B };
97static unsigned char secp256r1_gx[] = {
98 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
99 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
100 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 };
101static unsigned char secp256r1_gy[] = {
102 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
103 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
104 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
105static unsigned char secp256r1_n[] = {
106 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
107 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
108 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100109
110/*
111 * Domain parameters for secp384r1
112 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100113static unsigned char secp384r1_p[] = {
114 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
115 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
118static unsigned char *secp384r1_a = NULL;
119static unsigned char secp384r1_b[] = {
120 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
121 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
122 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
123 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF };
124static unsigned char secp384r1_gx[] = {
125 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
126 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
127 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
128 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 };
129static unsigned char secp384r1_gy[] = {
130 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
131 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
132 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
133 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
134static unsigned char secp384r1_n[] = {
135 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
136 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
137 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
138 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100139
140/*
141 * Domain parameters for secp521r1
142 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100143static unsigned char secp521r1_p[] = {
144 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
145 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
146 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
147 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
148 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
149 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
150static unsigned char *secp521r1_a = NULL;
151static unsigned char secp521r1_b[] = {
152 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
153 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
154 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
155 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
156 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
157 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 };
158static unsigned char secp521r1_gx[] = {
159 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
160 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
161 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
162 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
163 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
164 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 };
165static unsigned char secp521r1_gy[] = {
166 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
167 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
168 0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
169 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
170 0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
171 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50 };
172static unsigned char secp521r1_n[] = {
173 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
174 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
175 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
176 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
177 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
178 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100179
180/*
181 * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
182 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100183static unsigned char brainpoolP256r1_p[] = {
184 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90,
185 0x9D, 0x83, 0x8D, 0x72, 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
186 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77 };
187static unsigned char brainpoolP256r1_a[] = {
188 0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57, 0xEE, 0xF6, 0x75, 0x30,
189 0x41, 0x7A, 0xFF, 0xE7, 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C,
190 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9 };
191static unsigned char brainpoolP256r1_b[] = {
192 0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9,
193 0xBB, 0xD7, 0x7C, 0xBF, 0x95, 0x84, 0x16, 0x29, 0x5C, 0xF7, 0xE1, 0xCE,
194 0x6B, 0xCC, 0xDC, 0x18, 0xFF, 0x8C, 0x07, 0xB6 };
195static unsigned char brainpoolP256r1_gx[] = {
196 0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB, 0x2C, 0x4B, 0x48, 0x2F,
197 0xFC, 0x81, 0xB7, 0xAF, 0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2,
198 0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62 };
199static unsigned char brainpoolP256r1_gy[] = {
200 0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD, 0x97, 0xF8, 0x46, 0x1A,
201 0x14, 0x61, 0x1D, 0xC9, 0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54,
202 0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97 };
203static unsigned char brainpoolP256r1_n[] = {
204 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90,
205 0x9D, 0x83, 0x8D, 0x71, 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
206 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100207
208/*
209 * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
210 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100211static unsigned char brainpoolP384r1_p[] = {
212 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,
213 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4,
214 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7, 0x29,
215 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53 };
216static unsigned char brainpoolP384r1_a[] = {
217 0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08, 0x0A,
218 0xCE, 0x05, 0xAF, 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87,
219 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, 0x8A, 0xA5, 0x81, 0x4A,
220 0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26 };
221static unsigned char brainpoolP384r1_b[] = {
222 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54,
223 0x16, 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6,
224 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, 0x7C, 0xB4, 0x39, 0x02,
225 0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11 };
226static unsigned char brainpoolP384r1_gx[] = {
227 0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A, 0x81,
228 0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3,
229 0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26, 0xE0, 0x34,
230 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E };
231static unsigned char brainpoolP384r1_gy[] = {
232 0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB, 0x8E,
233 0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64,
234 0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46, 0x46, 0x21,
235 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15 };
236static unsigned char brainpoolP384r1_n[] = {
237 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,
238 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3,
239 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A, 0xB6, 0xAF,
240 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100241
242/*
243 * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
244 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100245static unsigned char brainpoolP512r1_p[] = {
246 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE,
247 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E,
248 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x71, 0x7D, 0x4D, 0x9B, 0x00,
249 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3, 0x80, 0xE6,
250 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60, 0x56,
251 0x58, 0x3A, 0x48, 0xF3 };
252static unsigned char brainpoolP512r1_a[] = {
253 0x78, 0x30, 0xA3, 0x31, 0x8B, 0x60, 0x3B, 0x89, 0xE2, 0x32, 0x71, 0x45,
254 0xAC, 0x23, 0x4C, 0xC5, 0x94, 0xCB, 0xDD, 0x8D, 0x3D, 0xF9, 0x16, 0x10,
255 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, 0x2D, 0xED, 0x5D, 0x5A,
256 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5,
257 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D,
258 0x77, 0xFC, 0x94, 0xCA };
259static unsigned char brainpoolP512r1_b[] = {
260 0x3D, 0xF9, 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC,
261 0x2D, 0xED, 0x5D, 0x5A, 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9,
262 0x8B, 0x9A, 0xC8, 0xB5, 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9,
263 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA, 0xDC, 0x08, 0x3E, 0x67,
264 0x98, 0x40, 0x50, 0xB7, 0x5E, 0xBA, 0xE5, 0xDD, 0x28, 0x09, 0xBD, 0x63,
265 0x80, 0x16, 0xF7, 0x23 };
266static unsigned char brainpoolP512r1_gx[] = {
267 0x81, 0xAE, 0xE4, 0xBD, 0xD8, 0x2E, 0xD9, 0x64, 0x5A, 0x21, 0x32, 0x2E,
268 0x9C, 0x4C, 0x6A, 0x93, 0x85, 0xED, 0x9F, 0x70, 0xB5, 0xD9, 0x16, 0xC1,
269 0xB4, 0x3B, 0x62, 0xEE, 0xF4, 0xD0, 0x09, 0x8E, 0xFF, 0x3B, 0x1F, 0x78,
270 0xE2, 0xD0, 0xD4, 0x8D, 0x50, 0xD1, 0x68, 0x7B, 0x93, 0xB9, 0x7D, 0x5F,
271 0x7C, 0x6D, 0x50, 0x47, 0x40, 0x6A, 0x5E, 0x68, 0x8B, 0x35, 0x22, 0x09,
272 0xBC, 0xB9, 0xF8, 0x22 };
273static unsigned char brainpoolP512r1_gy[] = {
274 0x7D, 0xDE, 0x38, 0x5D, 0x56, 0x63, 0x32, 0xEC, 0xC0, 0xEA, 0xBF, 0xA9,
275 0xCF, 0x78, 0x22, 0xFD, 0xF2, 0x09, 0xF7, 0x00, 0x24, 0xA5, 0x7B, 0x1A,
276 0xA0, 0x00, 0xC5, 0x5B, 0x88, 0x1F, 0x81, 0x11, 0xB2, 0xDC, 0xDE, 0x49,
277 0x4A, 0x5F, 0x48, 0x5E, 0x5B, 0xCA, 0x4B, 0xD8, 0x8A, 0x27, 0x63, 0xAE,
278 0xD1, 0xCA, 0x2B, 0x2F, 0xA8, 0xF0, 0x54, 0x06, 0x78, 0xCD, 0x1E, 0x0F,
279 0x3A, 0xD8, 0x08, 0x92 };
280static unsigned char brainpoolP512r1_n[] = {
281 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE,
282 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E,
283 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x70, 0x55, 0x3E, 0x5C, 0x41,
284 0x4C, 0xA9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7F, 0xAC, 0x10, 0x47,
285 0x1D, 0xB1, 0xD3, 0x81, 0x08, 0x5D, 0xDA, 0xDD, 0xB5, 0x87, 0x96, 0x82,
286 0x9C, 0xA9, 0x00, 0x69 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100287
288/*
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100289 * Import an ECP group from binary
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100290 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100291static int ecp_group_read_binary( ecp_group *grp,
292 const unsigned char *p, size_t plen,
293 const unsigned char *a, size_t alen,
294 const unsigned char *b, size_t blen,
295 const unsigned char *gx, size_t gxlen,
296 const unsigned char *gy, size_t gylen,
297 const unsigned char *n, size_t nlen)
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100298{
299 int ret;
300
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100301 MPI_CHK( mpi_read_binary( &grp->P, p, plen ) );
302 if( a != NULL )
303 MPI_CHK( mpi_read_binary( &grp->A, a, alen ) );
304 else
305 MPI_CHK( mpi_sub_int( &grp->A, &grp->P, 3 ) );
306 MPI_CHK( mpi_read_binary( &grp->B, b, blen ) );
307 MPI_CHK( mpi_read_binary( &grp->N, n, nlen ) );
308
309 MPI_CHK( mpi_read_binary( &grp->G.X, gx, gxlen ) );
310 MPI_CHK( mpi_read_binary( &grp->G.Y, gy, gylen ) );
311 MPI_CHK( mpi_lset( &grp->G.Z, 1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100312
313 grp->pbits = mpi_msb( &grp->P );
314 grp->nbits = mpi_msb( &grp->N );
315
316cleanup:
317 if( ret != 0 )
318 ecp_group_free( grp );
319
320 return( ret );
321}
322
323#if defined(POLARSSL_ECP_NIST_OPTIM)
324/* Forward declarations */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100325static int ecp_mod_p192( mpi * );
326static int ecp_mod_p224( mpi * );
327static int ecp_mod_p256( mpi * );
328static int ecp_mod_p384( mpi * );
329static int ecp_mod_p521( mpi * );
330
331#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P;
332#else
333#define NIST_MODP( P )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100334#endif
335
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100336#define LOAD_GROUP( G ) ecp_group_read_binary( grp, \
337 G ## _p, sizeof( G ## _p ), \
338 G ## _a, sizeof( G ## _a ), \
339 G ## _b, sizeof( G ## _b ), \
340 G ## _gx, sizeof( G ## _gx ), \
341 G ## _gy, sizeof( G ## _gy ), \
342 G ## _n, sizeof( G ## _n ) )
343
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100344/*
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100345 * Specialized function for creating the Curve25519 group
346 */
347static int ecp_use_curve25519( ecp_group *grp )
348{
349 int ret;
350
351 /* Actually ( A + 2 ) / 4 */
352 MPI_CHK( mpi_read_string( &grp->A, 16, "01DB42" ) );
353
354 /* P = 2^255 - 19 */
355 MPI_CHK( mpi_lset( &grp->P, 1 ) );
356 MPI_CHK( mpi_shift_l( &grp->P, 255 ) );
357 MPI_CHK( mpi_sub_int( &grp->P, &grp->P, 19 ) );
358 grp->pbits = mpi_msb( &grp->P );
359
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100360 /* Y intentionaly not set, since we use x/z coordinates.
361 * This is used as a marker to identify Montgomery curves! */
362 MPI_CHK( mpi_lset( &grp->G.X, 9 ) );
363 MPI_CHK( mpi_lset( &grp->G.Z, 1 ) );
364 mpi_free( &grp->G.Y );
365
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100366 /* Actually, the required msb for private keys */
367 grp->nbits = 254;
368
369cleanup:
370 if( ret != 0 )
371 ecp_group_free( grp );
372
373 return( ret );
374}
375
376/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100377 * Set a group using well-known domain parameters
378 */
379int ecp_use_known_dp( ecp_group *grp, ecp_group_id id )
380{
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100381 ecp_group_free( grp );
382
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100383 grp->id = id;
384
385 switch( id )
386 {
387#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
388 case POLARSSL_ECP_DP_SECP192R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100389 NIST_MODP( p192 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100390 return( LOAD_GROUP( secp192r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100391#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
392
393#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
394 case POLARSSL_ECP_DP_SECP224R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100395 NIST_MODP( p224 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100396 return( LOAD_GROUP( secp224r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100397#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
398
399#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
400 case POLARSSL_ECP_DP_SECP256R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100401 NIST_MODP( p256 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100402 return( LOAD_GROUP( secp256r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100403#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
404
405#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
406 case POLARSSL_ECP_DP_SECP384R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100407 NIST_MODP( p384 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100408 return( LOAD_GROUP( secp384r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100409#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
410
411#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
412 case POLARSSL_ECP_DP_SECP521R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100413 NIST_MODP( p521 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100414 return( LOAD_GROUP( secp521r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100415#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
416
417#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
418 case POLARSSL_ECP_DP_BP256R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100419 return( LOAD_GROUP( brainpoolP256r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100420#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
421
422#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
423 case POLARSSL_ECP_DP_BP384R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100424 return( LOAD_GROUP( brainpoolP384r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100425#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
426
427#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
428 case POLARSSL_ECP_DP_BP512R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100429 return( LOAD_GROUP( brainpoolP512r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100430#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
431
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100432#if defined(POLARSSL_ECP_DP_M255_ENABLED)
433 case POLARSSL_ECP_DP_M255:
434 return( ecp_use_curve25519( grp ) );
435#endif /* POLARSSL_ECP_DP_M255_ENABLED */
436
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100437 default:
438 ecp_group_free( grp );
439 return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
440 }
441}
442
443#if defined(POLARSSL_ECP_NIST_OPTIM)
444/*
445 * Fast reduction modulo the primes used by the NIST curves.
446 *
447 * These functions are critical for speed, but not needed for correct
448 * operations. So, we make the choice to heavily rely on the internals of our
449 * bignum library, which creates a tight coupling between these functions and
450 * our MPI implementation. However, the coupling between the ECP module and
451 * MPI remains loose, since these functions can be deactivated at will.
452 */
453
454#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
455/*
456 * Compared to the way things are presented in FIPS 186-3 D.2,
457 * we proceed in columns, from right (least significant chunk) to left,
458 * adding chunks to N in place, and keeping a carry for the next chunk.
459 * This avoids moving things around in memory, and uselessly adding zeros,
460 * compared to the more straightforward, line-oriented approach.
461 *
462 * For this prime we need to handle data in chunks of 64 bits.
463 * Since this is always a multiple of our basic t_uint, we can
464 * use a t_uint * to designate such a chunk, and small loops to handle it.
465 */
466
467/* Add 64-bit chunks (dst += src) and update carry */
468static inline void add64( t_uint *dst, t_uint *src, t_uint *carry )
469{
470 unsigned char i;
471 t_uint c = 0;
472 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ )
473 {
474 *dst += c; c = ( *dst < c );
475 *dst += *src; c += ( *dst < *src );
476 }
477 *carry += c;
478}
479
480/* Add carry to a 64-bit chunk and update carry */
481static inline void carry64( t_uint *dst, t_uint *carry )
482{
483 unsigned char i;
484 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ )
485 {
486 *dst += *carry;
487 *carry = ( *dst < *carry );
488 }
489}
490
491#define WIDTH 8 / sizeof( t_uint )
492#define A( i ) N->p + i * WIDTH
493#define ADD( i ) add64( p, A( i ), &c )
494#define NEXT p += WIDTH; carry64( p, &c )
495#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0
496
497/*
498 * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
499 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100500static int ecp_mod_p192( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100501{
502 int ret;
503 t_uint c = 0;
504 t_uint *p, *end;
505
506 /* Make sure we have enough blocks so that A(5) is legal */
507 MPI_CHK( mpi_grow( N, 6 * WIDTH ) );
508
509 p = N->p;
510 end = p + N->n;
511
512 ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5
513 ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5
514 ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5
515
516cleanup:
517 return( ret );
518}
519
520#undef WIDTH
521#undef A
522#undef ADD
523#undef NEXT
524#undef LAST
525#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
526
527#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \
528 defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \
529 defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
530/*
531 * The reader is advised to first understand ecp_mod_p192() since the same
532 * general structure is used here, but with additional complications:
533 * (1) chunks of 32 bits, and (2) subtractions.
534 */
535
536/*
537 * For these primes, we need to handle data in chunks of 32 bits.
538 * This makes it more complicated if we use 64 bits limbs in MPI,
539 * which prevents us from using a uniform access method as for p192.
540 *
541 * So, we define a mini abstraction layer to access 32 bit chunks,
542 * load them in 'cur' for work, and store them back from 'cur' when done.
543 *
544 * While at it, also define the size of N in terms of 32-bit chunks.
545 */
546#define LOAD32 cur = A( i );
547
548#if defined(POLARSSL_HAVE_INT8) /* 8 bit */
549
550#define MAX32 N->n / 4
551#define A( j ) (uint32_t)( N->p[4*j+0] ) | \
552 ( N->p[4*j+1] << 8 ) | \
553 ( N->p[4*j+2] << 16 ) | \
554 ( N->p[4*j+3] << 24 )
555#define STORE32 N->p[4*i+0] = (t_uint)( cur ); \
556 N->p[4*i+1] = (t_uint)( cur >> 8 ); \
557 N->p[4*i+2] = (t_uint)( cur >> 16 ); \
558 N->p[4*i+3] = (t_uint)( cur >> 24 );
559
560#elif defined(POLARSSL_HAVE_INT16) /* 16 bit */
561
562#define MAX32 N->n / 2
563#define A( j ) (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 )
564#define STORE32 N->p[2*i+0] = (t_uint)( cur ); \
565 N->p[2*i+1] = (t_uint)( cur >> 16 );
566
567#elif defined(POLARSSL_HAVE_INT32) /* 32 bit */
568
569#define MAX32 N->n
570#define A( j ) N->p[j]
571#define STORE32 N->p[i] = cur;
572
573#else /* 64-bit */
574
575#define MAX32 N->n * 2
576#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] )
577#define STORE32 \
578 if( i % 2 ) { \
579 N->p[i/2] &= 0x00000000FFFFFFFF; \
580 N->p[i/2] |= ((t_uint) cur) << 32; \
581 } else { \
582 N->p[i/2] &= 0xFFFFFFFF00000000; \
583 N->p[i/2] |= (t_uint) cur; \
584 }
585
586#endif /* sizeof( t_uint ) */
587
588/*
589 * Helpers for addition and subtraction of chunks, with signed carry.
590 */
591static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
592{
593 *dst += src;
594 *carry += ( *dst < src );
595}
596
597static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
598{
599 *carry -= ( *dst < src );
600 *dst -= src;
601}
602
603#define ADD( j ) add32( &cur, A( j ), &c );
604#define SUB( j ) sub32( &cur, A( j ), &c );
605
606/*
607 * Helpers for the main 'loop'
608 * (see fix_negative for the motivation of C)
609 */
610#define INIT( b ) \
611 int ret; \
612 signed char c = 0, cc; \
613 uint32_t cur; \
614 size_t i = 0, bits = b; \
615 mpi C; \
616 t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ]; \
617 \
618 C.s = 1; \
619 C.n = b / 8 / sizeof( t_uint) + 1; \
620 C.p = Cp; \
621 memset( Cp, 0, C.n * sizeof( t_uint ) ); \
622 \
623 MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \
624 LOAD32;
625
626#define NEXT \
627 STORE32; i++; LOAD32; \
628 cc = c; c = 0; \
629 if( cc < 0 ) \
630 sub32( &cur, -cc, &c ); \
631 else \
632 add32( &cur, cc, &c ); \
633
634#define LAST \
635 STORE32; i++; \
636 cur = c > 0 ? c : 0; STORE32; \
637 cur = 0; while( ++i < MAX32 ) { STORE32; } \
638 if( c < 0 ) fix_negative( N, c, &C, bits );
639
640/*
641 * If the result is negative, we get it in the form
642 * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
643 */
644static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits )
645{
646 int ret;
647
648 /* C = - c * 2^(bits + 32) */
649#if !defined(POLARSSL_HAVE_INT64)
650 ((void) bits);
651#else
652 if( bits == 224 )
653 C->p[ C->n - 1 ] = ((t_uint) -c) << 32;
654 else
655#endif
656 C->p[ C->n - 1 ] = (t_uint) -c;
657
658 /* N = - ( C - N ) */
659 MPI_CHK( mpi_sub_abs( N, C, N ) );
660 N->s = -1;
661
662cleanup:
663
664 return( ret );
665}
666
667#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
668/*
669 * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
670 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100671static int ecp_mod_p224( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100672{
673 INIT( 224 );
674
675 SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11
676 SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12
677 SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13
678 SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11
679 SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12
680 SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13
681 SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10
682
683cleanup:
684 return( ret );
685}
686#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
687
688#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
689/*
690 * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
691 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100692static int ecp_mod_p256( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100693{
694 INIT( 256 );
695
696 ADD( 8 ); ADD( 9 );
697 SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0
698
699 ADD( 9 ); ADD( 10 );
700 SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1
701
702 ADD( 10 ); ADD( 11 );
703 SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2
704
705 ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
706 SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3
707
708 ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
709 SUB( 9 ); SUB( 10 ); NEXT; // A4
710
711 ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
712 SUB( 10 ); SUB( 11 ); NEXT; // A5
713
714 ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
715 SUB( 8 ); SUB( 9 ); NEXT; // A6
716
717 ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
718 SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7
719
720cleanup:
721 return( ret );
722}
723#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
724
725#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
726/*
727 * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
728 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100729static int ecp_mod_p384( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100730{
731 INIT( 384 );
732
733 ADD( 12 ); ADD( 21 ); ADD( 20 );
734 SUB( 23 ); NEXT; // A0
735
736 ADD( 13 ); ADD( 22 ); ADD( 23 );
737 SUB( 12 ); SUB( 20 ); NEXT; // A2
738
739 ADD( 14 ); ADD( 23 );
740 SUB( 13 ); SUB( 21 ); NEXT; // A2
741
742 ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
743 SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3
744
745 ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
746 SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4
747
748 ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
749 SUB( 16 ); NEXT; // A5
750
751 ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
752 SUB( 17 ); NEXT; // A6
753
754 ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
755 SUB( 18 ); NEXT; // A7
756
757 ADD( 20 ); ADD( 17 ); ADD( 16 );
758 SUB( 19 ); NEXT; // A8
759
760 ADD( 21 ); ADD( 18 ); ADD( 17 );
761 SUB( 20 ); NEXT; // A9
762
763 ADD( 22 ); ADD( 19 ); ADD( 18 );
764 SUB( 21 ); NEXT; // A10
765
766 ADD( 23 ); ADD( 20 ); ADD( 19 );
767 SUB( 22 ); LAST; // A11
768
769cleanup:
770 return( ret );
771}
772#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
773
774#undef A
775#undef LOAD32
776#undef STORE32
777#undef MAX32
778#undef INIT
779#undef NEXT
780#undef LAST
781
782#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED ||
783 POLARSSL_ECP_DP_SECP256R1_ENABLED ||
784 POLARSSL_ECP_DP_SECP384R1_ENABLED */
785
786#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
787/*
788 * Here we have an actual Mersenne prime, so things are more straightforward.
789 * However, chunks are aligned on a 'weird' boundary (521 bits).
790 */
791
792/* Size of p521 in terms of t_uint */
793#define P521_WIDTH ( 521 / 8 / sizeof( t_uint ) + 1 )
794
795/* Bits to keep in the most significant t_uint */
796#if defined(POLARSSL_HAVE_INT8)
797#define P521_MASK 0x01
798#else
799#define P521_MASK 0x01FF
800#endif
801
802/*
803 * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
804 * Write N as A1 + 2^521 A0, return A0 + A1
805 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100806static int ecp_mod_p521( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100807{
808 int ret;
809 size_t i;
810 mpi M;
811 t_uint Mp[P521_WIDTH + 1];
812 /* Worst case for the size of M is when t_uint is 16 bits:
813 * we need to hold bits 513 to 1056, which is 34 limbs, that is
814 * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
815
816 if( N->n < P521_WIDTH )
817 return( 0 );
818
819 /* M = A1 */
820 M.s = 1;
821 M.n = N->n - ( P521_WIDTH - 1 );
822 if( M.n > P521_WIDTH + 1 )
823 M.n = P521_WIDTH + 1;
824 M.p = Mp;
825 memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) );
826 MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) );
827
828 /* N = A0 */
829 N->p[P521_WIDTH - 1] &= P521_MASK;
830 for( i = P521_WIDTH; i < N->n; i++ )
831 N->p[i] = 0;
832
833 /* N = A0 + A1 */
834 MPI_CHK( mpi_add_abs( N, N, &M ) );
835
836cleanup:
837 return( ret );
838}
839
840#undef P521_WIDTH
841#undef P521_MASK
842#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
843
844#endif /* POLARSSL_ECP_NIST_OPTIM */
845
846#endif