Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup fixed time and allow using time offset for crypto operations #239

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crypto/attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (keyRing *KeyRing) newAttachmentProcessor(

config := &packet.Config{
DefaultCipher: packet.CipherAES256,
Time: getTimeGenerator(),
Time: GetTime,
}

reader, writer := io.Pipe()
Expand Down Expand Up @@ -163,7 +163,7 @@ func (keyRing *KeyRing) DecryptAttachment(message *PGPSplitMessage) (*PlainMessa

encryptedReader := io.MultiReader(keyReader, dataReader)

config := &packet.Config{Time: getTimeGenerator()}
config := &packet.Config{Time: GetTime}

md, err := openpgp.ReadMessage(encryptedReader, privKeyEntries, nil, config)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion crypto/attachment_manual.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func (keyRing *KeyRing) NewManualAttachmentProcessor(
// encryption config
config := &packet.Config{
DefaultCipher: packet.CipherAES256,
Time: getTimeGenerator(),
Time: GetTime,
}

// goroutine that reads the key packet
Expand Down
14 changes: 8 additions & 6 deletions crypto/attachment_manual_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
)

func TestManualAttachmentProcessor(t *testing.T) {
pgp.latestServerTime = 1615394034
defer func() { pgp.latestServerTime = testTime }()
defer setFixedTime(testTime)
setFixedTime(1615394034)

passphrase := []byte("wUMuF/lkDPYWH/0ZqqY8kJKw7YJg6kS")
pk, err := NewKeyFromArmored(readTestFile("att_key", false))
if err != nil {
Expand Down Expand Up @@ -86,8 +87,8 @@ func TestManualAttachmentProcessor(t *testing.T) {
}

func TestManualAttachmentProcessorNotEnoughBuffer(t *testing.T) {
pgp.latestServerTime = 1615394034
defer func() { pgp.latestServerTime = testTime }()
defer setFixedTime(testTime)
setFixedTime(1615394034)
passphrase := []byte("wUMuF/lkDPYWH/0ZqqY8kJKw7YJg6kS")
pk, err := NewKeyFromArmored(readTestFile("att_key", false))
if err != nil {
Expand Down Expand Up @@ -141,8 +142,9 @@ func TestManualAttachmentProcessorNotEnoughBuffer(t *testing.T) {
}

func TestManualAttachmentProcessorEmptyBuffer(t *testing.T) {
pgp.latestServerTime = 1615394034
defer func() { pgp.latestServerTime = testTime }()
defer setFixedTime(testTime)
setFixedTime(1615394034)

passphrase := []byte("wUMuF/lkDPYWH/0ZqqY8kJKw7YJg6kS")
pk, err := NewKeyFromArmored(readTestFile("att_key", false))
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion crypto/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func readTestFile(name string, trimNewlines bool) string {
}

func init() {
UpdateTime(testTime) // 2019-05-13T13:37:07+00:00
setFixedTime(testTime) // 2019-05-13T13:37:07+00:00

initGenerateKeys()
initArmoredKeys()
Expand Down
6 changes: 4 additions & 2 deletions crypto/gopenpgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import "sync"
// GopenPGP is used as a "namespace" for many of the functions in this package.
// It is a struct that keeps track of time skew between server and client.
type GopenPGP struct {
latestServerTime int64
fixedTime int64
timeOffset int64
generationOffset int64
lock *sync.RWMutex
}

var pgp = GopenPGP{
latestServerTime: 0,
fixedTime: 0,
timeOffset: 0,
generationOffset: 0,
lock: &sync.RWMutex{},
}
Expand Down
12 changes: 6 additions & 6 deletions crypto/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,26 +264,26 @@ func (key *Key) GetPublicKey() (b []byte, err error) {

// CanVerify returns true if any of the subkeys can be used for verification.
func (key *Key) CanVerify() bool {
_, canVerify := key.entity.SigningKey(getNow())
_, canVerify := key.entity.SigningKey(GetTime())
return canVerify
}

// CanEncrypt returns true if any of the subkeys can be used for encryption.
func (key *Key) CanEncrypt() bool {
_, canEncrypt := key.entity.EncryptionKey(getNow())
_, canEncrypt := key.entity.EncryptionKey(GetTime())
return canEncrypt
}

// IsExpired checks whether the key is expired.
func (key *Key) IsExpired() bool {
i := key.entity.PrimaryIdentity()
return key.entity.PrimaryKey.KeyExpired(i.SelfSignature, getNow()) || // primary key has expired
i.SelfSignature.SigExpired(getNow()) // user ID self-signature has expired
return key.entity.PrimaryKey.KeyExpired(i.SelfSignature, GetTime()) || // primary key has expired
i.SelfSignature.SigExpired(GetTime()) // user ID self-signature has expired
}

// IsRevoked checks whether the key or the primary identity has a valid revocation signature.
func (key *Key) IsRevoked() bool {
return key.entity.Revoked(getNow()) || key.entity.PrimaryIdentity().Revoked(getNow())
return key.entity.Revoked(GetTime()) || key.entity.PrimaryIdentity().Revoked(GetTime())
}

// IsPrivate returns true if the key is private.
Expand Down Expand Up @@ -447,7 +447,7 @@ func generateKey(
cfg := &packet.Config{
Algorithm: packet.PubKeyAlgoRSA,
RSABits: bits,
Time: getKeyGenerationTimeGenerator(),
Time: getKeyGenerationTime,
DefaultHash: crypto.SHA256,
DefaultCipher: packet.CipherAES256,
DefaultCompressionAlgo: packet.CompressionZLIB,
Expand Down
42 changes: 38 additions & 4 deletions crypto/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,42 @@ func TestIsExpired(t *testing.T) {
assert.Exactly(t, true, futureKey.IsExpired())
}

func TestGeneratedWithOffset(t *testing.T) {
defer setFixedTime(testTime)
setFixedTime(0)
defer SetTimeOffset(0)
var timeOffset int64 = 30
SetTimeOffset(timeOffset)

// generate key with offset
keyTestRSA, err := GenerateKey(keyTestName, keyTestDomain, "rsa", 1024)
if err != nil {
panic("Cannot generate RSA key:" + err.Error())
}

// Bring back offset to zero
SetTimeOffset(0)

// Verify if key was generated with offset but lower by 1 sec to compensate time passing in test
assert.GreaterOrEqual(t, keyTestRSA.entity.PrimaryKey.CreationTime.Unix(), GetUnixTime()+timeOffset-1)
}

func TestGeneratedWithKeyOffset(t *testing.T) {
defer setFixedTime(testTime)
setFixedTime(testTime)
defer SetKeyGenerationOffset(0)
var timeOffset int64 = 30
SetKeyGenerationOffset(timeOffset)

// generate key with key offset
keyTestRSA, err := GenerateKey(keyTestName, keyTestDomain, "rsa", 1024)
if err != nil {
panic("Cannot generate RSA key:" + err.Error())
}

assert.GreaterOrEqual(t, keyTestRSA.entity.PrimaryKey.CreationTime.Unix(), testTime+timeOffset)
}

func TestGenerateKeyWithPrimes(t *testing.T) {
prime1, _ := base64.StdEncoding.DecodeString(
"/thF8zjjk6fFx/y9NId35NFx8JTA7jvHEl+gI0dp9dIl9trmeZb+ESZ8f7bNXUmTI8j271kyenlrVJiqwqk80Q==")
Expand Down Expand Up @@ -418,10 +454,8 @@ func TestKeyCapabilities(t *testing.T) {
}

func TestRevokedKeyCapabilities(t *testing.T) {
pgp.latestServerTime = 1632219895
defer func() {
pgp.latestServerTime = testTime
}()
defer setFixedTime(testTime)
setFixedTime(1632219895)

revokedKey, err := NewKeyFromArmored(readTestFile("key_revoked", false))
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions crypto/keyring_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func asymmetricEncryptStream(
) (encryptWriter io.WriteCloser, err error) {
config := &packet.Config{
DefaultCipher: packet.CipherAES256,
Time: getTimeGenerator(),
Time: GetTime,
}

if compress {
Expand Down Expand Up @@ -337,7 +337,7 @@ func asymmetricDecryptStream(
but the caller will remove signature expiration errors later on.
See processSignatureExpiration().
*/
return getNow()
return GetTime()
}
return time.Unix(verifyTime, 0)
},
Expand Down
2 changes: 1 addition & 1 deletion crypto/keyring_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (keyRing *KeyRing) EncryptSessionKey(sk *SessionKey) ([]byte, error) {

pubKeys := make([]*packet.PublicKey, 0, len(keyRing.entities))
for _, e := range keyRing.entities {
encryptionKey, ok := e.EncryptionKey(getNow())
encryptionKey, ok := e.EncryptionKey(GetTime())
if !ok {
return nil, errors.New("gopenpgp: encryption key is unavailable for key id " + strconv.FormatUint(e.PrimaryKey.KeyId, 16))
}
Expand Down
7 changes: 3 additions & 4 deletions crypto/keyring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,10 @@ func TestKeyringCapabilities(t *testing.T) {
}

func TestVerificationTime(t *testing.T) {
defer setFixedTime(testTime)
setFixedTime(1632312383)
message := NewPlainMessageFromString("Hello")
pgp.latestServerTime = 1632312383
defer func() {
pgp.latestServerTime = testTime
}()

enc, err := keyRingTestPublic.Encrypt(
message,
keyRingTestPrivate,
Expand Down
10 changes: 4 additions & 6 deletions crypto/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,8 @@ func TestBinaryMessageEncryption(t *testing.T) {
}

func TestIssue11(t *testing.T) {
pgp.latestServerTime = 1559655272
defer func() {
pgp.latestServerTime = testTime
}()
defer setFixedTime(testTime)
setFixedTime(1559655272)

var issue11Password = []byte("1234")

Expand Down Expand Up @@ -258,8 +256,8 @@ func TestIssue11(t *testing.T) {
}

func TestDummy(t *testing.T) {
pgp.latestServerTime = 1636644417
defer func() { pgp.latestServerTime = testTime }()
defer setFixedTime(testTime)
setFixedTime(1636644417)

dummyKey, err := NewKeyFromArmored(readTestFile("key_dummy", false))
if err != nil {
Expand Down
5 changes: 4 additions & 1 deletion crypto/mime.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ func parseMIME(
if err != nil {
return nil, nil, nil, errors.Wrap(err, "gopenpgp: error in reading message")
}
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()}
config := &packet.Config{
DefaultCipher: packet.CipherAES256,
Time: GetTime,
}

h := textproto.MIMEHeader(mm.Header)
mmBodyData, err := ioutil.ReadAll(mm.Body)
Expand Down
5 changes: 3 additions & 2 deletions crypto/password.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func EncryptSessionKeyWithPassword(sk *SessionKey, password []byte) ([]byte, err

config := &packet.Config{
DefaultCipher: cf,
Time: GetTime,
}

err = packet.SerializeSymmetricKeyEncryptedReuseKey(outbuf, sk.Key, password, config)
Expand All @@ -109,7 +110,7 @@ func passwordEncrypt(message *PlainMessage, password []byte) ([]byte, error) {

config := &packet.Config{
DefaultCipher: packet.CipherAES256,
Time: getTimeGenerator(),
Time: GetTime,
}

hints := &openpgp.FileHints{
Expand Down Expand Up @@ -148,7 +149,7 @@ func passwordDecrypt(encryptedIO io.Reader, password []byte) (*PlainMessage, err
}

config := &packet.Config{
Time: getTimeGenerator(),
Time: GetTime,
}

var emptyKeyRing openpgp.EntityList
Expand Down
9 changes: 6 additions & 3 deletions crypto/sessionkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ func (sk *SessionKey) GetBase64Key() string {

// RandomToken generates a random token with the specified key size.
func RandomToken(size int) ([]byte, error) {
config := &packet.Config{DefaultCipher: packet.CipherAES256}
config := &packet.Config{
DefaultCipher: packet.CipherAES256,
Time: GetTime,
}
symKey := make([]byte, size)
if _, err := io.ReadFull(config.Random(), symKey); err != nil {
return nil, errors.Wrap(err, "gopenpgp: error in generating random token")
Expand Down Expand Up @@ -225,7 +228,7 @@ func encryptStreamWithSessionKey(
}

config := &packet.Config{
Time: getTimeGenerator(),
Time: GetTime,
DefaultCipher: dc,
}

Expand Down Expand Up @@ -426,7 +429,7 @@ func decryptStreamWithSessionKey(
}

config := &packet.Config{
Time: getTimeGenerator(),
Time: GetTime,
}

if verificationContext != nil {
Expand Down
2 changes: 1 addition & 1 deletion crypto/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ func signMessageDetached(
) (*PGPSignature, error) {
config := &packet.Config{
DefaultHash: crypto.SHA512,
Time: getTimeGenerator(),
Time: GetTime,
}

signEntity, err := signKeyRing.getSigningEntity()
Expand Down
Loading