/
server.go
115 lines (90 loc) · 3.25 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
// https://spdx.org/licenses/MIT.html
// Package ake provides high-level functions for the 3DH AKE.
package ake
import (
"errors"
"github.com/bytemare/crypto/group"
"github.com/bytemare/opaque/internal"
"github.com/bytemare/opaque/internal/encoding"
cred "github.com/bytemare/opaque/internal/message"
"github.com/bytemare/opaque/message"
)
var errStateNotEmpty = errors.New("existing state is not empty")
// Server exposes the server's AKE functions and holds its state.
type Server struct {
clientMac []byte
sessionSecret []byte
// testing: integrated to support testing, to force values.
esk *group.Scalar
nonceS []byte
}
// NewServer returns a new, empty, 3DH server.
func NewServer() *Server {
return &Server{}
}
// SetValues - testing: integrated to support testing, to force values.
// There's no effect if esk, epk, and nonce have already been set in a previous call.
func (s *Server) SetValues(id group.Group, esk *group.Scalar, nonce []byte, nonceLen int) *group.Point {
es, nonce := setValues(id, esk, nonce, nonceLen)
if s.esk == nil || (esk != nil && s.esk != es) {
s.esk = es
}
if s.nonceS == nil {
s.nonceS = nonce
}
return id.Base().Mult(s.esk)
}
// Response produces a 3DH server response message.
func (s *Server) Response(p *internal.Parameters, serverIdentity []byte, serverSecretKey *group.Scalar, clientIdentity, clientPublicKey []byte,
ke1 *message.KE1, response *cred.CredentialResponse) (*message.KE2, error) {
epk := s.SetValues(p.Group, nil, nil, p.NonceLen)
nonce := s.nonceS
k := &coreKeys{s.esk, serverSecretKey, ke1.EpkU, clientPublicKey}
ke2 := &message.KE2{
CredentialResponse: response,
NonceS: nonce,
EpkS: encoding.PadPoint(epk.Bytes(), p.Group),
}
macs, sessionSecret, err := core3DH(server, p, k, clientIdentity, serverIdentity, ke1, ke2)
if err != nil {
return nil, err
}
s.sessionSecret = sessionSecret
s.clientMac = macs.clientMac
ke2.Mac = macs.serverMac
return ke2, nil
}
// SerializeState will return a []byte containing internal state of the Server.
func (s *Server) SerializeState() []byte {
state := make([]byte, len(s.clientMac)+len(s.sessionSecret))
i := copy(state, s.clientMac)
copy(state[i:], s.sessionSecret)
return state
}
// SetState will set the given clientMac and sessionSecret in the server's internal state.
func (s *Server) SetState(clientMac, sessionSecret []byte) error {
if len(s.clientMac) != 0 || len(s.sessionSecret) != 0 {
return errStateNotEmpty
}
s.clientMac = clientMac
s.sessionSecret = sessionSecret
return nil
}
// Finalize verifies the authentication tag contained in ke3.
func (s *Server) Finalize(p *internal.Parameters, ke3 *message.KE3) bool {
return p.MAC.Equal(s.clientMac, ke3.Mac)
}
// SessionKey returns the secret shared session key if a previous call to Response() was successful.
func (s *Server) SessionKey() []byte {
return s.sessionSecret
}
// ExpectedMAC returns the expected client MAC if a previous call to Response() was successful.
func (s *Server) ExpectedMAC() []byte {
return s.clientMac
}