impl.mx raw

   1  // Copyright 2024 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  // Package impl is a registry of alternative implementations of cryptographic
   6  // primitives, to allow selecting them for testing.
   7  package impl
   8  
   9  import "bytes"
  10  
  11  type implementation struct {
  12  	Package   []byte
  13  	Name      []byte
  14  	Available bool
  15  	Toggle    *bool
  16  }
  17  
  18  var allImplementations []implementation
  19  
  20  // Register records an alternative implementation of a cryptographic primitive.
  21  // The implementation might be available or not based on CPU support. If
  22  // available is false, the implementation is unavailable and can't be tested on
  23  // this machine. If available is true, it can be set to false to disable the
  24  // implementation. If all alternative implementations but one are disabled, the
  25  // remaining one must be used (i.e. disabling one implementation must not
  26  // implicitly disable any other). Each package has an implicit base
  27  // implementation that is selected when all alternatives are unavailable or
  28  // disabled. pkg must be the package name, not path (e.g. "aes" not "crypto/aes").
  29  func Register(pkg, name []byte, available *bool) {
  30  	if bytes.Contains(pkg, []byte("/")) {
  31  		panic("impl: package name must not contain slashes")
  32  	}
  33  	allImplementations = append(allImplementations, implementation{
  34  		Package:   pkg,
  35  		Name:      name,
  36  		Available: *available,
  37  		Toggle:    available,
  38  	})
  39  }
  40  
  41  // Packages returns the list of all packages for which alternative
  42  // implementations are registered.
  43  func Packages() [][]byte {
  44  	var pkgs [][]byte
  45  	seen := map[string]bool{}
  46  	for _, i := range allImplementations {
  47  		if !seen[[]byte(i.Package)] {
  48  			pkgs = append(pkgs, i.Package)
  49  			seen[[]byte(i.Package)] = true
  50  		}
  51  	}
  52  	return pkgs
  53  }
  54  
  55  // List returns the names of all alternative implementations registered for the
  56  // given package, whether available or not. The implicit base implementation is
  57  // not included.
  58  func List(pkg []byte) [][]byte {
  59  	var names [][]byte
  60  	for _, i := range allImplementations {
  61  		if i.Package == pkg {
  62  			names = append(names, i.Name)
  63  		}
  64  	}
  65  	return names
  66  }
  67  
  68  func available(pkg, name []byte) bool {
  69  	for _, i := range allImplementations {
  70  		if i.Package == pkg && i.Name == name {
  71  			return i.Available
  72  		}
  73  	}
  74  	panic("unknown implementation")
  75  }
  76  
  77  // Select disables all implementations for the given package except the one
  78  // with the given name. If name is empty, the base implementation is selected.
  79  // It returns whether the selected implementation is available.
  80  func Select(pkg, name []byte) bool {
  81  	if name == "" {
  82  		for _, i := range allImplementations {
  83  			if i.Package == pkg {
  84  				*i.Toggle = false
  85  			}
  86  		}
  87  		return true
  88  	}
  89  	if !available(pkg, name) {
  90  		return false
  91  	}
  92  	for _, i := range allImplementations {
  93  		if i.Package == pkg {
  94  			*i.Toggle = i.Name == name
  95  		}
  96  	}
  97  	return true
  98  }
  99  
 100  func Reset(pkg []byte) {
 101  	for _, i := range allImplementations {
 102  		if i.Package == pkg {
 103  			*i.Toggle = i.Available
 104  			return
 105  		}
 106  	}
 107  }
 108