blob: 87edbb7081b82bca0bbdbb22d2a692698d8c7dec [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
32/*
33 * Domain parameters for secp192r1
34 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +010035static unsigned char secp192r1_p[] = {
36 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
37 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
38static unsigned char *secp192r1_a = NULL;
39static unsigned char secp192r1_b[] = {
40 0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB,
41 0x72, 0x24, 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1 };
42static unsigned char secp192r1_gx[] = {
43 0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB,
44 0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12 };
45static unsigned char secp192r1_gy[] = {
46 0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78, 0x63, 0x10, 0x11, 0xED,
47 0x6B, 0x24, 0xCD, 0xD5, 0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11 };
48static unsigned char secp192r1_n[] = {
49 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
50 0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +010051
52/*
53 * Domain parameters for secp224r1
54 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +010055static unsigned char secp224r1_p[] = {
56 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
57 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x01 };
59static unsigned char *secp224r1_a = NULL;
60static unsigned char secp224r1_b[] = {
61 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
62 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
63 0x23, 0x55, 0xFF, 0xB4 };
64static unsigned char secp224r1_gx[] = {
65 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
66 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
67 0x11, 0x5C, 0x1D, 0x21 };
68static unsigned char secp224r1_gy[] = {
69 0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6,
70 0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99,
71 0x85, 0x00, 0x7E, 0x34 };
72static unsigned char secp224r1_n[] = {
73 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
74 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
75 0x5C, 0x5C, 0x2A, 0x3D };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +010076
77/*
78 * Domain parameters for secp256r1
79 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +010080static unsigned char secp256r1_p[] = {
81 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
83 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
84static unsigned char *secp256r1_a = NULL;
85static unsigned char secp256r1_b[] = {
86 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
87 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
88 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B };
89static unsigned char secp256r1_gx[] = {
90 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
91 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
92 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 };
93static unsigned char secp256r1_gy[] = {
94 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
95 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
96 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
97static unsigned char secp256r1_n[] = {
98 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
99 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
100 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100101
102/*
103 * Domain parameters for secp384r1
104 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100105static unsigned char secp384r1_p[] = {
106 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
107 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
108 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
110static unsigned char *secp384r1_a = NULL;
111static unsigned char secp384r1_b[] = {
112 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
113 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
114 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
115 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF };
116static unsigned char secp384r1_gx[] = {
117 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
118 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
119 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
120 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 };
121static unsigned char secp384r1_gy[] = {
122 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
123 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
124 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
125 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
126static unsigned char secp384r1_n[] = {
127 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
128 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
129 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
130 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100131
132/*
133 * Domain parameters for secp521r1
134 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100135static unsigned char secp521r1_p[] = {
136 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
137 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
138 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
139 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
140 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
141 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
142static unsigned char *secp521r1_a = NULL;
143static unsigned char secp521r1_b[] = {
144 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
145 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
146 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
147 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
148 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
149 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 };
150static unsigned char secp521r1_gx[] = {
151 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
152 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
153 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
154 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
155 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
156 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 };
157static unsigned char secp521r1_gy[] = {
158 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
159 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
160 0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
161 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
162 0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
163 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50 };
164static unsigned char secp521r1_n[] = {
165 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
166 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
167 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
168 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
169 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
170 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100171
172/*
173 * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
174 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100175static unsigned char brainpoolP256r1_p[] = {
176 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90,
177 0x9D, 0x83, 0x8D, 0x72, 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
178 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77 };
179static unsigned char brainpoolP256r1_a[] = {
180 0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57, 0xEE, 0xF6, 0x75, 0x30,
181 0x41, 0x7A, 0xFF, 0xE7, 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C,
182 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9 };
183static unsigned char brainpoolP256r1_b[] = {
184 0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9,
185 0xBB, 0xD7, 0x7C, 0xBF, 0x95, 0x84, 0x16, 0x29, 0x5C, 0xF7, 0xE1, 0xCE,
186 0x6B, 0xCC, 0xDC, 0x18, 0xFF, 0x8C, 0x07, 0xB6 };
187static unsigned char brainpoolP256r1_gx[] = {
188 0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB, 0x2C, 0x4B, 0x48, 0x2F,
189 0xFC, 0x81, 0xB7, 0xAF, 0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2,
190 0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62 };
191static unsigned char brainpoolP256r1_gy[] = {
192 0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD, 0x97, 0xF8, 0x46, 0x1A,
193 0x14, 0x61, 0x1D, 0xC9, 0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54,
194 0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97 };
195static unsigned char brainpoolP256r1_n[] = {
196 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90,
197 0x9D, 0x83, 0x8D, 0x71, 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
198 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100199
200/*
201 * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
202 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100203static unsigned char brainpoolP384r1_p[] = {
204 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,
205 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4,
206 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7, 0x29,
207 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53 };
208static unsigned char brainpoolP384r1_a[] = {
209 0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08, 0x0A,
210 0xCE, 0x05, 0xAF, 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87,
211 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, 0x8A, 0xA5, 0x81, 0x4A,
212 0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26 };
213static unsigned char brainpoolP384r1_b[] = {
214 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54,
215 0x16, 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6,
216 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, 0x7C, 0xB4, 0x39, 0x02,
217 0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11 };
218static unsigned char brainpoolP384r1_gx[] = {
219 0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A, 0x81,
220 0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3,
221 0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26, 0xE0, 0x34,
222 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E };
223static unsigned char brainpoolP384r1_gy[] = {
224 0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB, 0x8E,
225 0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64,
226 0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46, 0x46, 0x21,
227 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15 };
228static unsigned char brainpoolP384r1_n[] = {
229 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,
230 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3,
231 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A, 0xB6, 0xAF,
232 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100233
234/*
235 * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
236 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100237static unsigned char brainpoolP512r1_p[] = {
238 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE,
239 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E,
240 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x71, 0x7D, 0x4D, 0x9B, 0x00,
241 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3, 0x80, 0xE6,
242 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60, 0x56,
243 0x58, 0x3A, 0x48, 0xF3 };
244static unsigned char brainpoolP512r1_a[] = {
245 0x78, 0x30, 0xA3, 0x31, 0x8B, 0x60, 0x3B, 0x89, 0xE2, 0x32, 0x71, 0x45,
246 0xAC, 0x23, 0x4C, 0xC5, 0x94, 0xCB, 0xDD, 0x8D, 0x3D, 0xF9, 0x16, 0x10,
247 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, 0x2D, 0xED, 0x5D, 0x5A,
248 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5,
249 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D,
250 0x77, 0xFC, 0x94, 0xCA };
251static unsigned char brainpoolP512r1_b[] = {
252 0x3D, 0xF9, 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC,
253 0x2D, 0xED, 0x5D, 0x5A, 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9,
254 0x8B, 0x9A, 0xC8, 0xB5, 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9,
255 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA, 0xDC, 0x08, 0x3E, 0x67,
256 0x98, 0x40, 0x50, 0xB7, 0x5E, 0xBA, 0xE5, 0xDD, 0x28, 0x09, 0xBD, 0x63,
257 0x80, 0x16, 0xF7, 0x23 };
258static unsigned char brainpoolP512r1_gx[] = {
259 0x81, 0xAE, 0xE4, 0xBD, 0xD8, 0x2E, 0xD9, 0x64, 0x5A, 0x21, 0x32, 0x2E,
260 0x9C, 0x4C, 0x6A, 0x93, 0x85, 0xED, 0x9F, 0x70, 0xB5, 0xD9, 0x16, 0xC1,
261 0xB4, 0x3B, 0x62, 0xEE, 0xF4, 0xD0, 0x09, 0x8E, 0xFF, 0x3B, 0x1F, 0x78,
262 0xE2, 0xD0, 0xD4, 0x8D, 0x50, 0xD1, 0x68, 0x7B, 0x93, 0xB9, 0x7D, 0x5F,
263 0x7C, 0x6D, 0x50, 0x47, 0x40, 0x6A, 0x5E, 0x68, 0x8B, 0x35, 0x22, 0x09,
264 0xBC, 0xB9, 0xF8, 0x22 };
265static unsigned char brainpoolP512r1_gy[] = {
266 0x7D, 0xDE, 0x38, 0x5D, 0x56, 0x63, 0x32, 0xEC, 0xC0, 0xEA, 0xBF, 0xA9,
267 0xCF, 0x78, 0x22, 0xFD, 0xF2, 0x09, 0xF7, 0x00, 0x24, 0xA5, 0x7B, 0x1A,
268 0xA0, 0x00, 0xC5, 0x5B, 0x88, 0x1F, 0x81, 0x11, 0xB2, 0xDC, 0xDE, 0x49,
269 0x4A, 0x5F, 0x48, 0x5E, 0x5B, 0xCA, 0x4B, 0xD8, 0x8A, 0x27, 0x63, 0xAE,
270 0xD1, 0xCA, 0x2B, 0x2F, 0xA8, 0xF0, 0x54, 0x06, 0x78, 0xCD, 0x1E, 0x0F,
271 0x3A, 0xD8, 0x08, 0x92 };
272static unsigned char brainpoolP512r1_n[] = {
273 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE,
274 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E,
275 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x70, 0x55, 0x3E, 0x5C, 0x41,
276 0x4C, 0xA9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7F, 0xAC, 0x10, 0x47,
277 0x1D, 0xB1, 0xD3, 0x81, 0x08, 0x5D, 0xDA, 0xDD, 0xB5, 0x87, 0x96, 0x82,
278 0x9C, 0xA9, 0x00, 0x69 };
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100279
280/*
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100281 * Import an ECP group from binary
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100282 */
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100283static int ecp_group_read_binary( ecp_group *grp,
284 const unsigned char *p, size_t plen,
285 const unsigned char *a, size_t alen,
286 const unsigned char *b, size_t blen,
287 const unsigned char *gx, size_t gxlen,
288 const unsigned char *gy, size_t gylen,
289 const unsigned char *n, size_t nlen)
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100290{
291 int ret;
292
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100293 MPI_CHK( mpi_read_binary( &grp->P, p, plen ) );
294 if( a != NULL )
295 MPI_CHK( mpi_read_binary( &grp->A, a, alen ) );
296 else
297 MPI_CHK( mpi_sub_int( &grp->A, &grp->P, 3 ) );
298 MPI_CHK( mpi_read_binary( &grp->B, b, blen ) );
299 MPI_CHK( mpi_read_binary( &grp->N, n, nlen ) );
300
301 MPI_CHK( mpi_read_binary( &grp->G.X, gx, gxlen ) );
302 MPI_CHK( mpi_read_binary( &grp->G.Y, gy, gylen ) );
303 MPI_CHK( mpi_lset( &grp->G.Z, 1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100304
305 grp->pbits = mpi_msb( &grp->P );
306 grp->nbits = mpi_msb( &grp->N );
307
308cleanup:
309 if( ret != 0 )
310 ecp_group_free( grp );
311
312 return( ret );
313}
314
315#if defined(POLARSSL_ECP_NIST_OPTIM)
316/* Forward declarations */
317int ecp_mod_p192( mpi * );
318int ecp_mod_p224( mpi * );
319int ecp_mod_p256( mpi * );
320int ecp_mod_p384( mpi * );
321int ecp_mod_p521( mpi * );
322#endif
323
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100324#define LOAD_GROUP( G ) ecp_group_read_binary( grp, \
325 G ## _p, sizeof( G ## _p ), \
326 G ## _a, sizeof( G ## _a ), \
327 G ## _b, sizeof( G ## _b ), \
328 G ## _gx, sizeof( G ## _gx ), \
329 G ## _gy, sizeof( G ## _gy ), \
330 G ## _n, sizeof( G ## _n ) )
331
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100332/*
333 * Set a group using well-known domain parameters
334 */
335int ecp_use_known_dp( ecp_group *grp, ecp_group_id id )
336{
337 grp->id = id;
338
339 switch( id )
340 {
341#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
342 case POLARSSL_ECP_DP_SECP192R1:
343#if defined(POLARSSL_ECP_NIST_OPTIM)
344 grp->modp = ecp_mod_p192;
345#endif
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100346 return( LOAD_GROUP( secp192r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100347#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
348
349#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
350 case POLARSSL_ECP_DP_SECP224R1:
351#if defined(POLARSSL_ECP_NIST_OPTIM)
352 grp->modp = ecp_mod_p224;
353#endif
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100354 return( LOAD_GROUP( secp224r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100355#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
356
357#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
358 case POLARSSL_ECP_DP_SECP256R1:
359#if defined(POLARSSL_ECP_NIST_OPTIM)
360 grp->modp = ecp_mod_p256;
361#endif
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100362 return( LOAD_GROUP( secp256r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100363#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
364
365#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
366 case POLARSSL_ECP_DP_SECP384R1:
367#if defined(POLARSSL_ECP_NIST_OPTIM)
368 grp->modp = ecp_mod_p384;
369#endif
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100370 return( LOAD_GROUP( secp384r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100371#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
372
373#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
374 case POLARSSL_ECP_DP_SECP521R1:
375#if defined(POLARSSL_ECP_NIST_OPTIM)
376 grp->modp = ecp_mod_p521;
377#endif
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100378 return( LOAD_GROUP( secp521r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100379#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
380
381#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
382 case POLARSSL_ECP_DP_BP256R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100383 return( LOAD_GROUP( brainpoolP256r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100384#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
385
386#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
387 case POLARSSL_ECP_DP_BP384R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100388 return( LOAD_GROUP( brainpoolP384r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100389#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
390
391#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
392 case POLARSSL_ECP_DP_BP512R1:
Manuel Pégourié-Gonnard9854fe92013-12-02 16:30:43 +0100393 return( LOAD_GROUP( brainpoolP512r1 ) );
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +0100394#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
395
396 default:
397 ecp_group_free( grp );
398 return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
399 }
400}
401
402#if defined(POLARSSL_ECP_NIST_OPTIM)
403/*
404 * Fast reduction modulo the primes used by the NIST curves.
405 *
406 * These functions are critical for speed, but not needed for correct
407 * operations. So, we make the choice to heavily rely on the internals of our
408 * bignum library, which creates a tight coupling between these functions and
409 * our MPI implementation. However, the coupling between the ECP module and
410 * MPI remains loose, since these functions can be deactivated at will.
411 */
412
413#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
414/*
415 * Compared to the way things are presented in FIPS 186-3 D.2,
416 * we proceed in columns, from right (least significant chunk) to left,
417 * adding chunks to N in place, and keeping a carry for the next chunk.
418 * This avoids moving things around in memory, and uselessly adding zeros,
419 * compared to the more straightforward, line-oriented approach.
420 *
421 * For this prime we need to handle data in chunks of 64 bits.
422 * Since this is always a multiple of our basic t_uint, we can
423 * use a t_uint * to designate such a chunk, and small loops to handle it.
424 */
425
426/* Add 64-bit chunks (dst += src) and update carry */
427static inline void add64( t_uint *dst, t_uint *src, t_uint *carry )
428{
429 unsigned char i;
430 t_uint c = 0;
431 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ )
432 {
433 *dst += c; c = ( *dst < c );
434 *dst += *src; c += ( *dst < *src );
435 }
436 *carry += c;
437}
438
439/* Add carry to a 64-bit chunk and update carry */
440static inline void carry64( t_uint *dst, t_uint *carry )
441{
442 unsigned char i;
443 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ )
444 {
445 *dst += *carry;
446 *carry = ( *dst < *carry );
447 }
448}
449
450#define WIDTH 8 / sizeof( t_uint )
451#define A( i ) N->p + i * WIDTH
452#define ADD( i ) add64( p, A( i ), &c )
453#define NEXT p += WIDTH; carry64( p, &c )
454#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0
455
456/*
457 * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
458 */
459int ecp_mod_p192( mpi *N )
460{
461 int ret;
462 t_uint c = 0;
463 t_uint *p, *end;
464
465 /* Make sure we have enough blocks so that A(5) is legal */
466 MPI_CHK( mpi_grow( N, 6 * WIDTH ) );
467
468 p = N->p;
469 end = p + N->n;
470
471 ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5
472 ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5
473 ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5
474
475cleanup:
476 return( ret );
477}
478
479#undef WIDTH
480#undef A
481#undef ADD
482#undef NEXT
483#undef LAST
484#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
485
486#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \
487 defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \
488 defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
489/*
490 * The reader is advised to first understand ecp_mod_p192() since the same
491 * general structure is used here, but with additional complications:
492 * (1) chunks of 32 bits, and (2) subtractions.
493 */
494
495/*
496 * For these primes, we need to handle data in chunks of 32 bits.
497 * This makes it more complicated if we use 64 bits limbs in MPI,
498 * which prevents us from using a uniform access method as for p192.
499 *
500 * So, we define a mini abstraction layer to access 32 bit chunks,
501 * load them in 'cur' for work, and store them back from 'cur' when done.
502 *
503 * While at it, also define the size of N in terms of 32-bit chunks.
504 */
505#define LOAD32 cur = A( i );
506
507#if defined(POLARSSL_HAVE_INT8) /* 8 bit */
508
509#define MAX32 N->n / 4
510#define A( j ) (uint32_t)( N->p[4*j+0] ) | \
511 ( N->p[4*j+1] << 8 ) | \
512 ( N->p[4*j+2] << 16 ) | \
513 ( N->p[4*j+3] << 24 )
514#define STORE32 N->p[4*i+0] = (t_uint)( cur ); \
515 N->p[4*i+1] = (t_uint)( cur >> 8 ); \
516 N->p[4*i+2] = (t_uint)( cur >> 16 ); \
517 N->p[4*i+3] = (t_uint)( cur >> 24 );
518
519#elif defined(POLARSSL_HAVE_INT16) /* 16 bit */
520
521#define MAX32 N->n / 2
522#define A( j ) (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 )
523#define STORE32 N->p[2*i+0] = (t_uint)( cur ); \
524 N->p[2*i+1] = (t_uint)( cur >> 16 );
525
526#elif defined(POLARSSL_HAVE_INT32) /* 32 bit */
527
528#define MAX32 N->n
529#define A( j ) N->p[j]
530#define STORE32 N->p[i] = cur;
531
532#else /* 64-bit */
533
534#define MAX32 N->n * 2
535#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] )
536#define STORE32 \
537 if( i % 2 ) { \
538 N->p[i/2] &= 0x00000000FFFFFFFF; \
539 N->p[i/2] |= ((t_uint) cur) << 32; \
540 } else { \
541 N->p[i/2] &= 0xFFFFFFFF00000000; \
542 N->p[i/2] |= (t_uint) cur; \
543 }
544
545#endif /* sizeof( t_uint ) */
546
547/*
548 * Helpers for addition and subtraction of chunks, with signed carry.
549 */
550static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
551{
552 *dst += src;
553 *carry += ( *dst < src );
554}
555
556static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
557{
558 *carry -= ( *dst < src );
559 *dst -= src;
560}
561
562#define ADD( j ) add32( &cur, A( j ), &c );
563#define SUB( j ) sub32( &cur, A( j ), &c );
564
565/*
566 * Helpers for the main 'loop'
567 * (see fix_negative for the motivation of C)
568 */
569#define INIT( b ) \
570 int ret; \
571 signed char c = 0, cc; \
572 uint32_t cur; \
573 size_t i = 0, bits = b; \
574 mpi C; \
575 t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ]; \
576 \
577 C.s = 1; \
578 C.n = b / 8 / sizeof( t_uint) + 1; \
579 C.p = Cp; \
580 memset( Cp, 0, C.n * sizeof( t_uint ) ); \
581 \
582 MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \
583 LOAD32;
584
585#define NEXT \
586 STORE32; i++; LOAD32; \
587 cc = c; c = 0; \
588 if( cc < 0 ) \
589 sub32( &cur, -cc, &c ); \
590 else \
591 add32( &cur, cc, &c ); \
592
593#define LAST \
594 STORE32; i++; \
595 cur = c > 0 ? c : 0; STORE32; \
596 cur = 0; while( ++i < MAX32 ) { STORE32; } \
597 if( c < 0 ) fix_negative( N, c, &C, bits );
598
599/*
600 * If the result is negative, we get it in the form
601 * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
602 */
603static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits )
604{
605 int ret;
606
607 /* C = - c * 2^(bits + 32) */
608#if !defined(POLARSSL_HAVE_INT64)
609 ((void) bits);
610#else
611 if( bits == 224 )
612 C->p[ C->n - 1 ] = ((t_uint) -c) << 32;
613 else
614#endif
615 C->p[ C->n - 1 ] = (t_uint) -c;
616
617 /* N = - ( C - N ) */
618 MPI_CHK( mpi_sub_abs( N, C, N ) );
619 N->s = -1;
620
621cleanup:
622
623 return( ret );
624}
625
626#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
627/*
628 * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
629 */
630int ecp_mod_p224( mpi *N )
631{
632 INIT( 224 );
633
634 SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11
635 SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12
636 SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13
637 SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11
638 SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12
639 SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13
640 SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10
641
642cleanup:
643 return( ret );
644}
645#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
646
647#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
648/*
649 * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
650 */
651int ecp_mod_p256( mpi *N )
652{
653 INIT( 256 );
654
655 ADD( 8 ); ADD( 9 );
656 SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0
657
658 ADD( 9 ); ADD( 10 );
659 SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1
660
661 ADD( 10 ); ADD( 11 );
662 SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2
663
664 ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
665 SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3
666
667 ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
668 SUB( 9 ); SUB( 10 ); NEXT; // A4
669
670 ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
671 SUB( 10 ); SUB( 11 ); NEXT; // A5
672
673 ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
674 SUB( 8 ); SUB( 9 ); NEXT; // A6
675
676 ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
677 SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7
678
679cleanup:
680 return( ret );
681}
682#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
683
684#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
685/*
686 * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
687 */
688int ecp_mod_p384( mpi *N )
689{
690 INIT( 384 );
691
692 ADD( 12 ); ADD( 21 ); ADD( 20 );
693 SUB( 23 ); NEXT; // A0
694
695 ADD( 13 ); ADD( 22 ); ADD( 23 );
696 SUB( 12 ); SUB( 20 ); NEXT; // A2
697
698 ADD( 14 ); ADD( 23 );
699 SUB( 13 ); SUB( 21 ); NEXT; // A2
700
701 ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
702 SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3
703
704 ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
705 SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4
706
707 ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
708 SUB( 16 ); NEXT; // A5
709
710 ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
711 SUB( 17 ); NEXT; // A6
712
713 ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
714 SUB( 18 ); NEXT; // A7
715
716 ADD( 20 ); ADD( 17 ); ADD( 16 );
717 SUB( 19 ); NEXT; // A8
718
719 ADD( 21 ); ADD( 18 ); ADD( 17 );
720 SUB( 20 ); NEXT; // A9
721
722 ADD( 22 ); ADD( 19 ); ADD( 18 );
723 SUB( 21 ); NEXT; // A10
724
725 ADD( 23 ); ADD( 20 ); ADD( 19 );
726 SUB( 22 ); LAST; // A11
727
728cleanup:
729 return( ret );
730}
731#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
732
733#undef A
734#undef LOAD32
735#undef STORE32
736#undef MAX32
737#undef INIT
738#undef NEXT
739#undef LAST
740
741#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED ||
742 POLARSSL_ECP_DP_SECP256R1_ENABLED ||
743 POLARSSL_ECP_DP_SECP384R1_ENABLED */
744
745#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
746/*
747 * Here we have an actual Mersenne prime, so things are more straightforward.
748 * However, chunks are aligned on a 'weird' boundary (521 bits).
749 */
750
751/* Size of p521 in terms of t_uint */
752#define P521_WIDTH ( 521 / 8 / sizeof( t_uint ) + 1 )
753
754/* Bits to keep in the most significant t_uint */
755#if defined(POLARSSL_HAVE_INT8)
756#define P521_MASK 0x01
757#else
758#define P521_MASK 0x01FF
759#endif
760
761/*
762 * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
763 * Write N as A1 + 2^521 A0, return A0 + A1
764 */
765int ecp_mod_p521( mpi *N )
766{
767 int ret;
768 size_t i;
769 mpi M;
770 t_uint Mp[P521_WIDTH + 1];
771 /* Worst case for the size of M is when t_uint is 16 bits:
772 * we need to hold bits 513 to 1056, which is 34 limbs, that is
773 * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
774
775 if( N->n < P521_WIDTH )
776 return( 0 );
777
778 /* M = A1 */
779 M.s = 1;
780 M.n = N->n - ( P521_WIDTH - 1 );
781 if( M.n > P521_WIDTH + 1 )
782 M.n = P521_WIDTH + 1;
783 M.p = Mp;
784 memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) );
785 MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) );
786
787 /* N = A0 */
788 N->p[P521_WIDTH - 1] &= P521_MASK;
789 for( i = P521_WIDTH; i < N->n; i++ )
790 N->p[i] = 0;
791
792 /* N = A0 + A1 */
793 MPI_CHK( mpi_add_abs( N, N, &M ) );
794
795cleanup:
796 return( ret );
797}
798
799#undef P521_WIDTH
800#undef P521_MASK
801#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
802
803#endif /* POLARSSL_ECP_NIST_OPTIM */
804
805#endif