blob: 26d9e1efd01518a2c6dbe6bcb66e4d3f10e59061 [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é-Gonnard3d7053a2013-12-04 20:51:13 +0100325#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100326static int ecp_mod_p192( mpi * );
Manuel Pégourié-Gonnard3d7053a2013-12-04 20:51:13 +0100327#endif
328#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100329static int ecp_mod_p224( mpi * );
Manuel Pégourié-Gonnard3d7053a2013-12-04 20:51:13 +0100330#endif
331#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100332static int ecp_mod_p256( mpi * );
Manuel Pégourié-Gonnard3d7053a2013-12-04 20:51:13 +0100333#endif
334#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100335static int ecp_mod_p384( mpi * );
Manuel Pégourié-Gonnard3d7053a2013-12-04 20:51:13 +0100336#endif
337#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100338static int ecp_mod_p521( mpi * );
Manuel Pégourié-Gonnard3d7053a2013-12-04 20:51:13 +0100339#endif
340#if defined(POLARSSL_ECP_DP_M255_ENABLED)
341static int ecp_mod_p255( mpi * );
342#endif
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100343
344#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P;
345#else
346#define NIST_MODP( P )
Manuel Pégourié-Gonnard3d7053a2013-12-04 20:51:13 +0100347#endif /* POLARSSL_ECP_NIST_OPTIM */
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100348
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100349#define LOAD_GROUP( G ) ecp_group_read_binary( grp, \
350 G ## _p, sizeof( G ## _p ), \
351 G ## _a, sizeof( G ## _a ), \
352 G ## _b, sizeof( G ## _b ), \
353 G ## _gx, sizeof( G ## _gx ), \
354 G ## _gy, sizeof( G ## _gy ), \
355 G ## _n, sizeof( G ## _n ) )
356
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100357/*
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100358 * Specialized function for creating the Curve25519 group
359 */
360static int ecp_use_curve25519( ecp_group *grp )
361{
362 int ret;
363
364 /* Actually ( A + 2 ) / 4 */
365 MPI_CHK( mpi_read_string( &grp->A, 16, "01DB42" ) );
366
367 /* P = 2^255 - 19 */
368 MPI_CHK( mpi_lset( &grp->P, 1 ) );
369 MPI_CHK( mpi_shift_l( &grp->P, 255 ) );
370 MPI_CHK( mpi_sub_int( &grp->P, &grp->P, 19 ) );
371 grp->pbits = mpi_msb( &grp->P );
372
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100373 /* Y intentionaly not set, since we use x/z coordinates.
374 * This is used as a marker to identify Montgomery curves! */
375 MPI_CHK( mpi_lset( &grp->G.X, 9 ) );
376 MPI_CHK( mpi_lset( &grp->G.Z, 1 ) );
377 mpi_free( &grp->G.Y );
378
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100379 /* Actually, the required msb for private keys */
380 grp->nbits = 254;
381
382cleanup:
383 if( ret != 0 )
384 ecp_group_free( grp );
385
386 return( ret );
387}
388
389/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100390 * Set a group using well-known domain parameters
391 */
392int ecp_use_known_dp( ecp_group *grp, ecp_group_id id )
393{
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100394 ecp_group_free( grp );
395
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100396 grp->id = id;
397
398 switch( id )
399 {
400#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
401 case POLARSSL_ECP_DP_SECP192R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100402 NIST_MODP( p192 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100403 return( LOAD_GROUP( secp192r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100404#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
405
406#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
407 case POLARSSL_ECP_DP_SECP224R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100408 NIST_MODP( p224 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100409 return( LOAD_GROUP( secp224r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100410#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
411
412#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
413 case POLARSSL_ECP_DP_SECP256R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100414 NIST_MODP( p256 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100415 return( LOAD_GROUP( secp256r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100416#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
417
418#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
419 case POLARSSL_ECP_DP_SECP384R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100420 NIST_MODP( p384 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100421 return( LOAD_GROUP( secp384r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100422#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
423
424#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
425 case POLARSSL_ECP_DP_SECP521R1:
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100426 NIST_MODP( p521 );
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100427 return( LOAD_GROUP( secp521r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100428#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
429
430#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
431 case POLARSSL_ECP_DP_BP256R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100432 return( LOAD_GROUP( brainpoolP256r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100433#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
434
435#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
436 case POLARSSL_ECP_DP_BP384R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100437 return( LOAD_GROUP( brainpoolP384r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100438#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
439
440#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
441 case POLARSSL_ECP_DP_BP512R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100442 return( LOAD_GROUP( brainpoolP512r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100443#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
444
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100445#if defined(POLARSSL_ECP_DP_M255_ENABLED)
446 case POLARSSL_ECP_DP_M255:
Manuel Pégourié-Gonnard3d7053a2013-12-04 20:51:13 +0100447 grp->modp = ecp_mod_p255;
Manuel Pégourié-Gonnard66153662013-12-03 14:12:26 +0100448 return( ecp_use_curve25519( grp ) );
449#endif /* POLARSSL_ECP_DP_M255_ENABLED */
450
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100451 default:
452 ecp_group_free( grp );
453 return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
454 }
455}
456
457#if defined(POLARSSL_ECP_NIST_OPTIM)
458/*
459 * Fast reduction modulo the primes used by the NIST curves.
460 *
461 * These functions are critical for speed, but not needed for correct
462 * operations. So, we make the choice to heavily rely on the internals of our
463 * bignum library, which creates a tight coupling between these functions and
464 * our MPI implementation. However, the coupling between the ECP module and
465 * MPI remains loose, since these functions can be deactivated at will.
466 */
467
468#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
469/*
470 * Compared to the way things are presented in FIPS 186-3 D.2,
471 * we proceed in columns, from right (least significant chunk) to left,
472 * adding chunks to N in place, and keeping a carry for the next chunk.
473 * This avoids moving things around in memory, and uselessly adding zeros,
474 * compared to the more straightforward, line-oriented approach.
475 *
476 * For this prime we need to handle data in chunks of 64 bits.
477 * Since this is always a multiple of our basic t_uint, we can
478 * use a t_uint * to designate such a chunk, and small loops to handle it.
479 */
480
481/* Add 64-bit chunks (dst += src) and update carry */
482static inline void add64( t_uint *dst, t_uint *src, t_uint *carry )
483{
484 unsigned char i;
485 t_uint c = 0;
486 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ )
487 {
488 *dst += c; c = ( *dst < c );
489 *dst += *src; c += ( *dst < *src );
490 }
491 *carry += c;
492}
493
494/* Add carry to a 64-bit chunk and update carry */
495static inline void carry64( t_uint *dst, t_uint *carry )
496{
497 unsigned char i;
498 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ )
499 {
500 *dst += *carry;
501 *carry = ( *dst < *carry );
502 }
503}
504
505#define WIDTH 8 / sizeof( t_uint )
506#define A( i ) N->p + i * WIDTH
507#define ADD( i ) add64( p, A( i ), &c )
508#define NEXT p += WIDTH; carry64( p, &c )
509#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0
510
511/*
512 * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
513 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100514static int ecp_mod_p192( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100515{
516 int ret;
517 t_uint c = 0;
518 t_uint *p, *end;
519
520 /* Make sure we have enough blocks so that A(5) is legal */
521 MPI_CHK( mpi_grow( N, 6 * WIDTH ) );
522
523 p = N->p;
524 end = p + N->n;
525
526 ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5
527 ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5
528 ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5
529
530cleanup:
531 return( ret );
532}
533
534#undef WIDTH
535#undef A
536#undef ADD
537#undef NEXT
538#undef LAST
539#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
540
541#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \
542 defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \
543 defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
544/*
545 * The reader is advised to first understand ecp_mod_p192() since the same
546 * general structure is used here, but with additional complications:
547 * (1) chunks of 32 bits, and (2) subtractions.
548 */
549
550/*
551 * For these primes, we need to handle data in chunks of 32 bits.
552 * This makes it more complicated if we use 64 bits limbs in MPI,
553 * which prevents us from using a uniform access method as for p192.
554 *
555 * So, we define a mini abstraction layer to access 32 bit chunks,
556 * load them in 'cur' for work, and store them back from 'cur' when done.
557 *
558 * While at it, also define the size of N in terms of 32-bit chunks.
559 */
560#define LOAD32 cur = A( i );
561
562#if defined(POLARSSL_HAVE_INT8) /* 8 bit */
563
564#define MAX32 N->n / 4
565#define A( j ) (uint32_t)( N->p[4*j+0] ) | \
566 ( N->p[4*j+1] << 8 ) | \
567 ( N->p[4*j+2] << 16 ) | \
568 ( N->p[4*j+3] << 24 )
569#define STORE32 N->p[4*i+0] = (t_uint)( cur ); \
570 N->p[4*i+1] = (t_uint)( cur >> 8 ); \
571 N->p[4*i+2] = (t_uint)( cur >> 16 ); \
572 N->p[4*i+3] = (t_uint)( cur >> 24 );
573
574#elif defined(POLARSSL_HAVE_INT16) /* 16 bit */
575
576#define MAX32 N->n / 2
577#define A( j ) (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 )
578#define STORE32 N->p[2*i+0] = (t_uint)( cur ); \
579 N->p[2*i+1] = (t_uint)( cur >> 16 );
580
581#elif defined(POLARSSL_HAVE_INT32) /* 32 bit */
582
583#define MAX32 N->n
584#define A( j ) N->p[j]
585#define STORE32 N->p[i] = cur;
586
587#else /* 64-bit */
588
589#define MAX32 N->n * 2
590#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] )
591#define STORE32 \
592 if( i % 2 ) { \
593 N->p[i/2] &= 0x00000000FFFFFFFF; \
594 N->p[i/2] |= ((t_uint) cur) << 32; \
595 } else { \
596 N->p[i/2] &= 0xFFFFFFFF00000000; \
597 N->p[i/2] |= (t_uint) cur; \
598 }
599
600#endif /* sizeof( t_uint ) */
601
602/*
603 * Helpers for addition and subtraction of chunks, with signed carry.
604 */
605static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
606{
607 *dst += src;
608 *carry += ( *dst < src );
609}
610
611static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
612{
613 *carry -= ( *dst < src );
614 *dst -= src;
615}
616
617#define ADD( j ) add32( &cur, A( j ), &c );
618#define SUB( j ) sub32( &cur, A( j ), &c );
619
620/*
621 * Helpers for the main 'loop'
622 * (see fix_negative for the motivation of C)
623 */
624#define INIT( b ) \
625 int ret; \
626 signed char c = 0, cc; \
627 uint32_t cur; \
628 size_t i = 0, bits = b; \
629 mpi C; \
630 t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ]; \
631 \
632 C.s = 1; \
633 C.n = b / 8 / sizeof( t_uint) + 1; \
634 C.p = Cp; \
635 memset( Cp, 0, C.n * sizeof( t_uint ) ); \
636 \
637 MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \
638 LOAD32;
639
640#define NEXT \
641 STORE32; i++; LOAD32; \
642 cc = c; c = 0; \
643 if( cc < 0 ) \
644 sub32( &cur, -cc, &c ); \
645 else \
646 add32( &cur, cc, &c ); \
647
648#define LAST \
649 STORE32; i++; \
650 cur = c > 0 ? c : 0; STORE32; \
651 cur = 0; while( ++i < MAX32 ) { STORE32; } \
652 if( c < 0 ) fix_negative( N, c, &C, bits );
653
654/*
655 * If the result is negative, we get it in the form
656 * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
657 */
658static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits )
659{
660 int ret;
661
662 /* C = - c * 2^(bits + 32) */
663#if !defined(POLARSSL_HAVE_INT64)
664 ((void) bits);
665#else
666 if( bits == 224 )
667 C->p[ C->n - 1 ] = ((t_uint) -c) << 32;
668 else
669#endif
670 C->p[ C->n - 1 ] = (t_uint) -c;
671
672 /* N = - ( C - N ) */
673 MPI_CHK( mpi_sub_abs( N, C, N ) );
674 N->s = -1;
675
676cleanup:
677
678 return( ret );
679}
680
681#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
682/*
683 * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
684 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100685static int ecp_mod_p224( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100686{
687 INIT( 224 );
688
689 SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11
690 SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12
691 SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13
692 SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11
693 SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12
694 SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13
695 SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10
696
697cleanup:
698 return( ret );
699}
700#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
701
702#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
703/*
704 * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
705 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100706static int ecp_mod_p256( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100707{
708 INIT( 256 );
709
710 ADD( 8 ); ADD( 9 );
711 SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0
712
713 ADD( 9 ); ADD( 10 );
714 SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1
715
716 ADD( 10 ); ADD( 11 );
717 SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2
718
719 ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
720 SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3
721
722 ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
723 SUB( 9 ); SUB( 10 ); NEXT; // A4
724
725 ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
726 SUB( 10 ); SUB( 11 ); NEXT; // A5
727
728 ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
729 SUB( 8 ); SUB( 9 ); NEXT; // A6
730
731 ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
732 SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7
733
734cleanup:
735 return( ret );
736}
737#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
738
739#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
740/*
741 * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
742 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100743static int ecp_mod_p384( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100744{
745 INIT( 384 );
746
747 ADD( 12 ); ADD( 21 ); ADD( 20 );
748 SUB( 23 ); NEXT; // A0
749
750 ADD( 13 ); ADD( 22 ); ADD( 23 );
751 SUB( 12 ); SUB( 20 ); NEXT; // A2
752
753 ADD( 14 ); ADD( 23 );
754 SUB( 13 ); SUB( 21 ); NEXT; // A2
755
756 ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
757 SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3
758
759 ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
760 SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4
761
762 ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
763 SUB( 16 ); NEXT; // A5
764
765 ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
766 SUB( 17 ); NEXT; // A6
767
768 ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
769 SUB( 18 ); NEXT; // A7
770
771 ADD( 20 ); ADD( 17 ); ADD( 16 );
772 SUB( 19 ); NEXT; // A8
773
774 ADD( 21 ); ADD( 18 ); ADD( 17 );
775 SUB( 20 ); NEXT; // A9
776
777 ADD( 22 ); ADD( 19 ); ADD( 18 );
778 SUB( 21 ); NEXT; // A10
779
780 ADD( 23 ); ADD( 20 ); ADD( 19 );
781 SUB( 22 ); LAST; // A11
782
783cleanup:
784 return( ret );
785}
786#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
787
788#undef A
789#undef LOAD32
790#undef STORE32
791#undef MAX32
792#undef INIT
793#undef NEXT
794#undef LAST
795
796#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED ||
797 POLARSSL_ECP_DP_SECP256R1_ENABLED ||
798 POLARSSL_ECP_DP_SECP384R1_ENABLED */
799
800#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
801/*
802 * Here we have an actual Mersenne prime, so things are more straightforward.
803 * However, chunks are aligned on a 'weird' boundary (521 bits).
804 */
805
806/* Size of p521 in terms of t_uint */
807#define P521_WIDTH ( 521 / 8 / sizeof( t_uint ) + 1 )
808
809/* Bits to keep in the most significant t_uint */
810#if defined(POLARSSL_HAVE_INT8)
811#define P521_MASK 0x01
812#else
813#define P521_MASK 0x01FF
814#endif
815
816/*
817 * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
818 * Write N as A1 + 2^521 A0, return A0 + A1
819 */
Manuel Pégourié-Gonnard3ee90002013-12-02 17:14:48 +0100820static int ecp_mod_p521( mpi *N )
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100821{
822 int ret;
823 size_t i;
824 mpi M;
825 t_uint Mp[P521_WIDTH + 1];
826 /* Worst case for the size of M is when t_uint is 16 bits:
827 * we need to hold bits 513 to 1056, which is 34 limbs, that is
828 * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
829
830 if( N->n < P521_WIDTH )
831 return( 0 );
832
833 /* M = A1 */
834 M.s = 1;
835 M.n = N->n - ( P521_WIDTH - 1 );
836 if( M.n > P521_WIDTH + 1 )
837 M.n = P521_WIDTH + 1;
838 M.p = Mp;
839 memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) );
840 MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) );
841
842 /* N = A0 */
843 N->p[P521_WIDTH - 1] &= P521_MASK;
844 for( i = P521_WIDTH; i < N->n; i++ )
845 N->p[i] = 0;
846
847 /* N = A0 + A1 */
848 MPI_CHK( mpi_add_abs( N, N, &M ) );
849
850cleanup:
851 return( ret );
852}
853
854#undef P521_WIDTH
855#undef P521_MASK
856#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
857
858#endif /* POLARSSL_ECP_NIST_OPTIM */
859
Manuel Pégourié-Gonnard3d7053a2013-12-04 20:51:13 +0100860#if defined(POLARSSL_ECP_DP_M255_ENABLED)
861
862/* Size of p255 in terms of t_uint */
863#define P255_WIDTH ( 255 / 8 / sizeof( t_uint ) + 1 )
864
865/*
866 * Fast quasi-reduction modulo p255 = 2^255 - 19
867 * Write N as A1 + 2^255 A1, return A0 + 19 * A1
868 */
869static int ecp_mod_p255( mpi *N )
870{
871 int ret;
872 size_t i;
873 mpi M;
874 t_uint Mp[P255_WIDTH + 2];
875
876 if( N->n < P255_WIDTH )
877 return( 0 );
878
879 /* M = A1 */
880 M.s = 1;
881 M.n = N->n - ( P255_WIDTH - 1 );
882 if( M.n > P255_WIDTH + 1 )
883 M.n = P255_WIDTH + 1;
884 M.p = Mp;
885 memset( Mp, 0, sizeof Mp );
886 memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( t_uint ) );
887 MPI_CHK( mpi_shift_r( &M, 255 % ( 8 * sizeof( t_uint ) ) ) );
888 M.n++; /* Make room for multiplication by 19 */
889
890 /* N = A0 */
891 mpi_set_bit( N, 255, 0 );
892 for( i = P255_WIDTH; i < N->n; i++ )
893 N->p[i] = 0;
894
895 /* N = A0 + 19 * A1 */
896 MPI_CHK( mpi_mul_int( &M, &M, 19 ) );
897 MPI_CHK( mpi_add_abs( N, N, &M ) );
898
899cleanup:
900 return( ret );
901}
902#endif /* POLARSSL_ECP_DP_M255_ENABLED */
903
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100904#endif