1/* Copyright (c) 2016, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <openssl/curve25519.h>
16
17#include <assert.h>
18#include <string.h>
19
20#include <openssl/bytestring.h>
21#include <openssl/mem.h>
22#include <openssl/rand.h>
23#include <openssl/sha.h>
24
25#include "../internal.h"
26#include "../../third_party/fiat/internal.h"
27
28
29// The following precomputation tables are for the following
30// points used in the SPAKE2 protocol.
31//
32// N:
33// x: 49918732221787544735331783592030787422991506689877079631459872391322455579424
34// y: 54629554431565467720832445949441049581317094546788069926228343916274969994000
35// encoded: 10e3df0ae37d8e7a99b5fe74b44672103dbddcbd06af680d71329a11693bc778
36//
37// M:
38// x: 31406539342727633121250288103050113562375374900226415211311216773867585644232
39// y: 21177308356423958466833845032658859666296341766942662650232962324899758529114
40// encoded: 5ada7e4bf6ddd9adb6626d32131c6b5c51a1e347a3478f53cfcf441b88eed12e
41//
42// These points and their precomputation tables are generated with the
43// following Python code. For a description of the precomputation table,
44// see curve25519.c in this directory.
45//
46// Exact copies of the source code are kept in bug 27296743.
47
48/*
49import hashlib
50import ed25519 as E # http://ed25519.cr.yp.to/python/ed25519.py
51
52SEED_N = 'edwards25519 point generation seed (N)'
53SEED_M = 'edwards25519 point generation seed (M)'
54
55def genpoint(seed):
56 v = hashlib.sha256(seed).digest()
57 it = 1
58 while True:
59 try:
60 x,y = E.decodepoint(v)
61 except Exception, e:
62 print e
63 it += 1
64 v = hashlib.sha256(v).digest()
65 continue
66 print "Found in %d iterations:" % it
67 print " x = %d" % x
68 print " y = %d" % y
69 print " Encoded (hex)"
70 print E.encodepoint((x,y)).encode('hex')
71 return (x,y)
72
73def gentable(P):
74 t = []
75 for i in range(1,16):
76 k = ((i >> 3 & 1) * (1 << 192) +
77 (i >> 2 & 1) * (1 << 128) +
78 (i >> 1 & 1) * (1 << 64) +
79 (i & 1))
80 t.append(E.scalarmult(P, k))
81 return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t)
82
83def printtable(table, name):
84 print "static const uint8_t %s[15 * 2 * 32] = {" % name,
85 for i in range(15 * 2 * 32):
86 if i % 12 == 0:
87 print "\n ",
88 print " 0x%02x," % ord(table[i]),
89 print "\n};"
90
91if __name__ == "__main__":
92 print "Searching for N"
93 N = genpoint(SEED_N)
94 print "Generating precomputation table for N"
95 Ntable = gentable(N)
96 printtable(Ntable, "kSpakeNSmallPrecomp")
97
98 print "Searching for M"
99 M = genpoint(SEED_M)
100 print "Generating precomputation table for M"
101 Mtable = gentable(M)
102 printtable(Mtable, "kSpakeMSmallPrecomp")
103*/
104
105static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = {
106 0x20, 0x1b, 0xc5, 0xb3, 0x43, 0x17, 0x71, 0x10, 0x44, 0x1e, 0x73, 0xb3,
107 0xae, 0x3f, 0xbf, 0x9f, 0xf5, 0x44, 0xc8, 0x13, 0x8f, 0xd1, 0x01, 0xc2,
108 0x8a, 0x1a, 0x6d, 0xea, 0x4d, 0x00, 0x5d, 0x6e, 0x10, 0xe3, 0xdf, 0x0a,
109 0xe3, 0x7d, 0x8e, 0x7a, 0x99, 0xb5, 0xfe, 0x74, 0xb4, 0x46, 0x72, 0x10,
110 0x3d, 0xbd, 0xdc, 0xbd, 0x06, 0xaf, 0x68, 0x0d, 0x71, 0x32, 0x9a, 0x11,
111 0x69, 0x3b, 0xc7, 0x78, 0x93, 0xf1, 0x57, 0x97, 0x6e, 0xf0, 0x6e, 0x45,
112 0x37, 0x4a, 0xf4, 0x0b, 0x18, 0x51, 0xf5, 0x4f, 0x67, 0x3c, 0xdc, 0xec,
113 0x84, 0xed, 0xd0, 0xeb, 0xca, 0xfb, 0xdb, 0xff, 0x7f, 0xeb, 0xa8, 0x23,
114 0x68, 0x87, 0x13, 0x64, 0x6a, 0x10, 0xf7, 0x45, 0xe0, 0x0f, 0x32, 0x21,
115 0x59, 0x7c, 0x0e, 0x50, 0xad, 0x56, 0xd7, 0x12, 0x69, 0x7b, 0x58, 0xf8,
116 0xb9, 0x3b, 0xa5, 0xbb, 0x4d, 0x1b, 0x87, 0x1c, 0x46, 0xa7, 0x17, 0x9d,
117 0x6d, 0x84, 0x45, 0xbe, 0x7f, 0x95, 0xd2, 0x34, 0xcd, 0x89, 0x95, 0xc0,
118 0xf0, 0xd3, 0xdf, 0x6e, 0x10, 0x4a, 0xe3, 0x7b, 0xce, 0x7f, 0x40, 0x27,
119 0xc7, 0x2b, 0xab, 0x66, 0x03, 0x59, 0xb4, 0x7b, 0xc7, 0xc7, 0xf0, 0x39,
120 0x9a, 0x33, 0x35, 0xbf, 0xcc, 0x2f, 0xf3, 0x2e, 0x68, 0x9d, 0x53, 0x5c,
121 0x88, 0x52, 0xe3, 0x77, 0x90, 0xa1, 0x27, 0x85, 0xc5, 0x74, 0x7f, 0x23,
122 0x0e, 0x93, 0x01, 0x3e, 0xe7, 0x2e, 0x2e, 0x95, 0xf3, 0x0d, 0xc2, 0x25,
123 0x25, 0x39, 0x39, 0x3d, 0x6e, 0x8e, 0x89, 0xbd, 0xe8, 0xbb, 0x67, 0x5e,
124 0x8c, 0x66, 0x8b, 0x63, 0x28, 0x1e, 0x4e, 0x74, 0x85, 0xa8, 0xaf, 0x0f,
125 0x12, 0x5d, 0xb6, 0x8a, 0x83, 0x1a, 0x77, 0x76, 0x5e, 0x62, 0x8a, 0xa7,
126 0x3c, 0xb8, 0x05, 0x57, 0x2b, 0xaf, 0x36, 0x2e, 0x10, 0x90, 0xb2, 0x39,
127 0xb4, 0x3e, 0x75, 0x6d, 0x3a, 0xa8, 0x31, 0x35, 0xc2, 0x1e, 0x8f, 0xc2,
128 0x79, 0x89, 0x35, 0x16, 0x26, 0xd1, 0xc7, 0x0b, 0x04, 0x1f, 0x1d, 0xf9,
129 0x9c, 0x05, 0xa6, 0x6b, 0xb5, 0x19, 0x5a, 0x24, 0x6d, 0x91, 0xc5, 0x31,
130 0xfd, 0xc5, 0xfa, 0xe7, 0xa6, 0xcb, 0x0e, 0x4b, 0x18, 0x0d, 0x94, 0xc7,
131 0xee, 0x1d, 0x46, 0x1f, 0x92, 0xb1, 0xb2, 0x4a, 0x2b, 0x43, 0x37, 0xfe,
132 0xc2, 0x15, 0x11, 0x89, 0xef, 0x59, 0x73, 0x3c, 0x06, 0x76, 0x78, 0xcb,
133 0xa6, 0x0d, 0x79, 0x5f, 0x28, 0x0b, 0x5b, 0x8c, 0x9e, 0xe4, 0xaa, 0x51,
134 0x9a, 0x42, 0x6f, 0x11, 0x50, 0x3d, 0x01, 0xd6, 0x21, 0xc0, 0x99, 0x5e,
135 0x1a, 0xe8, 0x81, 0x25, 0x80, 0xeb, 0xed, 0x5d, 0x37, 0x47, 0x30, 0x70,
136 0xa0, 0x4e, 0x0b, 0x43, 0x17, 0xbe, 0xb6, 0x47, 0xe7, 0x2a, 0x62, 0x9d,
137 0x5d, 0xa6, 0xc5, 0x33, 0x62, 0x9d, 0x56, 0x24, 0x9d, 0x1d, 0xb2, 0x13,
138 0xbc, 0x17, 0x66, 0x43, 0xd1, 0x68, 0xd5, 0x3b, 0x17, 0x69, 0x17, 0xa6,
139 0x06, 0x9e, 0x12, 0xb8, 0x7c, 0xd5, 0xaf, 0x3e, 0x21, 0x1b, 0x31, 0xeb,
140 0x0b, 0xa4, 0x98, 0x1c, 0xf2, 0x6a, 0x5e, 0x7c, 0x9b, 0x45, 0x8f, 0xb2,
141 0x12, 0x06, 0xd5, 0x8c, 0x1d, 0xb2, 0xa7, 0x57, 0x5f, 0x2f, 0x4f, 0xdb,
142 0x52, 0x99, 0x7c, 0x58, 0x01, 0x5f, 0xf2, 0xa5, 0xf6, 0x51, 0x86, 0x21,
143 0x2f, 0x5b, 0x8d, 0x6a, 0xae, 0x83, 0x34, 0x6d, 0x58, 0x4b, 0xef, 0xfe,
144 0xbf, 0x73, 0x5d, 0xdb, 0xc4, 0x97, 0x2a, 0x85, 0xf3, 0x6c, 0x46, 0x42,
145 0xb3, 0x90, 0xc1, 0x57, 0x97, 0x50, 0x35, 0xb1, 0x9d, 0xb7, 0xc7, 0x3c,
146 0x85, 0x6d, 0x6c, 0xfd, 0xce, 0xb0, 0xc9, 0xa2, 0x77, 0xee, 0xc3, 0x6b,
147 0x0c, 0x37, 0xfa, 0x30, 0x91, 0xd1, 0x2c, 0xb8, 0x5e, 0x7f, 0x81, 0x5f,
148 0x87, 0xfd, 0x18, 0x02, 0x5a, 0x30, 0x4e, 0x62, 0xbc, 0x65, 0xc6, 0xce,
149 0x1a, 0xcf, 0x2b, 0xaa, 0x56, 0x3e, 0x4d, 0xcf, 0xba, 0x62, 0x5f, 0x9a,
150 0xd0, 0x72, 0xff, 0xef, 0x28, 0xbd, 0xbe, 0xd8, 0x57, 0x3d, 0xf5, 0x57,
151 0x7d, 0xe9, 0x71, 0x31, 0xec, 0x98, 0x90, 0x94, 0xd9, 0x54, 0xbf, 0x84,
152 0x0b, 0xe3, 0x06, 0x47, 0x19, 0x9a, 0x13, 0x1d, 0xef, 0x9d, 0x13, 0xf3,
153 0xdb, 0xc3, 0x5c, 0x72, 0x9e, 0xed, 0x24, 0xaa, 0x64, 0xed, 0xe7, 0x0d,
154 0xa0, 0x7c, 0x73, 0xba, 0x9b, 0x86, 0xa7, 0x3b, 0x55, 0xab, 0x58, 0x30,
155 0xf1, 0x15, 0x81, 0x83, 0x2f, 0xf9, 0x62, 0x84, 0x98, 0x66, 0xf6, 0x55,
156 0x21, 0xd8, 0xf2, 0x25, 0x64, 0x71, 0x4b, 0x12, 0x76, 0x59, 0xc5, 0xaa,
157 0x93, 0x67, 0xc3, 0x86, 0x25, 0xab, 0x4e, 0x4b, 0xf6, 0xd8, 0x3f, 0x44,
158 0x2e, 0x11, 0xe0, 0xbd, 0x6a, 0xf2, 0x5d, 0xf5, 0xf9, 0x53, 0xea, 0xa4,
159 0xc8, 0xd9, 0x50, 0x33, 0x81, 0xd9, 0xa8, 0x2d, 0x91, 0x7d, 0x13, 0x2a,
160 0x11, 0xcf, 0xde, 0x3f, 0x0a, 0xd2, 0xbc, 0x33, 0xb2, 0x62, 0x53, 0xea,
161 0x77, 0x88, 0x43, 0x66, 0x27, 0x43, 0x85, 0xe9, 0x5f, 0x55, 0xf5, 0x2a,
162 0x8a, 0xac, 0xdf, 0xff, 0x9b, 0x4c, 0x96, 0x9c, 0xa5, 0x7a, 0xce, 0xd5,
163 0x79, 0x18, 0xf1, 0x0b, 0x58, 0x95, 0x7a, 0xe7, 0xd3, 0x74, 0x65, 0x0b,
164 0xa4, 0x64, 0x30, 0xe8, 0x5c, 0xfc, 0x55, 0x56, 0xee, 0x14, 0x14, 0xd3,
165 0x45, 0x3b, 0xf8, 0xde, 0x05, 0x3e, 0xb9, 0x3c, 0xd7, 0x6a, 0x52, 0x72,
166 0x5b, 0x39, 0x09, 0xbe, 0x82, 0x23, 0x10, 0x4a, 0xb7, 0xc3, 0xdc, 0x4c,
167 0x5d, 0xc9, 0xf1, 0x14, 0x83, 0xf9, 0x0b, 0x9b, 0xe9, 0x23, 0x84, 0x6a,
168 0xc4, 0x08, 0x3d, 0xda, 0x3d, 0x12, 0x95, 0x87, 0x18, 0xa4, 0x7d, 0x3f,
169 0x23, 0xde, 0xd4, 0x1e, 0xa8, 0x47, 0xc3, 0x71, 0xdb, 0xf5, 0x03, 0x6c,
170 0x57, 0xe7, 0xa4, 0x43, 0x82, 0x33, 0x7b, 0x62, 0x46, 0x7d, 0xf7, 0x10,
171 0x69, 0x18, 0x38, 0x27, 0x9a, 0x6f, 0x38, 0xac, 0xfa, 0x92, 0xc5, 0xae,
172 0x66, 0xa6, 0x73, 0x95, 0x15, 0x0e, 0x4c, 0x04, 0xb6, 0xfc, 0xf5, 0xc7,
173 0x21, 0x3a, 0x99, 0xdb, 0x0e, 0x36, 0xf0, 0x56, 0xbc, 0x75, 0xf9, 0x87,
174 0x9b, 0x11, 0x18, 0x92, 0x64, 0x1a, 0xe7, 0xc7, 0xab, 0x5a, 0xc7, 0x26,
175 0x7f, 0x13, 0x98, 0x42, 0x52, 0x43, 0xdb, 0xc8, 0x6d, 0x0b, 0xb7, 0x31,
176 0x93, 0x24, 0xd6, 0xe8, 0x24, 0x1f, 0x6f, 0x21, 0xa7, 0x8c, 0xeb, 0xdb,
177 0x83, 0xb8, 0x89, 0xe3, 0xc1, 0xd7, 0x69, 0x3b, 0x02, 0x6b, 0x54, 0x0f,
178 0x84, 0x2f, 0xb5, 0x5c, 0x17, 0x77, 0xbe, 0xe5, 0x61, 0x0d, 0xc5, 0xdf,
179 0x3b, 0xcf, 0x3e, 0x93, 0x4f, 0xf5, 0x89, 0xb9, 0x5a, 0xc5, 0x29, 0x31,
180 0xc0, 0xc2, 0xff, 0xe5, 0x3f, 0xa6, 0xac, 0x03, 0xca, 0xf5, 0xff, 0xe0,
181 0x36, 0xce, 0xf3, 0xe2, 0xb7, 0x9c, 0x02, 0xe9, 0x9e, 0xd2, 0xbc, 0x87,
182 0x2f, 0x3d, 0x9a, 0x1d, 0x8f, 0xc5, 0x72, 0xb8, 0xa2, 0x01, 0xd4, 0x68,
183 0xb1, 0x84, 0x16, 0x10, 0xf6, 0xf3, 0x52, 0x25, 0xd9, 0xdc, 0x4c, 0xdd,
184 0x0f, 0xd6, 0x4a, 0xcf, 0x60, 0x96, 0x7e, 0xcc, 0x42, 0x0f, 0x64, 0x9d,
185 0x72, 0x46, 0x04, 0x07, 0xf2, 0x5b, 0xf4, 0x07, 0xd1, 0xf4, 0x59, 0x71,
186};
187
188static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = {
189 0xc8, 0xa6, 0x63, 0xc5, 0x97, 0xf1, 0xee, 0x40, 0xab, 0x62, 0x42, 0xee,
190 0x25, 0x6f, 0x32, 0x6c, 0x75, 0x2c, 0xa7, 0xd3, 0xbd, 0x32, 0x3b, 0x1e,
191 0x11, 0x9c, 0xbd, 0x04, 0xa9, 0x78, 0x6f, 0x45, 0x5a, 0xda, 0x7e, 0x4b,
192 0xf6, 0xdd, 0xd9, 0xad, 0xb6, 0x62, 0x6d, 0x32, 0x13, 0x1c, 0x6b, 0x5c,
193 0x51, 0xa1, 0xe3, 0x47, 0xa3, 0x47, 0x8f, 0x53, 0xcf, 0xcf, 0x44, 0x1b,
194 0x88, 0xee, 0xd1, 0x2e, 0x03, 0x89, 0xaf, 0xc0, 0x61, 0x2d, 0x9e, 0x35,
195 0xeb, 0x0e, 0x03, 0xe0, 0xb7, 0xfb, 0xa5, 0xbc, 0x44, 0xbe, 0x0c, 0x89,
196 0x0a, 0x0f, 0xd6, 0x59, 0x47, 0x9e, 0xe6, 0x3d, 0x36, 0x9d, 0xff, 0x44,
197 0x5e, 0xac, 0xab, 0xe5, 0x3a, 0xd5, 0xb0, 0x35, 0x9f, 0x6d, 0x7f, 0xba,
198 0xc0, 0x85, 0x0e, 0xf4, 0x70, 0x3f, 0x13, 0x90, 0x4c, 0x50, 0x1a, 0xee,
199 0xc5, 0xeb, 0x69, 0xfe, 0x98, 0x42, 0x87, 0x1d, 0xce, 0x6c, 0x29, 0xaa,
200 0x2b, 0x31, 0xc2, 0x38, 0x7b, 0x6b, 0xee, 0x88, 0x0b, 0xba, 0xce, 0xa8,
201 0xca, 0x19, 0x60, 0x1b, 0x16, 0xf1, 0x25, 0x1e, 0xcf, 0x63, 0x66, 0x1e,
202 0xbb, 0x63, 0xeb, 0x7d, 0xca, 0xd2, 0xb4, 0x23, 0x5a, 0x01, 0x6f, 0x05,
203 0xd1, 0xdc, 0x41, 0x73, 0x75, 0xc0, 0xfd, 0x30, 0x91, 0x52, 0x68, 0x96,
204 0x45, 0xb3, 0x66, 0x01, 0x3b, 0x53, 0x89, 0x3c, 0x69, 0xbc, 0x6c, 0x69,
205 0xe3, 0x51, 0x8f, 0xe3, 0xd2, 0x84, 0xd5, 0x28, 0x66, 0xb5, 0xe6, 0x06,
206 0x09, 0xfe, 0x6d, 0xb0, 0x72, 0x16, 0xe0, 0x8a, 0xce, 0x61, 0x65, 0xa9,
207 0x21, 0x32, 0x48, 0xdc, 0x7a, 0x1d, 0xe1, 0x38, 0x7f, 0x8c, 0x75, 0x88,
208 0x3d, 0x08, 0xa9, 0x4a, 0x6f, 0x3d, 0x9f, 0x7f, 0x3f, 0xbd, 0x57, 0x6b,
209 0x19, 0xce, 0x3f, 0x4a, 0xc9, 0xd3, 0xf9, 0x6e, 0x72, 0x7b, 0x5b, 0x74,
210 0xea, 0xbe, 0x9c, 0x7a, 0x6d, 0x9c, 0x40, 0x49, 0xe6, 0xfb, 0x2a, 0x1a,
211 0x75, 0x70, 0xe5, 0x4e, 0xed, 0x74, 0xe0, 0x75, 0xac, 0xc0, 0xb1, 0x11,
212 0x3e, 0xf2, 0xaf, 0x88, 0x4d, 0x66, 0xb6, 0xf6, 0x15, 0x4f, 0x3c, 0x6c,
213 0x77, 0xae, 0x47, 0x51, 0x63, 0x9a, 0xfe, 0xe1, 0xb4, 0x1a, 0x12, 0xdf,
214 0xe9, 0x54, 0x8d, 0x3b, 0x30, 0x2a, 0x75, 0xe3, 0xe5, 0x29, 0xb1, 0x4c,
215 0xb0, 0x7c, 0x6d, 0xb5, 0xae, 0x85, 0xdb, 0x1e, 0x38, 0x55, 0x96, 0xa5,
216 0x5b, 0x9f, 0x15, 0x23, 0x28, 0x36, 0xb8, 0xa2, 0x41, 0xb4, 0xd7, 0x19,
217 0x91, 0x8d, 0x26, 0x3e, 0xca, 0x9c, 0x05, 0x7a, 0x2b, 0x60, 0x45, 0x86,
218 0x8b, 0xee, 0x64, 0x6f, 0x5c, 0x09, 0x4d, 0x4b, 0x5a, 0x7f, 0xb0, 0xc3,
219 0x26, 0x9d, 0x8b, 0xb8, 0x83, 0x69, 0xcf, 0x16, 0x72, 0x62, 0x3e, 0x5e,
220 0x53, 0x4f, 0x9c, 0x73, 0x76, 0xfc, 0x19, 0xef, 0xa0, 0x74, 0x3a, 0x11,
221 0x1e, 0xd0, 0x4d, 0xb7, 0x87, 0xa1, 0xd6, 0x87, 0x6c, 0x0e, 0x6c, 0x8c,
222 0xe9, 0xa0, 0x44, 0xc4, 0x72, 0x3e, 0x73, 0x17, 0x13, 0xd1, 0x4e, 0x3d,
223 0x8e, 0x1d, 0x5a, 0x8b, 0x75, 0xcb, 0x59, 0x2c, 0x47, 0x87, 0x15, 0x41,
224 0xfe, 0x08, 0xe9, 0xa6, 0x97, 0x17, 0x08, 0x26, 0x6a, 0xb5, 0xbb, 0x73,
225 0xaa, 0xb8, 0x5b, 0x65, 0x65, 0x5b, 0x30, 0x9e, 0x62, 0x59, 0x02, 0xf8,
226 0xb8, 0x0f, 0x32, 0x10, 0xc1, 0x36, 0x08, 0x52, 0x98, 0x4a, 0x1e, 0xf0,
227 0xab, 0x21, 0x5e, 0xde, 0x16, 0x0c, 0xda, 0x09, 0x99, 0x6b, 0x9e, 0xc0,
228 0x90, 0xa5, 0x5a, 0xcc, 0xb0, 0xb7, 0xbb, 0xd2, 0x8b, 0x5f, 0xd3, 0x3b,
229 0x3e, 0x8c, 0xa5, 0x71, 0x66, 0x06, 0xe3, 0x28, 0xd4, 0xf8, 0x3f, 0xe5,
230 0x27, 0xdf, 0xfe, 0x0f, 0x09, 0xb2, 0x8a, 0x09, 0x5a, 0x23, 0x61, 0x0d,
231 0x2d, 0xf5, 0x44, 0xf1, 0x5c, 0xf8, 0x82, 0x4e, 0xdc, 0x78, 0x7a, 0xab,
232 0xc3, 0x57, 0x91, 0xaf, 0x65, 0x6e, 0x71, 0xf1, 0x44, 0xbf, 0xed, 0x43,
233 0x50, 0xb4, 0x67, 0x48, 0xef, 0x5a, 0x10, 0x46, 0x81, 0xb4, 0x0c, 0xc8,
234 0x48, 0xed, 0x99, 0x7a, 0x45, 0xa5, 0x92, 0xc3, 0x69, 0xd6, 0xd7, 0x8a,
235 0x20, 0x1b, 0xeb, 0x8f, 0xb2, 0xff, 0xec, 0x6d, 0x76, 0x04, 0xf8, 0xc2,
236 0x58, 0x9b, 0xf2, 0x20, 0x53, 0xc4, 0x74, 0x91, 0x19, 0xdd, 0x2d, 0x12,
237 0x53, 0xc7, 0x6e, 0xd0, 0x02, 0x51, 0x3c, 0xa6, 0x7d, 0x80, 0x75, 0x6b,
238 0x1d, 0xdf, 0xf8, 0x6a, 0x52, 0xbb, 0x81, 0xf8, 0x30, 0x45, 0xef, 0x51,
239 0x85, 0x36, 0xbe, 0x8e, 0xcf, 0x0b, 0x9a, 0x46, 0xe8, 0x3f, 0x99, 0xfd,
240 0xf7, 0xd9, 0x3e, 0x84, 0xe5, 0xe3, 0x37, 0xcf, 0x98, 0x7f, 0xeb, 0x5e,
241 0x5a, 0x53, 0x77, 0x1c, 0x20, 0xdc, 0xf1, 0x20, 0x99, 0xec, 0x60, 0x40,
242 0x93, 0xef, 0x5c, 0x1c, 0x81, 0xe2, 0xa5, 0xad, 0x2a, 0xc2, 0xdb, 0x6b,
243 0xc1, 0x7e, 0x8f, 0xa9, 0x23, 0x5b, 0xd9, 0x0d, 0xfe, 0xa0, 0xac, 0x11,
244 0x28, 0xba, 0x8e, 0x92, 0x07, 0x2d, 0x07, 0x40, 0x83, 0x14, 0x4c, 0x35,
245 0x8d, 0xd0, 0x11, 0xff, 0x98, 0xdb, 0x00, 0x30, 0x6f, 0x65, 0xb6, 0xa0,
246 0x7f, 0x9c, 0x08, 0xb8, 0xce, 0xb3, 0xa8, 0x42, 0xd3, 0x84, 0x45, 0xe1,
247 0xe3, 0x8f, 0xa6, 0x89, 0x21, 0xd7, 0x74, 0x02, 0x4d, 0x64, 0xdf, 0x54,
248 0x15, 0x9e, 0xba, 0x12, 0x49, 0x09, 0x41, 0xf6, 0x10, 0x24, 0xa1, 0x84,
249 0x15, 0xfd, 0x68, 0x6a, 0x57, 0x66, 0xb3, 0x6d, 0x4c, 0xea, 0xbf, 0xbc,
250 0x60, 0x3f, 0x52, 0x1c, 0x44, 0x1b, 0xc0, 0x4a, 0x25, 0xe3, 0xd9, 0x4c,
251 0x9a, 0x74, 0xad, 0xfc, 0x9e, 0x8d, 0x0b, 0x18, 0x66, 0x24, 0xd1, 0x06,
252 0xac, 0x68, 0xc1, 0xae, 0x14, 0xce, 0xb1, 0xf3, 0x86, 0x9f, 0x87, 0x11,
253 0xd7, 0x9f, 0x30, 0x92, 0xdb, 0xec, 0x0b, 0x4a, 0xe8, 0xf6, 0x53, 0x36,
254 0x68, 0x12, 0x11, 0x5e, 0xe0, 0x34, 0xa4, 0xff, 0x00, 0x0a, 0x26, 0xb8,
255 0x62, 0x79, 0x9c, 0x0c, 0xd5, 0xe5, 0xf5, 0x1c, 0x1a, 0x16, 0x84, 0x4d,
256 0x8e, 0x5d, 0x31, 0x7e, 0xf7, 0xe2, 0xd3, 0xa1, 0x41, 0x90, 0x61, 0x5d,
257 0x04, 0xb2, 0x9a, 0x18, 0x9e, 0x54, 0xfb, 0xd1, 0x61, 0x95, 0x1b, 0x08,
258 0xca, 0x7c, 0x49, 0x44, 0x74, 0x1d, 0x2f, 0xca, 0xc4, 0x7a, 0xe1, 0x8b,
259 0x2f, 0xbb, 0x96, 0xee, 0x19, 0x8a, 0x5d, 0xfb, 0x3e, 0x82, 0xe7, 0x15,
260 0xdb, 0x29, 0x14, 0xee, 0xc9, 0x4d, 0x9a, 0xfb, 0x9f, 0x8a, 0xbb, 0x17,
261 0x37, 0x1b, 0x6e, 0x28, 0x6c, 0xf9, 0xff, 0xb5, 0xb5, 0x8b, 0x9d, 0x88,
262 0x20, 0x08, 0x10, 0xd7, 0xca, 0x58, 0xf6, 0xe1, 0x32, 0x91, 0x6f, 0x36,
263 0xc0, 0xad, 0xc1, 0x57, 0x5d, 0x76, 0x31, 0x43, 0xf3, 0xdd, 0xec, 0xf1,
264 0xa9, 0x79, 0xe9, 0xe9, 0x85, 0xd7, 0x91, 0xc7, 0x31, 0x62, 0x3c, 0xd2,
265 0x90, 0x2c, 0x9c, 0xa4, 0x56, 0x37, 0x7b, 0xbe, 0x40, 0x58, 0xc0, 0x81,
266 0x83, 0x22, 0xe8, 0x13, 0x79, 0x18, 0xdb, 0x3a, 0x1b, 0x31, 0x0d, 0x00,
267 0x6c, 0x22, 0x62, 0x75, 0x70, 0xd8, 0x96, 0x59, 0x99, 0x44, 0x79, 0x71,
268 0xa6, 0x76, 0x81, 0x28, 0xb2, 0x65, 0xe8, 0x47, 0x14, 0xc6, 0x39, 0x06,
269};
270
271SPAKE2_CTX *SPAKE2_CTX_new(enum spake2_role_t my_role,
272 const uint8_t *my_name, size_t my_name_len,
273 const uint8_t *their_name, size_t their_name_len) {
274 SPAKE2_CTX *ctx = OPENSSL_malloc(sizeof(SPAKE2_CTX));
275 if (ctx == NULL) {
276 return NULL;
277 }
278
279 OPENSSL_memset(ctx, 0, sizeof(SPAKE2_CTX));
280 ctx->my_role = my_role;
281
282 CBS my_name_cbs, their_name_cbs;
283 CBS_init(&my_name_cbs, my_name, my_name_len);
284 CBS_init(&their_name_cbs, their_name, their_name_len);
285 if (!CBS_stow(&my_name_cbs, &ctx->my_name, &ctx->my_name_len) ||
286 !CBS_stow(&their_name_cbs, &ctx->their_name, &ctx->their_name_len)) {
287 SPAKE2_CTX_free(ctx);
288 return NULL;
289 }
290
291 return ctx;
292}
293
294void SPAKE2_CTX_free(SPAKE2_CTX *ctx) {
295 if (ctx == NULL) {
296 return;
297 }
298
299 OPENSSL_free(ctx->my_name);
300 OPENSSL_free(ctx->their_name);
301 OPENSSL_free(ctx);
302}
303
304// left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian
305// order.
306static void left_shift_3(uint8_t n[32]) {
307 uint8_t carry = 0;
308 unsigned i;
309
310 for (i = 0; i < 32; i++) {
311 const uint8_t next_carry = n[i] >> 5;
312 n[i] = (n[i] << 3) | carry;
313 carry = next_carry;
314 }
315}
316
317typedef union {
318 uint8_t bytes[32];
319 uint32_t words[8];
320} scalar;
321
322// kOrder is the order of the prime-order subgroup of curve25519 in
323// little-endian order.
324static const scalar kOrder = {{0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
325 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}};
328
329// scalar_cmov copies |src| to |dest| if |mask| is all ones.
330static void scalar_cmov(scalar *dest, const scalar *src, crypto_word_t mask) {
331 for (size_t i = 0; i < 8; i++) {
332 dest->words[i] =
333 constant_time_select_w(mask, src->words[i], dest->words[i]);
334 }
335}
336
337// scalar_double sets |s| to |2×s|.
338static void scalar_double(scalar *s) {
339 uint32_t carry = 0;
340
341 for (size_t i = 0; i < 8; i++) {
342 const uint32_t carry_out = s->words[i] >> 31;
343 s->words[i] = (s->words[i] << 1) | carry;
344 carry = carry_out;
345 }
346}
347
348// scalar_add sets |dest| to |dest| plus |src|.
349static void scalar_add(scalar *dest, const scalar *src) {
350 uint32_t carry = 0;
351
352 for (size_t i = 0; i < 8; i++) {
353 uint64_t tmp = ((uint64_t)dest->words[i] + src->words[i]) + carry;
354 dest->words[i] = (uint32_t)tmp;
355 carry = (uint32_t)(tmp >> 32);
356 }
357}
358
359int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len,
360 size_t max_out_len, const uint8_t *password,
361 size_t password_len) {
362 if (ctx->state != spake2_state_init) {
363 return 0;
364 }
365
366 if (max_out_len < sizeof(ctx->my_msg)) {
367 return 0;
368 }
369
370 uint8_t private_tmp[64];
371 RAND_bytes(private_tmp, sizeof(private_tmp));
372 x25519_sc_reduce(private_tmp);
373 // Multiply by the cofactor (eight) so that we'll clear it when operating on
374 // the peer's point later in the protocol.
375 left_shift_3(private_tmp);
376 OPENSSL_memcpy(ctx->private_key, private_tmp, sizeof(ctx->private_key));
377
378 ge_p3 P;
379 x25519_ge_scalarmult_base(&P, ctx->private_key);
380
381 // mask = h(password) * <N or M>.
382 uint8_t password_tmp[SHA512_DIGEST_LENGTH];
383 SHA512(password, password_len, password_tmp);
384 OPENSSL_memcpy(ctx->password_hash, password_tmp, sizeof(ctx->password_hash));
385 x25519_sc_reduce(password_tmp);
386
387 // Due to a copy-paste error, the call to |left_shift_3| was omitted after
388 // the |x25519_sc_reduce|, just above. This meant that |ctx->password_scalar|
389 // was not a multiple of eight to clear the cofactor and thus three bits of
390 // the password hash would leak. In order to fix this in a unilateral way,
391 // points of small order are added to the mask point such that it is in the
392 // prime-order subgroup. Since the ephemeral scalar is a multiple of eight,
393 // these points will cancel out when calculating the shared secret.
394 //
395 // Adding points of small order is the same as adding multiples of the prime
396 // order to the password scalar. Since that's faster, that is what is done
397 // below. The prime order (kOrder) is a large prime, thus odd, thus the LSB
398 // is one. So adding it will flip the LSB. Adding twice it will flip the next
399 // bit and so one for all the bottom three bits.
400
401 scalar password_scalar;
402 OPENSSL_memcpy(&password_scalar, password_tmp, sizeof(password_scalar));
403
404 // |password_scalar| is the result of |x25519_sc_reduce| and thus is, at
405 // most, $l-1$ (where $l$ is |kOrder|, the order of the prime-order subgroup
406 // of Ed25519). In the following, we may add $l + 2×l + 4×l$ for a max value
407 // of $8×l-1$. That is < 2**256, as required.
408
409 if (!ctx->disable_password_scalar_hack) {
410 scalar order = kOrder;
411 scalar tmp;
412
413 OPENSSL_memset(&tmp, 0, sizeof(tmp));
414 scalar_cmov(&tmp, &order,
415 constant_time_eq_w(password_scalar.bytes[0] & 1, 1));
416 scalar_add(&password_scalar, &tmp);
417
418 scalar_double(&order);
419 OPENSSL_memset(&tmp, 0, sizeof(tmp));
420 scalar_cmov(&tmp, &order,
421 constant_time_eq_w(password_scalar.bytes[0] & 2, 2));
422 scalar_add(&password_scalar, &tmp);
423
424 scalar_double(&order);
425 OPENSSL_memset(&tmp, 0, sizeof(tmp));
426 scalar_cmov(&tmp, &order,
427 constant_time_eq_w(password_scalar.bytes[0] & 4, 4));
428 scalar_add(&password_scalar, &tmp);
429
430 assert((password_scalar.bytes[0] & 7) == 0);
431 }
432
433 OPENSSL_memcpy(ctx->password_scalar, password_scalar.bytes,
434 sizeof(ctx->password_scalar));
435
436 ge_p3 mask;
437 x25519_ge_scalarmult_small_precomp(&mask, ctx->password_scalar,
438 ctx->my_role == spake2_role_alice
439 ? kSpakeMSmallPrecomp
440 : kSpakeNSmallPrecomp);
441
442 // P* = P + mask.
443 ge_cached mask_cached;
444 x25519_ge_p3_to_cached(&mask_cached, &mask);
445 ge_p1p1 Pstar;
446 x25519_ge_add(&Pstar, &P, &mask_cached);
447
448 // Encode P*
449 ge_p2 Pstar_proj;
450 x25519_ge_p1p1_to_p2(&Pstar_proj, &Pstar);
451 x25519_ge_tobytes(ctx->my_msg, &Pstar_proj);
452
453 OPENSSL_memcpy(out, ctx->my_msg, sizeof(ctx->my_msg));
454 *out_len = sizeof(ctx->my_msg);
455 ctx->state = spake2_state_msg_generated;
456
457 return 1;
458}
459
460static void update_with_length_prefix(SHA512_CTX *sha, const uint8_t *data,
461 const size_t len) {
462 uint8_t len_le[8];
463 size_t l = len;
464 unsigned i;
465
466 for (i = 0; i < 8; i++) {
467 len_le[i] = l & 0xff;
468 l >>= 8;
469 }
470
471 SHA512_Update(sha, len_le, sizeof(len_le));
472 SHA512_Update(sha, data, len);
473}
474
475int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, size_t *out_key_len,
476 size_t max_out_key_len, const uint8_t *their_msg,
477 size_t their_msg_len) {
478 if (ctx->state != spake2_state_msg_generated ||
479 their_msg_len != 32) {
480 return 0;
481 }
482
483 ge_p3 Qstar;
484 if (!x25519_ge_frombytes_vartime(&Qstar, their_msg)) {
485 // Point received from peer was not on the curve.
486 return 0;
487 }
488
489 // Unmask peer's value.
490 ge_p3 peers_mask;
491 x25519_ge_scalarmult_small_precomp(&peers_mask, ctx->password_scalar,
492 ctx->my_role == spake2_role_alice
493 ? kSpakeNSmallPrecomp
494 : kSpakeMSmallPrecomp);
495
496 ge_cached peers_mask_cached;
497 x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask);
498
499 ge_p1p1 Q_compl;
500 ge_p3 Q_ext;
501 x25519_ge_sub(&Q_compl, &Qstar, &peers_mask_cached);
502 x25519_ge_p1p1_to_p3(&Q_ext, &Q_compl);
503
504 ge_p2 dh_shared;
505 x25519_ge_scalarmult(&dh_shared, ctx->private_key, &Q_ext);
506
507 uint8_t dh_shared_encoded[32];
508 x25519_ge_tobytes(dh_shared_encoded, &dh_shared);
509
510 SHA512_CTX sha;
511 SHA512_Init(&sha);
512 if (ctx->my_role == spake2_role_alice) {
513 update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len);
514 update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len);
515 update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg));
516 update_with_length_prefix(&sha, their_msg, 32);
517 } else {
518 update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len);
519 update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len);
520 update_with_length_prefix(&sha, their_msg, 32);
521 update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg));
522 }
523 update_with_length_prefix(&sha, dh_shared_encoded, sizeof(dh_shared_encoded));
524 update_with_length_prefix(&sha, ctx->password_hash,
525 sizeof(ctx->password_hash));
526
527 uint8_t key[SHA512_DIGEST_LENGTH];
528 SHA512_Final(key, &sha);
529
530 size_t to_copy = max_out_key_len;
531 if (to_copy > sizeof(key)) {
532 to_copy = sizeof(key);
533 }
534 OPENSSL_memcpy(out_key, key, to_copy);
535 *out_key_len = to_copy;
536 ctx->state = spake2_state_key_generated;
537
538 return 1;
539}
540