...

Source file src/github.com/letsencrypt/boulder/goodkey/blocked.go

Documentation: github.com/letsencrypt/boulder/goodkey

     1  package goodkey
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/sha256"
     6  	"encoding/base64"
     7  	"encoding/hex"
     8  	"errors"
     9  	"os"
    10  
    11  	"github.com/letsencrypt/boulder/core"
    12  	"github.com/letsencrypt/boulder/strictyaml"
    13  )
    14  
    15  // blockedKeys is a type for maintaining a map of SHA256 hashes
    16  // of SubjectPublicKeyInfo's that should be considered blocked.
    17  // blockedKeys are created by using loadBlockedKeysList.
    18  type blockedKeys map[core.Sha256Digest]bool
    19  
    20  var ErrWrongDecodedSize = errors.New("not enough bytes decoded for sha256 hash")
    21  
    22  // blocked checks if the given public key is considered administratively
    23  // blocked based on a SHA256 hash of the SubjectPublicKeyInfo.
    24  // Important: blocked should not be called except on a blockedKeys instance
    25  // returned from loadBlockedKeysList.
    26  // function should not be used until after `loadBlockedKeysList` has returned.
    27  func (b blockedKeys) blocked(key crypto.PublicKey) (bool, error) {
    28  	hash, err := core.KeyDigest(key)
    29  	if err != nil {
    30  		// the bool result should be ignored when err is != nil but to be on the
    31  		// paranoid side return true anyway so that a key we can't compute the
    32  		// digest for will always be blocked even if a caller foolishly discards the
    33  		// err result.
    34  		return true, err
    35  	}
    36  	return b[hash], nil
    37  }
    38  
    39  // loadBlockedKeysList creates a blockedKeys object that can be used to check if
    40  // a key is blocked. It creates a lookup map from a list of
    41  // SHA256 hashes of SubjectPublicKeyInfo's in the input YAML file
    42  // with the expected format:
    43  //
    44  //	blocked:
    45  //	  - cuwGhNNI6nfob5aqY90e7BleU6l7rfxku4X3UTJ3Z7M=
    46  //	  <snipped>
    47  //	  - Qebc1V3SkX3izkYRGNJilm9Bcuvf0oox4U2Rn+b4JOE=
    48  //
    49  // If no hashes are found in the input YAML an error is returned.
    50  func loadBlockedKeysList(filename string) (*blockedKeys, error) {
    51  	yamlBytes, err := os.ReadFile(filename)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	var list struct {
    57  		BlockedHashes    []string `yaml:"blocked"`
    58  		BlockedHashesHex []string `yaml:"blockedHashesHex"`
    59  	}
    60  	err = strictyaml.Unmarshal(yamlBytes, &list)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	if len(list.BlockedHashes) == 0 && len(list.BlockedHashesHex) == 0 {
    66  		return nil, errors.New("no blocked hashes in YAML")
    67  	}
    68  
    69  	blockedKeys := make(blockedKeys, len(list.BlockedHashes)+len(list.BlockedHashesHex))
    70  	for _, b64Hash := range list.BlockedHashes {
    71  		decoded, err := base64.StdEncoding.DecodeString(b64Hash)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		if len(decoded) != sha256.Size {
    76  			return nil, ErrWrongDecodedSize
    77  		}
    78  		var sha256Digest core.Sha256Digest
    79  		copy(sha256Digest[:], decoded[0:sha256.Size])
    80  		blockedKeys[sha256Digest] = true
    81  	}
    82  	for _, hexHash := range list.BlockedHashesHex {
    83  		decoded, err := hex.DecodeString(hexHash)
    84  		if err != nil {
    85  			return nil, err
    86  		}
    87  		if len(decoded) != sha256.Size {
    88  			return nil, ErrWrongDecodedSize
    89  		}
    90  		var sha256Digest core.Sha256Digest
    91  		copy(sha256Digest[:], decoded[0:sha256.Size])
    92  		blockedKeys[sha256Digest] = true
    93  	}
    94  	return &blockedKeys, nil
    95  }
    96  

View as plain text