github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/saltpack_dec.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     7  	"io"
     8  
     9  	"github.com/keybase/saltpack"
    10  )
    11  
    12  func getStatusCodeFromDecryptionError(err *DecryptionError) (code int) {
    13  	switch err.Cause.Err.(type) {
    14  	case APINetError:
    15  		code = SCAPINetworkError
    16  	case saltpack.ErrNoSenderKey:
    17  		code = SCDecryptionKeyNotFound
    18  	case saltpack.ErrWrongMessageType:
    19  		code = SCWrongCryptoMsgType
    20  	}
    21  	return code
    22  }
    23  
    24  func SaltpackDecrypt(m MetaContext, source io.Reader, sink io.WriteCloser,
    25  	decryptionKeyring saltpack.SigncryptKeyring,
    26  	checkSenderMki func(*saltpack.MessageKeyInfo) error,
    27  	checkSenderSigningKey func(saltpack.SigningPublicKey) error,
    28  	keyResolver saltpack.SymmetricKeyResolver) (mki *saltpack.MessageKeyInfo, err error) {
    29  	defer func() {
    30  		if derr, ok := err.(DecryptionError); ok {
    31  			derr.Cause.StatusCode = getStatusCodeFromDecryptionError(&derr)
    32  			err = derr
    33  		}
    34  	}()
    35  
    36  	sc, newSource, err := ClassifyStream(source)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	if sc.Format != CryptoMessageFormatSaltpack {
    42  		return nil, WrongCryptoFormatError{
    43  			Wanted:    CryptoMessageFormatSaltpack,
    44  			Received:  sc.Format,
    45  			Operation: "decrypt",
    46  		}
    47  	}
    48  
    49  	source = newSource
    50  
    51  	// mki will be set for DH mode, senderSigningKey will be set for signcryption mode
    52  	plainsource, typ, mki, senderSigningKey, isArmored, brand, _, err := saltpack.ClassifyEncryptedStreamAndMakeDecoder(source, decryptionKeyring, keyResolver)
    53  	if err != nil {
    54  		return mki, DecryptionError{Cause: ErrorCause{Err: err}}
    55  	}
    56  
    57  	if typ == saltpack.MessageTypeEncryption && checkSenderMki != nil {
    58  		if err = checkSenderMki(mki); err != nil {
    59  			return mki, DecryptionError{Cause: ErrorCause{Err: err}}
    60  		}
    61  	}
    62  	if typ == saltpack.MessageTypeSigncryption && checkSenderSigningKey != nil {
    63  		if err = checkSenderSigningKey(senderSigningKey); err != nil {
    64  			return nil, DecryptionError{Cause: ErrorCause{Err: err}}
    65  		}
    66  	}
    67  
    68  	n, err := io.Copy(sink, plainsource)
    69  	if err != nil {
    70  		return mki, DecryptionError{Cause: ErrorCause{Err: err}}
    71  	}
    72  
    73  	if isArmored {
    74  		// Note: the following check always passes!
    75  		if err = checkSaltpackBrand(brand); err != nil {
    76  			return mki, DecryptionError{Cause: ErrorCause{Err: err}}
    77  		}
    78  	}
    79  
    80  	m.Debug("Decrypt: read %d bytes", n)
    81  
    82  	if err := sink.Close(); err != nil {
    83  		return mki, DecryptionError{Cause: ErrorCause{Err: err}}
    84  	}
    85  	return mki, nil
    86  }