diff --git a/client/internal/sam/datagram.go b/client/internal/sam/datagram.go index 0c0694a..daece4d 100644 --- a/client/internal/sam/datagram.go +++ b/client/internal/sam/datagram.go @@ -5,6 +5,7 @@ import ( "io" "strconv" "strings" + "time" "gosuda.org/ivnp/foundation" "gosuda.org/ivnp/interfaces/destination" @@ -175,7 +176,7 @@ func (s *samSession) parseReceivedDatagram(delivery networking.StreamingTunnelDe } return foundation.EncodeI2PBase64(packet.V1.From.Bytes()), packet.V1.Payload, true case networking.DatagramProtocolDatagram2: - valid, err := packet.V2.VerifyTarget(s.endpoint.Hash()) + valid, err := packet.V2.VerifyTargetAt(s.endpoint.Hash(), uint32(time.Now().Unix())) if err != nil || !valid || packet.V2.From.Hash() != delivery.From { return "", nil, false } diff --git a/client/internal/sam/private_destination.go b/client/internal/sam/private_destination.go index 0a56c7d..fdc0737 100644 --- a/client/internal/sam/private_destination.go +++ b/client/internal/sam/private_destination.go @@ -219,11 +219,11 @@ func parseOfflinePrivateKey(identity foundation.Identity, section []byte) (*offl return nil, ErrInvalidKey } offset := 6 - public := append([]byte(nil), section[offset:offset+publicLength]...) + public := section[offset : offset+publicLength] offset += publicLength - signature := append([]byte(nil), section[offset:offset+signatureLength]...) + signature := section[offset : offset+signatureLength] offset += signatureLength - transientPrivate := append([]byte(nil), section[offset:]...) + transientPrivate := section[offset:] return &offlinePrivateKey{ OfflineSignature: foundation.OfflineSignature{ Expires: binary.BigEndian.Uint32(section[:4]), diff --git a/client/internal/sam/protocol.go b/client/internal/sam/protocol.go index 7bcbc3b..5a4a6a2 100644 --- a/client/internal/sam/protocol.go +++ b/client/internal/sam/protocol.go @@ -149,6 +149,14 @@ func (s *Server) createSession(ctx context.Context, connection *serverConnection if meta, ok := local.OfflineSignature(); ok { meta := meta offline = &meta + if style == styleDatagram { + local.ReleaseSensitive() + return connection.writeLine("SESSION STATUS RESULT=INVALID_KEY") + } + if policy.Encrypted { + local.ReleaseSensitive() + return connection.writeLine("SESSION STATUS RESULT=INVALID_KEY") + } } private, err := encodePrivateDestination(local) if err != nil { diff --git a/foundation/address_generator.go b/foundation/address_generator.go index 3781a5b..f0226d4 100644 --- a/foundation/address_generator.go +++ b/foundation/address_generator.go @@ -305,10 +305,13 @@ func (d *LocalDestination) Sign(message []byte) ([]byte, error) { if d.offline != nil { switch d.offline.keyType { case SigningEdDSASHA512Ed25519: - return ed25519.Sign(ed25519.NewKeyFromSeed(d.offline.private), message), nil + private := ed25519.NewKeyFromSeed(d.offline.private) + defer clear(private) + return ed25519.Sign(private, message), nil case SigningRedDSASHA512Ed25519: var private [32]byte copy(private[:], d.offline.private) + defer clear(private[:]) return Red25519Sign(private, message) default: return nil, ErrEncryptedSigningKey diff --git a/foundation/offline_signature.go b/foundation/offline_signature.go index 62b04ff..f62ade0 100644 --- a/foundation/offline_signature.go +++ b/foundation/offline_signature.go @@ -18,13 +18,24 @@ type OfflineSignature struct { Signature []byte } -// SignedContent returns the authorized content (expires, key type, public key) -// covered by the offline signature. +// SignedContentLen returns the encoded length of the authorized content. +func (o OfflineSignature) SignedContentLen() int { return 6 + len(o.PublicKey) } + +// MarshalSignedContentTo serializes the authorized content into dst. +func (o OfflineSignature) MarshalSignedContentTo(dst []byte) (int, error) { + if len(dst) < o.SignedContentLen() { + return 0, ErrInvalidIdentity + } + binary.BigEndian.PutUint32(dst[:4], o.Expires) + binary.BigEndian.PutUint16(dst[4:6], uint16(o.Type)) + copy(dst[6:], o.PublicKey) + return o.SignedContentLen(), nil +} + +// SignedContent returns the authorized content (expires, key type, public key). func (o OfflineSignature) SignedContent() []byte { - signed := make([]byte, 6+len(o.PublicKey)) - binary.BigEndian.PutUint32(signed[:4], o.Expires) - binary.BigEndian.PutUint16(signed[4:6], uint16(o.Type)) - copy(signed[6:], o.PublicKey) + signed := make([]byte, o.SignedContentLen()) + _, _ = o.MarshalSignedContentTo(signed) return signed }