Source file src/crypto/internal/fips140/cast.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 fips140
     6  
     7  import (
     8  	"crypto/internal/fips140deps/godebug"
     9  	"errors"
    10  	"strings"
    11  	_ "unsafe" // for go:linkname
    12  )
    13  
    14  // fatal is [runtime.fatal], pushed via linkname.
    15  //
    16  //go:linkname fatal crypto/internal/fips140.fatal
    17  func fatal(string)
    18  
    19  // failfipscast is a GODEBUG key allowing simulation of a CAST or PCT failure,
    20  // as required during FIPS 140-3 functional testing. The value is the whole name
    21  // of the target CAST or PCT.
    22  var failfipscast = godebug.Value("#failfipscast")
    23  
    24  // CAST runs the named Cryptographic Algorithm Self-Test (if operated in FIPS
    25  // mode) and aborts the program (stopping the module input/output and entering
    26  // the "error state") if the self-test fails.
    27  //
    28  // CASTs are mandatory self-checks that must be performed by FIPS 140-3 modules
    29  // before the algorithm is used. See Implementation Guidance 10.3.A.
    30  //
    31  // The name must not contain commas, colons, hashes, or equal signs.
    32  //
    33  // If a package p calls CAST from its init function, an import of p should also
    34  // be added to crypto/internal/fips140test. If a package p calls CAST on the first
    35  // use of the algorithm, an invocation of that algorithm should be added to
    36  // fipstest.TestConditionals.
    37  func CAST(name string, f func() error) {
    38  	if strings.ContainsAny(name, ",#=:") {
    39  		panic("fips: invalid self-test name: " + name)
    40  	}
    41  	if !Enabled {
    42  		return
    43  	}
    44  
    45  	err := f()
    46  	if name == failfipscast {
    47  		err = errors.New("simulated CAST failure")
    48  	}
    49  	if err != nil {
    50  		fatal("FIPS 140-3 self-test failed: " + name + ": " + err.Error())
    51  		panic("unreachable")
    52  	}
    53  	if debug {
    54  		println("FIPS 140-3 self-test passed:", name)
    55  	}
    56  }
    57  
    58  // PCT runs the named Pairwise Consistency Test (if operated in FIPS mode) and
    59  // aborts the program (stopping the module input/output and entering the "error
    60  // state") if the test fails.
    61  //
    62  // PCTs are mandatory for every generated (but not imported) key pair, including
    63  // ephemeral keys (which effectively doubles the cost of key establishment). See
    64  // Implementation Guidance 10.3.A Additional Comment 1.
    65  //
    66  // The name must not contain commas, colons, hashes, or equal signs.
    67  //
    68  // If a package p calls PCT during key generation, an invocation of that
    69  // function should be added to fipstest.TestConditionals.
    70  func PCT(name string, f func() error) {
    71  	if strings.ContainsAny(name, ",#=:") {
    72  		panic("fips: invalid self-test name: " + name)
    73  	}
    74  	if !Enabled {
    75  		return
    76  	}
    77  
    78  	err := f()
    79  	if name == failfipscast {
    80  		err = errors.New("simulated PCT failure")
    81  	}
    82  	if err != nil {
    83  		fatal("FIPS 140-3 self-test failed: " + name + ": " + err.Error())
    84  		panic("unreachable")
    85  	}
    86  	if debug {
    87  		println("FIPS 140-3 PCT passed:", name)
    88  	}
    89  }
    90  

View as plain text