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