blob: 10a179f1d0b8382bdc2e836eab5990e536258e20 [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
360 /* Actually, the required msb for private keys */
361 grp->nbits = 254;
362
363cleanup:
364 if( ret != 0 )
365 ecp_group_free( grp );
366
367 return( ret );
368}
369
370/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100371 * Set a group using well-known domain parameters
372 */
373int ecp_use_known_dp( ecp_group *grp, ecp_group_id id )
374{
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100375 ecp_group_free( grp );
376
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100377 grp->id = id;
378
379 switch( id )
380 {
381#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
382 case POLARSSL_ECP_DP_SECP192R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100383 NIST_MODP( p192 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100384 return( LOAD_GROUP( secp192r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100385#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
386
387#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
388 case POLARSSL_ECP_DP_SECP224R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100389 NIST_MODP( p224 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100390 return( LOAD_GROUP( secp224r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100391#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
392
393#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
394 case POLARSSL_ECP_DP_SECP256R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100395 NIST_MODP( p256 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100396 return( LOAD_GROUP( secp256r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100397#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
398
399#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
400 case POLARSSL_ECP_DP_SECP384R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100401 NIST_MODP( p384 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100402 return( LOAD_GROUP( secp384r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100403#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
404
405#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
406 case POLARSSL_ECP_DP_SECP521R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100407 NIST_MODP( p521 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100408 return( LOAD_GROUP( secp521r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100409#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
410
411#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
412 case POLARSSL_ECP_DP_BP256R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100413 return( LOAD_GROUP( brainpoolP256r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100414#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
415
416#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
417 case POLARSSL_ECP_DP_BP384R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100418 return( LOAD_GROUP( brainpoolP384r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100419#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
420
421#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
422 case POLARSSL_ECP_DP_BP512R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100423 return( LOAD_GROUP( brainpoolP512r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100424#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
425
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100426#if defined(POLARSSL_ECP_DP_M255_ENABLED)
427 case POLARSSL_ECP_DP_M255:
428 return( ecp_use_curve25519( grp ) );
429#endif /* POLARSSL_ECP_DP_M255_ENABLED */
430
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100431 default:
432 ecp_group_free( grp );
433 return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
434 }
435}
436
437#if defined(POLARSSL_ECP_NIST_OPTIM)
438/*
439 * Fast reduction modulo the primes used by the NIST curves.
440 *
441 * These functions are critical for speed, but not needed for correct
442 * operations. So, we make the choice to heavily rely on the internals of our
443 * bignum library, which creates a tight coupling between these functions and
444 * our MPI implementation. However, the coupling between the ECP module and
445 * MPI remains loose, since these functions can be deactivated at will.
446 */
447
448#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
449/*
450 * Compared to the way things are presented in FIPS 186-3 D.2,
451 * we proceed in columns, from right (least significant chunk) to left,
452 * adding chunks to N in place, and keeping a carry for the next chunk.
453 * This avoids moving things around in memory, and uselessly adding zeros,
454 * compared to the more straightforward, line-oriented approach.
455 *
456 * For this prime we need to handle data in chunks of 64 bits.
457 * Since this is always a multiple of our basic t_uint, we can
458 * use a t_uint * to designate such a chunk, and small loops to handle it.
459 */
460
461/* Add 64-bit chunks (dst += src) and update carry */
462static inline void add64( t_uint *dst, t_uint *src, t_uint *carry )
463{
464 unsigned char i;
465 t_uint c = 0;
466 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ )
467 {
468 *dst += c; c = ( *dst < c );
469 *dst += *src; c += ( *dst < *src );
470 }
471 *carry += c;
472}
473
474/* Add carry to a 64-bit chunk and update carry */
475static inline void carry64( t_uint *dst, t_uint *carry )
476{
477 unsigned char i;
478 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ )
479 {
480 *dst += *carry;
481 *carry = ( *dst < *carry );
482 }
483}
484
485#define WIDTH 8 / sizeof( t_uint )
486#define A( i ) N->p + i * WIDTH
487#define ADD( i ) add64( p, A( i ), &c )
488#define NEXT p += WIDTH; carry64( p, &c )
489#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0
490
491/*
492 * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
493 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100494static int ecp_mod_p192( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100495{
496 int ret;
497 t_uint c = 0;
498 t_uint *p, *end;
499
500 /* Make sure we have enough blocks so that A(5) is legal */
501 MPI_CHK( mpi_grow( N, 6 * WIDTH ) );
502
503 p = N->p;
504 end = p + N->n;
505
506 ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5
507 ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5
508 ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5
509
510cleanup:
511 return( ret );
512}
513
514#undef WIDTH
515#undef A
516#undef ADD
517#undef NEXT
518#undef LAST
519#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
520
521#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \
522 defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \
523 defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
524/*
525 * The reader is advised to first understand ecp_mod_p192() since the same
526 * general structure is used here, but with additional complications:
527 * (1) chunks of 32 bits, and (2) subtractions.
528 */
529
530/*
531 * For these primes, we need to handle data in chunks of 32 bits.
532 * This makes it more complicated if we use 64 bits limbs in MPI,
533 * which prevents us from using a uniform access method as for p192.
534 *
535 * So, we define a mini abstraction layer to access 32 bit chunks,
536 * load them in 'cur' for work, and store them back from 'cur' when done.
537 *
538 * While at it, also define the size of N in terms of 32-bit chunks.
539 */
540#define LOAD32 cur = A( i );
541
542#if defined(POLARSSL_HAVE_INT8) /* 8 bit */
543
544#define MAX32 N->n / 4
545#define A( j ) (uint32_t)( N->p[4*j+0] ) | \
546 ( N->p[4*j+1] << 8 ) | \
547 ( N->p[4*j+2] << 16 ) | \
548 ( N->p[4*j+3] << 24 )
549#define STORE32 N->p[4*i+0] = (t_uint)( cur ); \
550 N->p[4*i+1] = (t_uint)( cur >> 8 ); \
551 N->p[4*i+2] = (t_uint)( cur >> 16 ); \
552 N->p[4*i+3] = (t_uint)( cur >> 24 );
553
554#elif defined(POLARSSL_HAVE_INT16) /* 16 bit */
555
556#define MAX32 N->n / 2
557#define A( j ) (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 )
558#define STORE32 N->p[2*i+0] = (t_uint)( cur ); \
559 N->p[2*i+1] = (t_uint)( cur >> 16 );
560
561#elif defined(POLARSSL_HAVE_INT32) /* 32 bit */
562
563#define MAX32 N->n
564#define A( j ) N->p[j]
565#define STORE32 N->p[i] = cur;
566
567#else /* 64-bit */
568
569#define MAX32 N->n * 2
570#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] )
571#define STORE32 \
572 if( i % 2 ) { \
573 N->p[i/2] &= 0x00000000FFFFFFFF; \
574 N->p[i/2] |= ((t_uint) cur) << 32; \
575 } else { \
576 N->p[i/2] &= 0xFFFFFFFF00000000; \
577 N->p[i/2] |= (t_uint) cur; \
578 }
579
580#endif /* sizeof( t_uint ) */
581
582/*
583 * Helpers for addition and subtraction of chunks, with signed carry.
584 */
585static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
586{
587 *dst += src;
588 *carry += ( *dst < src );
589}
590
591static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
592{
593 *carry -= ( *dst < src );
594 *dst -= src;
595}
596
597#define ADD( j ) add32( &cur, A( j ), &c );
598#define SUB( j ) sub32( &cur, A( j ), &c );
599
600/*
601 * Helpers for the main 'loop'
602 * (see fix_negative for the motivation of C)
603 */
604#define INIT( b ) \
605 int ret; \
606 signed char c = 0, cc; \
607 uint32_t cur; \
608 size_t i = 0, bits = b; \
609 mpi C; \
610 t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ]; \
611 \
612 C.s = 1; \
613 C.n = b / 8 / sizeof( t_uint) + 1; \
614 C.p = Cp; \
615 memset( Cp, 0, C.n * sizeof( t_uint ) ); \
616 \
617 MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \
618 LOAD32;
619
620#define NEXT \
621 STORE32; i++; LOAD32; \
622 cc = c; c = 0; \
623 if( cc < 0 ) \
624 sub32( &cur, -cc, &c ); \
625 else \
626 add32( &cur, cc, &c ); \
627
628#define LAST \
629 STORE32; i++; \
630 cur = c > 0 ? c : 0; STORE32; \
631 cur = 0; while( ++i < MAX32 ) { STORE32; } \
632 if( c < 0 ) fix_negative( N, c, &C, bits );
633
634/*
635 * If the result is negative, we get it in the form
636 * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
637 */
638static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits )
639{
640 int ret;
641
642 /* C = - c * 2^(bits + 32) */
643#if !defined(POLARSSL_HAVE_INT64)
644 ((void) bits);
645#else
646 if( bits == 224 )
647 C->p[ C->n - 1 ] = ((t_uint) -c) << 32;
648 else
649#endif
650 C->p[ C->n - 1 ] = (t_uint) -c;
651
652 /* N = - ( C - N ) */
653 MPI_CHK( mpi_sub_abs( N, C, N ) );
654 N->s = -1;
655
656cleanup:
657
658 return( ret );
659}
660
661#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
662/*
663 * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
664 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100665static int ecp_mod_p224( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100666{
667 INIT( 224 );
668
669 SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11
670 SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12
671 SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13
672 SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11
673 SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12
674 SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13
675 SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10
676
677cleanup:
678 return( ret );
679}
680#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
681
682#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
683/*
684 * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
685 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100686static int ecp_mod_p256( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100687{
688 INIT( 256 );
689
690 ADD( 8 ); ADD( 9 );
691 SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0
692
693 ADD( 9 ); ADD( 10 );
694 SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1
695
696 ADD( 10 ); ADD( 11 );
697 SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2
698
699 ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
700 SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3
701
702 ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
703 SUB( 9 ); SUB( 10 ); NEXT; // A4
704
705 ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
706 SUB( 10 ); SUB( 11 ); NEXT; // A5
707
708 ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
709 SUB( 8 ); SUB( 9 ); NEXT; // A6
710
711 ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
712 SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7
713
714cleanup:
715 return( ret );
716}
717#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
718
719#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
720/*
721 * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
722 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100723static int ecp_mod_p384( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100724{
725 INIT( 384 );
726
727 ADD( 12 ); ADD( 21 ); ADD( 20 );
728 SUB( 23 ); NEXT; // A0
729
730 ADD( 13 ); ADD( 22 ); ADD( 23 );
731 SUB( 12 ); SUB( 20 ); NEXT; // A2
732
733 ADD( 14 ); ADD( 23 );
734 SUB( 13 ); SUB( 21 ); NEXT; // A2
735
736 ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
737 SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3
738
739 ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
740 SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4
741
742 ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
743 SUB( 16 ); NEXT; // A5
744
745 ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
746 SUB( 17 ); NEXT; // A6
747
748 ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
749 SUB( 18 ); NEXT; // A7
750
751 ADD( 20 ); ADD( 17 ); ADD( 16 );
752 SUB( 19 ); NEXT; // A8
753
754 ADD( 21 ); ADD( 18 ); ADD( 17 );
755 SUB( 20 ); NEXT; // A9
756
757 ADD( 22 ); ADD( 19 ); ADD( 18 );
758 SUB( 21 ); NEXT; // A10
759
760 ADD( 23 ); ADD( 20 ); ADD( 19 );
761 SUB( 22 ); LAST; // A11
762
763cleanup:
764 return( ret );
765}
766#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
767
768#undef A
769#undef LOAD32
770#undef STORE32
771#undef MAX32
772#undef INIT
773#undef NEXT
774#undef LAST
775
776#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED ||
777 POLARSSL_ECP_DP_SECP256R1_ENABLED ||
778 POLARSSL_ECP_DP_SECP384R1_ENABLED */
779
780#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
781/*
782 * Here we have an actual Mersenne prime, so things are more straightforward.
783 * However, chunks are aligned on a 'weird' boundary (521 bits).
784 */
785
786/* Size of p521 in terms of t_uint */
787#define P521_WIDTH ( 521 / 8 / sizeof( t_uint ) + 1 )
788
789/* Bits to keep in the most significant t_uint */
790#if defined(POLARSSL_HAVE_INT8)
791#define P521_MASK 0x01
792#else
793#define P521_MASK 0x01FF
794#endif
795
796/*
797 * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
798 * Write N as A1 + 2^521 A0, return A0 + A1
799 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100800static int ecp_mod_p521( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100801{
802 int ret;
803 size_t i;
804 mpi M;
805 t_uint Mp[P521_WIDTH + 1];
806 /* Worst case for the size of M is when t_uint is 16 bits:
807 * we need to hold bits 513 to 1056, which is 34 limbs, that is
808 * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
809
810 if( N->n < P521_WIDTH )
811 return( 0 );
812
813 /* M = A1 */
814 M.s = 1;
815 M.n = N->n - ( P521_WIDTH - 1 );
816 if( M.n > P521_WIDTH + 1 )
817 M.n = P521_WIDTH + 1;
818 M.p = Mp;
819 memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) );
820 MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) );
821
822 /* N = A0 */
823 N->p[P521_WIDTH - 1] &= P521_MASK;
824 for( i = P521_WIDTH; i < N->n; i++ )
825 N->p[i] = 0;
826
827 /* N = A0 + A1 */
828 MPI_CHK( mpi_add_abs( N, N, &M ) );
829
830cleanup:
831 return( ret );
832}
833
834#undef P521_WIDTH
835#undef P521_MASK
836#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
837
838#endif /* POLARSSL_ECP_NIST_OPTIM */
839
840#endif