Source file src/crypto/internal/fips140deps/fipsdeps_test.go

     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 fipsdeps
     6  
     7  import (
     8  	"internal/testenv"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  // AllowedInternalPackages are internal packages that can be imported from the
    14  // FIPS module. The API of these packages ends up locked for the lifetime of the
    15  // validated module, which can be years.
    16  //
    17  // DO NOT add new packages here just to make the tests pass.
    18  var AllowedInternalPackages = map[string]bool{
    19  	// entropy.Depleted/Seed is the entropy source, and sysrand.Read
    20  	// is the actual (but uncredited!) random bytes source.
    21  	"crypto/internal/entropy":        true,
    22  	"crypto/internal/entropy/v1.0.0": true,
    23  	"crypto/internal/sysrand":        true,
    24  
    25  	// impl.Register is how the packages expose their alternative
    26  	// implementations to tests outside the module.
    27  	"crypto/internal/impl": true,
    28  
    29  	// randutil.MaybeReadByte is used in non-FIPS mode by GenerateKey functions.
    30  	"crypto/internal/randutil": true,
    31  
    32  	// constanttime are the constant-time intrinsics.
    33  	"crypto/internal/constanttime": true,
    34  }
    35  
    36  func TestImports(t *testing.T) {
    37  	cmd := testenv.Command(t, testenv.GoToolPath(t), "list", "-f", `{{$path := .ImportPath -}}
    38  {{range .Imports -}}
    39  {{$path}} {{.}}
    40  {{end -}}
    41  {{range .TestImports -}}
    42  {{$path}} {{.}}
    43  {{end -}}
    44  {{range .XTestImports -}}
    45  {{$path}} {{.}}
    46  {{end -}}`, "crypto/internal/fips140/...")
    47  	bout, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
    48  	if err != nil {
    49  		t.Fatalf("go list: %v\n%s", err, bout)
    50  	}
    51  	out := string(bout)
    52  
    53  	// In a snapshot, all the paths are crypto/internal/fips140/v1.2.3/...
    54  	// Determine the version number and remove it for the test.
    55  	_, v, _ := strings.Cut(out, "crypto/internal/fips140/")
    56  	v, _, _ = strings.Cut(v, "/")
    57  	v, _, _ = strings.Cut(v, " ")
    58  	if strings.HasPrefix(v, "v") && strings.Count(v, ".") == 2 {
    59  		out = strings.ReplaceAll(out, "crypto/internal/fips140/"+v, "crypto/internal/fips140")
    60  	}
    61  
    62  	allPackages := make(map[string]bool)
    63  
    64  	// importCheck is the set of packages that import crypto/internal/fips140/check.
    65  	importCheck := make(map[string]bool)
    66  
    67  	for _, line := range strings.Split(out, "\n") {
    68  		if line == "" {
    69  			continue
    70  		}
    71  		pkg, importedPkg, _ := strings.Cut(line, " ")
    72  
    73  		allPackages[pkg] = true
    74  
    75  		if importedPkg == "crypto/internal/fips140/check" {
    76  			importCheck[pkg] = true
    77  		}
    78  
    79  		// Ensure we don't import any unexpected internal package from the FIPS
    80  		// module, since we can't change the module source after it starts
    81  		// validation. This locks in the API of otherwise internal packages.
    82  		if importedPkg == "crypto/internal/fips140" ||
    83  			strings.HasPrefix(importedPkg, "crypto/internal/fips140/") ||
    84  			strings.HasPrefix(importedPkg, "crypto/internal/fips140deps/") {
    85  			continue
    86  		}
    87  		if AllowedInternalPackages[importedPkg] {
    88  			continue
    89  		}
    90  		if strings.Contains(importedPkg, "internal") {
    91  			t.Errorf("unexpected import of internal package: %s -> %s", pkg, importedPkg)
    92  		}
    93  	}
    94  
    95  	// Ensure that all packages except check and check's dependencies import check.
    96  	for pkg := range allPackages {
    97  		switch pkg {
    98  		case "crypto/internal/fips140/check":
    99  		case "crypto/internal/fips140":
   100  		case "crypto/internal/fips140/alias":
   101  		case "crypto/internal/fips140/subtle":
   102  		case "crypto/internal/fips140/hmac":
   103  		case "crypto/internal/fips140/sha3":
   104  		case "crypto/internal/fips140/sha256":
   105  		case "crypto/internal/fips140/sha512":
   106  		default:
   107  			if !importCheck[pkg] {
   108  				t.Errorf("package %s does not import crypto/internal/fips140/check", pkg)
   109  			}
   110  		}
   111  	}
   112  }
   113  

View as plain text