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