Skip to content

Commit 3412a70

Browse files
authored
Set server key material before LoginInit() (#58)
* set server key material before LoginInit() Signed-off-by: bytemare <[email protected]>
1 parent ebf2a01 commit 3412a70

File tree

10 files changed

+285
-84
lines changed

10 files changed

+285
-84
lines changed

examples_test.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ func Example_configuration() {
9191
func Example_serverSetup() {
9292
// This a straightforward way to use a secure and efficient configuration.
9393
// They have to be run only once in the application's lifecycle, and the output values must be stored appropriately.
94+
serverID := []byte("server-identity")
9495
conf := opaque.DefaultConfiguration()
9596
secretOprfSeed = conf.GenerateOPRFSeed()
9697
serverPrivateKey, serverPublicKey = conf.KeyGen()
@@ -99,9 +100,19 @@ func Example_serverSetup() {
99100
log.Fatalf("Oh no! Something went wrong setting up the server secrets!")
100101
}
101102

102-
fmt.Println("OPAQUE server values initialized.")
103+
// Server setup
104+
server, err := conf.Server()
105+
if err != nil {
106+
log.Fatalln(err)
107+
}
103108

104-
// Output: OPAQUE server values initialized.
109+
if err := server.SetKeyMaterial(serverID, serverPrivateKey, serverPublicKey, secretOprfSeed); err != nil {
110+
log.Fatalln(err)
111+
}
112+
113+
fmt.Println("OPAQUE server initialized.")
114+
115+
// Output: OPAQUE server initialized.
105116
}
106117

107118
// Example_Deserialization demonstrates a couple of ways to deserialize OPAQUE protocol messages.
@@ -297,6 +308,10 @@ func Example_loginKeyExchange() {
297308
log.Fatalln(err)
298309
}
299310

311+
if err := server.SetKeyMaterial(serverID, serverPrivateKey, serverPublicKey, secretOprfSeed); err != nil {
312+
log.Fatalln(err)
313+
}
314+
300315
// These are the 3 login messages that will be exchanged,
301316
// and the respective sessions keys for the client and server.
302317
var message1, message2, message3 []byte
@@ -315,8 +330,7 @@ func Example_loginKeyExchange() {
315330
log.Fatalln(err)
316331
}
317332

318-
ke2, err := server.LoginInit(ke1, serverID, serverPrivateKey, serverPublicKey, secretOprfSeed,
319-
exampleClientRecord)
333+
ke2, err := server.LoginInit(ke1, exampleClientRecord)
320334
if err != nil {
321335
log.Fatalln(err)
322336
}
@@ -410,12 +424,16 @@ func Example_fakeResponse() {
410424
log.Fatalln(err)
411425
}
412426

427+
if err := server.SetKeyMaterial(serverID, serverPrivateKey, serverPublicKey, secretOprfSeed); err != nil {
428+
log.Fatalln(err)
429+
}
430+
413431
ke1, err := server.Deserialize.KE1(message1)
414432
if err != nil {
415433
log.Fatalln(err)
416434
}
417435

418-
ke2, err := server.LoginInit(ke1, serverID, serverPrivateKey, serverPublicKey, secretOprfSeed, fakeRecord)
436+
ke2, err := server.LoginInit(ke1, fakeRecord)
419437
if err != nil {
420438
log.Fatalln(err)
421439
}

internal/ake/3dh.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,25 @@ type values struct {
8383
nonce []byte
8484
}
8585

86+
// GetEphemeralSecretKey returns the state's ephemeral secret key.
87+
func (v *values) GetEphemeralSecretKey() *group.Scalar {
88+
return v.ephemeralSecretKey
89+
}
90+
91+
// GetNonce returns the secret nonce.
92+
func (v *values) GetNonce() []byte {
93+
return v.nonce
94+
}
95+
96+
func (v *values) flush() {
97+
if v.ephemeralSecretKey != nil {
98+
v.ephemeralSecretKey.Zero()
99+
v.ephemeralSecretKey = nil
100+
}
101+
102+
v.nonce = nil
103+
}
104+
86105
// setOptions sets optional values.
87106
// There's no effect if ephemeralSecretKey and nonce have already been set in a previous call.
88107
func (v *values) setOptions(g group.Group, options Options) *group.Element {

internal/ake/client.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,9 @@ func (c *Client) Finalize(
8181
func (c *Client) SessionKey() []byte {
8282
return c.sessionSecret
8383
}
84+
85+
// Flush sets all the client's session related internal AKE values to nil.
86+
func (c *Client) Flush() {
87+
c.values.flush()
88+
c.sessionSecret = nil
89+
}

internal/ake/server.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,10 @@ func (s *Server) SetState(clientMac, sessionSecret []byte) error {
109109

110110
return nil
111111
}
112+
113+
// Flush sets all the server's session related internal AKE values to nil.
114+
func (s *Server) Flush() {
115+
s.values.flush()
116+
s.clientMac = nil
117+
s.sessionSecret = nil
118+
}

server.go

Lines changed: 67 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ import (
2323
)
2424

2525
var (
26+
// ErrNoServerKeyMaterial indicates that the server's key material has not been set.
27+
ErrNoServerKeyMaterial = errors.New("key material not set: call SetKeyMaterial() to set values")
28+
2629
// ErrAkeInvalidClientMac indicates that the MAC contained in the KE3 message is not valid in the given session.
2730
ErrAkeInvalidClientMac = errors.New("failed to authenticate client: invalid client mac")
2831

@@ -47,6 +50,14 @@ type Server struct {
4750
Deserialize *Deserializer
4851
conf *internal.Configuration
4952
Ake *ake.Server
53+
*keyMaterial
54+
}
55+
56+
type keyMaterial struct {
57+
serverIdentity []byte
58+
serverSecretKey *group.Scalar
59+
serverPublicKey []byte
60+
oprfSeed []byte
5061
}
5162

5263
// NewServer returns a Server instantiation given the application Configuration.
@@ -64,6 +75,7 @@ func NewServer(c *Configuration) (*Server, error) {
6475
Deserialize: &Deserializer{conf: conf},
6576
conf: conf,
6677
Ake: ake.NewServer(),
78+
keyMaterial: nil,
6779
}, nil
6880
}
6981

@@ -117,41 +129,6 @@ func (s *Server) credentialResponse(
117129
return message.NewCredentialResponse(z, maskingNonce, maskedResponse)
118130
}
119131

120-
func (s *Server) verifyInitInput(
121-
serverSecretKey, serverPublicKey, oprfSeed []byte,
122-
record *ClientRecord,
123-
) (*group.Scalar, error) {
124-
sks := s.conf.Group.NewScalar()
125-
if err := sks.Decode(serverSecretKey); err != nil {
126-
return nil, fmt.Errorf("invalid server AKE secret key: %w", err)
127-
}
128-
129-
if sks.IsZero() {
130-
return nil, ErrZeroSKS
131-
}
132-
133-
if len(oprfSeed) != s.conf.Hash.Size() {
134-
return nil, ErrInvalidOPRFSeedLength
135-
}
136-
137-
if len(serverPublicKey) != s.conf.Group.ElementLength() {
138-
return nil, ErrInvalidPksLength
139-
}
140-
141-
if err := s.conf.Group.NewElement().Decode(serverPublicKey); err != nil {
142-
return nil, fmt.Errorf("invalid server public key: %w", err)
143-
}
144-
145-
if len(record.Envelope) != s.conf.EnvelopeSize {
146-
return nil, ErrInvalidEnvelopeLength
147-
}
148-
149-
// We've checked that the server's public key and the client's envelope are of correct length,
150-
// thus ensuring that the subsequent xor-ing input is the same length as the encryption pad.
151-
152-
return sks, nil
153-
}
154-
155132
// ServerLoginInitOptions enables setting optional values for the session, which default to secure random values if not
156133
// set.
157134
type ServerLoginInitOptions struct {
@@ -175,30 +152,75 @@ func getServerLoginInitOptions(options []ServerLoginInitOptions) *ake.Options {
175152
return &op
176153
}
177154

178-
// LoginInit responds to a KE1 message with a KE2 message given server credentials and client record.
155+
// SetKeyMaterial set the server's identity and mandatory key material to be used during LoginInit().
156+
// All these values must be the same as used during client registration and remain the same across protocol execution
157+
// for a given registered client.
158+
//
159+
// - serverIdentity can be nil, in which case it will be set to serverPublicKey.
160+
// - serverSecretKey is the server's secret AKE key.
161+
// - serverPublicKey is the server's public AKE key to the serverSecretKey.
162+
// - oprfSeed is the long-term OPRF input seed.
163+
func (s *Server) SetKeyMaterial(serverIdentity, serverSecretKey, serverPublicKey, oprfSeed []byte) error {
164+
sks := s.conf.Group.NewScalar()
165+
if err := sks.Decode(serverSecretKey); err != nil {
166+
return fmt.Errorf("invalid server AKE secret key: %w", err)
167+
}
168+
169+
if sks.IsZero() {
170+
return ErrZeroSKS
171+
}
172+
173+
if len(oprfSeed) != s.conf.Hash.Size() {
174+
return ErrInvalidOPRFSeedLength
175+
}
176+
177+
if len(serverPublicKey) != s.conf.Group.ElementLength() {
178+
return ErrInvalidPksLength
179+
}
180+
181+
if err := s.conf.Group.NewElement().Decode(serverPublicKey); err != nil {
182+
return fmt.Errorf("invalid server public key: %w", err)
183+
}
184+
185+
s.keyMaterial = &keyMaterial{
186+
serverIdentity: serverIdentity,
187+
serverSecretKey: sks,
188+
serverPublicKey: serverPublicKey,
189+
oprfSeed: oprfSeed,
190+
}
191+
192+
return nil
193+
}
194+
195+
// LoginInit responds to a KE1 message with a KE2 message a client record.
179196
func (s *Server) LoginInit(
180197
ke1 *message.KE1,
181-
serverIdentity, serverSecretKey, serverPublicKey, oprfSeed []byte,
182198
record *ClientRecord,
183199
options ...ServerLoginInitOptions,
184200
) (*message.KE2, error) {
185-
sks, err := s.verifyInitInput(serverSecretKey, serverPublicKey, oprfSeed, record)
186-
if err != nil {
187-
return nil, err
201+
if s.keyMaterial == nil {
202+
return nil, ErrNoServerKeyMaterial
188203
}
189204

205+
if len(record.Envelope) != s.conf.EnvelopeSize {
206+
return nil, ErrInvalidEnvelopeLength
207+
}
208+
209+
// We've checked that the server's public key and the client's envelope are of correct length,
210+
// thus ensuring that the subsequent xor-ing input is the same length as the encryption pad.
211+
190212
op := getServerLoginInitOptions(options)
191213

192-
response := s.credentialResponse(ke1.CredentialRequest, serverPublicKey,
193-
record.RegistrationRecord, record.CredentialIdentifier, oprfSeed, record.TestMaskNonce)
214+
response := s.credentialResponse(ke1.CredentialRequest, s.keyMaterial.serverPublicKey,
215+
record.RegistrationRecord, record.CredentialIdentifier, s.keyMaterial.oprfSeed, record.TestMaskNonce)
194216

195217
identities := ake.Identities{
196218
ClientIdentity: record.ClientIdentity,
197-
ServerIdentity: serverIdentity,
219+
ServerIdentity: s.keyMaterial.serverIdentity,
198220
}
199-
identities.SetIdentities(record.PublicKey, serverPublicKey)
221+
identities.SetIdentities(record.PublicKey, s.keyMaterial.serverPublicKey)
200222

201-
ke2 := s.Ake.Response(s.conf, &identities, sks, record.PublicKey, ke1, response, *op)
223+
ke2 := s.Ake.Response(s.conf, &identities, s.keyMaterial.serverSecretKey, record.PublicKey, ke1, response, *op)
202224

203225
return ke2, nil
204226
}

tests/client_test.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package opaque_test
1010

1111
import (
12+
"log"
1213
"strings"
1314
"testing"
1415

@@ -117,16 +118,23 @@ func TestClientFinish_BadMaskedResponse(t *testing.T) {
117118
if err != nil {
118119
t.Fatal(err)
119120
}
121+
120122
server, err := conf.conf.Server()
121123
if err != nil {
122124
t.Fatal(err)
123125
}
126+
124127
sks, pks := conf.conf.KeyGen()
125128
oprfSeed := internal.RandomBytes(conf.conf.Hash.Size())
129+
130+
if err := server.SetKeyMaterial(nil, sks, pks, oprfSeed); err != nil {
131+
t.Fatal(err)
132+
}
133+
126134
rec := buildRecord(credID, oprfSeed, []byte("yo"), pks, client, server)
127135

128136
ke1 := client.LoginInit([]byte("yo"))
129-
ke2, _ := server.LoginInit(ke1, nil, sks, pks, oprfSeed, rec)
137+
ke2, _ := server.LoginInit(ke1, rec)
130138

131139
goodLength := client.GetConf().Group.ElementLength() + client.GetConf().EnvelopeSize
132140
expected := "invalid masked response length"
@@ -156,16 +164,23 @@ func TestClientFinish_InvalidEnvelopeTag(t *testing.T) {
156164
if err != nil {
157165
t.Fatal(err)
158166
}
167+
159168
server, err := conf.conf.Server()
160169
if err != nil {
161170
t.Fatal(err)
162171
}
172+
163173
sks, pks := conf.conf.KeyGen()
164174
oprfSeed := internal.RandomBytes(conf.conf.Hash.Size())
175+
176+
if err := server.SetKeyMaterial(nil, sks, pks, oprfSeed); err != nil {
177+
t.Fatal(err)
178+
}
179+
165180
rec := buildRecord(credID, oprfSeed, []byte("yo"), pks, client, server)
166181

167182
ke1 := client.LoginInit([]byte("yo"))
168-
ke2, _ := server.LoginInit(ke1, nil, sks, pks, oprfSeed, rec)
183+
ke2, _ := server.LoginInit(ke1, rec)
169184

170185
env, _, err := getEnvelope(client, ke2)
171186
if err != nil {
@@ -207,16 +222,23 @@ func TestClientFinish_InvalidKE2KeyEncoding(t *testing.T) {
207222
if err != nil {
208223
t.Fatal(err)
209224
}
225+
210226
server, err := conf.conf.Server()
211227
if err != nil {
212228
t.Fatal(err)
213229
}
230+
214231
sks, pks := conf.conf.KeyGen()
215232
oprfSeed := internal.RandomBytes(conf.conf.Hash.Size())
233+
234+
if err := server.SetKeyMaterial(nil, sks, pks, oprfSeed); err != nil {
235+
t.Fatal(err)
236+
}
237+
216238
rec := buildRecord(credID, oprfSeed, []byte("yo"), pks, client, server)
217239

218240
ke1 := client.LoginInit([]byte("yo"))
219-
ke2, _ := server.LoginInit(ke1, nil, sks, pks, oprfSeed, rec)
241+
ke2, _ := server.LoginInit(ke1, rec)
220242
// epks := ke2.EpkS
221243

222244
// tamper epks
@@ -283,16 +305,23 @@ func TestClientFinish_InvalidKE2Mac(t *testing.T) {
283305
if err != nil {
284306
t.Fatal(err)
285307
}
308+
286309
server, err := conf.conf.Server()
287310
if err != nil {
288311
t.Fatal(err)
289312
}
313+
290314
sks, pks := conf.conf.KeyGen()
291315
oprfSeed := internal.RandomBytes(conf.conf.Hash.Size())
316+
317+
if err := server.SetKeyMaterial(nil, sks, pks, oprfSeed); err != nil {
318+
log.Fatal(err)
319+
}
320+
292321
rec := buildRecord(credID, oprfSeed, []byte("yo"), pks, client, server)
293322

294323
ke1 := client.LoginInit([]byte("yo"))
295-
ke2, _ := server.LoginInit(ke1, nil, sks, pks, oprfSeed, rec)
324+
ke2, _ := server.LoginInit(ke1, rec)
296325

297326
ke2.Mac = internal.RandomBytes(client.GetConf().MAC.Size())
298327
expected := "finalizing AKE: invalid server mac"

0 commit comments

Comments
 (0)