Source file src/crypto/internal/fips140test/acvp_fips140v1.28_test.go

     1  // Copyright 2026 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  //go:build !fips140v1.0 && !fips140v1.26
     6  
     7  package fipstest
     8  
     9  import (
    10  	"crypto/internal/fips140/bigmod"
    11  	"crypto/internal/fips140/rsa"
    12  	"crypto/internal/fips140/sha256"
    13  	"crypto/internal/fips140/sha3"
    14  	"crypto/internal/fips140/sha512"
    15  	"crypto/rand"
    16  
    17  	_ "embed"
    18  	"encoding/binary"
    19  	"errors"
    20  	"fmt"
    21  	"hash"
    22  	"math/big"
    23  )
    24  
    25  //go:embed acvp_capabilities_fips140v1.28.json
    26  var capabilitiesJson []byte
    27  
    28  var testConfigFile = "acvp_test_fips140v1.28.config.json"
    29  
    30  func init() {
    31  	// RSA keyGen for keyFormat=crt capability. Previous versions used standard
    32  	commands["RSA/keyGen/crt"] = cmdRsaKeyGenCrtAft()
    33  
    34  	// RSA sigGen additional hash algorithms (adds SHA2-512 truncated hashes, SHA-3)
    35  	// Support for PSS saltLen argument.
    36  	commands["RSA/sigGen/SHA2-224/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha256.New224() }, "SHA-224", false)
    37  	commands["RSA/sigGen/SHA2-256/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha256.New() }, "SHA-256", false)
    38  	commands["RSA/sigGen/SHA2-384/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha512.New384() }, "SHA-384", false)
    39  	commands["RSA/sigGen/SHA2-512/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha512.New() }, "SHA-512", false)
    40  	commands["RSA/sigGen/SHA2-512/224/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha512.New512_224() }, "SHA-512/224", false)
    41  	commands["RSA/sigGen/SHA2-512/256/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha512.New512_256() }, "SHA-512/256", false)
    42  	commands["RSA/sigGen/SHA3-224/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha3.New224() }, "SHA3-224", false)
    43  	commands["RSA/sigGen/SHA3-256/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha3.New256() }, "SHA3-256", false)
    44  	commands["RSA/sigGen/SHA3-384/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha3.New384() }, "SHA3-384", false)
    45  	commands["RSA/sigGen/SHA3-512/pkcs1v1.5"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha3.New512() }, "SHA3-512", false)
    46  	commands["RSA/sigGen/SHA2-512/224/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha512.New512_224() }, "SHA-512/224", true)
    47  	commands["RSA/sigGen/SHA2-512/256/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha512.New512_256() }, "SHA-512/256", true)
    48  	commands["RSA/sigGen/SHA3-224/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha3.New224() }, "SHA3-224", true)
    49  	commands["RSA/sigGen/SHA3-256/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha3.New256() }, "SHA3-256", true)
    50  	commands["RSA/sigGen/SHA3-384/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha3.New384() }, "SHA3-384", true)
    51  	commands["RSA/sigGen/SHA3-512/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha3.New512() }, "SHA3-512", true)
    52  	commands["RSA/sigGen/SHA2-224/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha256.New224() }, "SHA-224", true)
    53  	commands["RSA/sigGen/SHA2-256/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha256.New() }, "SHA-256", true)
    54  	commands["RSA/sigGen/SHA2-384/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha512.New384() }, "SHA-384", true)
    55  	commands["RSA/sigGen/SHA2-512/pss"] = cmdRsaSigGenSaltLenAft(func() hash.Hash { return sha512.New() }, "SHA-512", true)
    56  
    57  	// RSA sigGen with pubExpMode=random capability. Previous versions used fixed.
    58  	// Also adds SHA2-512 truncated hashes. Notably SHA-3 is not supported by ACVP
    59  	// for RSA sigVer.
    60  	commands["RSA/sigVer/SHA2-224/pkcs1v1.5"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha256.New224() }, "SHA-224", false)
    61  	commands["RSA/sigVer/SHA2-256/pkcs1v1.5"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha256.New() }, "SHA-256", false)
    62  	commands["RSA/sigVer/SHA2-384/pkcs1v1.5"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha512.New384() }, "SHA-384", false)
    63  	commands["RSA/sigVer/SHA2-512/pkcs1v1.5"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha512.New() }, "SHA-512", false)
    64  	commands["RSA/sigVer/SHA2-512/224/pkcs1v1.5"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha512.New512_224() }, "SHA-512/224", false)
    65  	commands["RSA/sigVer/SHA2-512/256/pkcs1v1.5"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha512.New512_256() }, "SHA-512/256", false)
    66  	commands["RSA/sigVer/SHA2-224/pss"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha256.New224() }, "SHA-224", true)
    67  	commands["RSA/sigVer/SHA2-256/pss"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha256.New() }, "SHA-256", true)
    68  	commands["RSA/sigVer/SHA2-384/pss"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha512.New384() }, "SHA-384", true)
    69  	commands["RSA/sigVer/SHA2-512/pss"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha512.New() }, "SHA-512", true)
    70  	commands["RSA/sigVer/SHA2-512/224/pss"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha512.New512_224() }, "SHA-512/224", true)
    71  	commands["RSA/sigVer/SHA2-512/256/pss"] = cmdRsaSigVerRandExpAft(func() hash.Hash { return sha512.New512_256() }, "SHA-512/256", true)
    72  
    73  	// KTS-IFC with keyGenerationMethods=rsakpg2-crt (random exponent, CRT format).
    74  	// Previous version used rsakpg1-basic (fixed exponent, basic format).
    75  	commands["KTS-IFC/SHA2-224/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha256.New224() })
    76  	commands["KTS-IFC/SHA2-256/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha256.New() })
    77  	commands["KTS-IFC/SHA2-384/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha512.New384() })
    78  	commands["KTS-IFC/SHA2-512/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha512.New() })
    79  	commands["KTS-IFC/SHA2-512/224/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha512.New512_224() })
    80  	commands["KTS-IFC/SHA2-512/256/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha512.New512_256() })
    81  	commands["KTS-IFC/SHA3-224/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha3.New224() })
    82  	commands["KTS-IFC/SHA3-256/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha3.New256() })
    83  	commands["KTS-IFC/SHA3-384/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha3.New384() })
    84  	commands["KTS-IFC/SHA3-512/responder/crt"] = cmdKtsIfcResponderRandExpCrtAft(func() hash.Hash { return sha3.New512() })
    85  }
    86  
    87  func cmdRsaKeyGenCrtAft() command {
    88  	return command{
    89  		requiredArgs: 1, // Modulus bit-size
    90  		handler: func(args [][]byte) ([][]byte, error) {
    91  			bitSize := binary.LittleEndian.Uint32(args[0])
    92  
    93  			key, err := getRSAKey((int)(bitSize))
    94  			if err != nil {
    95  				return nil, fmt.Errorf("generating RSA key: %w", err)
    96  			}
    97  
    98  			N, e, d, P, Q, dP, dQ, qInv := key.Export()
    99  
   100  			eBytes := make([]byte, 4)
   101  			binary.BigEndian.PutUint32(eBytes, uint32(e))
   102  
   103  			return [][]byte{eBytes, P, Q, N, d, dP, dQ, qInv}, nil
   104  		},
   105  	}
   106  }
   107  
   108  func cmdRsaSigGenSaltLenAft(hashFunc func() hash.Hash, hashName string, pss bool) command {
   109  	return command{
   110  		requiredArgs: 3, // Modulus bit-size, message, saltLen
   111  		handler: func(args [][]byte) ([][]byte, error) {
   112  			bitSize := binary.LittleEndian.Uint32(args[0])
   113  			msg := args[1]
   114  			saltLen := binary.LittleEndian.Uint32(args[2])
   115  
   116  			key, err := getRSAKey((int)(bitSize))
   117  			if err != nil {
   118  				return nil, fmt.Errorf("generating RSA key: %w", err)
   119  			}
   120  
   121  			h := hashFunc()
   122  			h.Write(msg)
   123  			digest := h.Sum(nil)
   124  
   125  			var sig []byte
   126  			if !pss {
   127  				sig, err = rsa.SignPKCS1v15(key, hashName, digest)
   128  				if err != nil {
   129  					return nil, fmt.Errorf("signing RSA message: %w", err)
   130  				}
   131  			} else {
   132  				sig, err = rsa.SignPSS(rand.Reader, key, hashFunc(), digest, (int)(saltLen))
   133  				if err != nil {
   134  					return nil, fmt.Errorf("signing RSA message: %w", err)
   135  				}
   136  			}
   137  
   138  			N, e, _, _, _, _, _, _ := key.Export()
   139  			eBytes := make([]byte, 4)
   140  			binary.BigEndian.PutUint32(eBytes, uint32(e))
   141  
   142  			return [][]byte{N, eBytes, sig}, nil
   143  		},
   144  	}
   145  }
   146  
   147  func cmdRsaSigVerRandExpAft(hashFunc func() hash.Hash, hashName string, pss bool) command {
   148  	return command{
   149  		requiredArgs: 4, // n, e, message, signature
   150  		handler: func(args [][]byte) ([][]byte, error) {
   151  			nBytes := args[0]
   152  			eBytes := args[1]
   153  			msg := args[2]
   154  			sig := args[3]
   155  
   156  			n, err := bigmod.NewModulus(nBytes)
   157  			if err != nil {
   158  				return nil, fmt.Errorf("invalid RSA modulus: %w", err)
   159  			}
   160  
   161  			h := hashFunc()
   162  			h.Write(msg)
   163  			digest := h.Sum(nil)
   164  
   165  			if len(eBytes) < 32/8 || (len(eBytes) == 32/8 && eBytes[0] < 0x80) {
   166  				paddedE := make([]byte, 4)
   167  				copy(paddedE[4-len(eBytes):], eBytes)
   168  				e := int(binary.BigEndian.Uint32(paddedE))
   169  
   170  				pub := &rsa.PublicKey{
   171  					N: n,
   172  					E: e,
   173  				}
   174  
   175  				if !pss {
   176  					err = rsa.VerifyPKCS1v15(pub, hashName, digest, sig)
   177  				} else {
   178  					err = rsa.VerifyPSS(pub, hashFunc(), digest, sig)
   179  				}
   180  			} else {
   181  				pub := &rsa.TestingOnlyLargeExponentPublicKey{
   182  					N: n,
   183  					E: eBytes,
   184  				}
   185  
   186  				if !pss {
   187  					err = rsa.TestingOnlyLargeExponentVerifyPKCS1v15(pub, hashName, digest, sig)
   188  				} else {
   189  					err = rsa.TestingOnlyLargeExponentVerifyPSS(pub, hashFunc(), digest, sig)
   190  				}
   191  			}
   192  
   193  			if err != nil {
   194  				return [][]byte{{0}}, nil
   195  			}
   196  
   197  			return [][]byte{{1}}, nil
   198  		},
   199  	}
   200  }
   201  
   202  func cmdKtsIfcResponderRandExpCrtAft(h func() hash.Hash) command {
   203  	return command{
   204  		requiredArgs: 8, // n bytes, e bytes, p bytes, q bytes, dmp1 bytes, dmq1 bytes, iqmp bytes, c bytes
   205  		handler: func(args [][]byte) ([][]byte, error) {
   206  			nBytes := args[0]
   207  			eBytes := args[1]
   208  
   209  			pBytes := args[2]
   210  			qBytes := args[3]
   211  
   212  			dmp1Bytes := args[4]
   213  			dmq1Bytes := args[5]
   214  			iqmpBytes := args[6]
   215  
   216  			cBytes := args[7]
   217  
   218  			// We need to compute 'd' from the CRT values for NewPrivateKeyWithPrecomputation to
   219  			// check consistency.
   220  			p, q := new(big.Int).SetBytes(pBytes), new(big.Int).SetBytes(qBytes)
   221  			dP, dQ := new(big.Int).SetBytes(dmp1Bytes), new(big.Int).SetBytes(dmq1Bytes)
   222  			pMinus1, qMinus1 := new(big.Int).Sub(p, big.NewInt(1)), new(big.Int).Sub(q, big.NewInt(1))
   223  			x, y := new(big.Int), new(big.Int)
   224  			gcd := new(big.Int).GCD(x, y, pMinus1, qMinus1)
   225  			diff := new(big.Int).Sub(dQ, dP)
   226  			if new(big.Int).Mod(diff, gcd).Sign() != 0 {
   227  				return nil, errors.New("inconsistent CRT parameters")
   228  			}
   229  			lcm := new(big.Int).Mul(pMinus1, qMinus1)
   230  			lcm.Div(lcm, gcd)
   231  			d := new(big.Int).Mul(x, pMinus1)
   232  			d.Mul(d, diff).Div(d, gcd)
   233  			d.Add(d, dP).Mod(d, lcm)
   234  
   235  			var dkm []byte
   236  			var err error
   237  
   238  			if len(eBytes) < 32/8 || (len(eBytes) == 32/8 && eBytes[0] < 0x80) {
   239  				// Exponent fits in an int32, use standard PrivateKey.
   240  				paddedE := make([]byte, 4)
   241  				copy(paddedE[4-len(eBytes):], eBytes)
   242  				e := int(binary.BigEndian.Uint32(paddedE))
   243  
   244  				priv, err := rsa.NewPrivateKeyWithPrecomputation(nBytes, e, d.Bytes(), pBytes, qBytes, dmp1Bytes, dmq1Bytes, iqmpBytes)
   245  				if err != nil {
   246  					return nil, fmt.Errorf("failed to create private key: %v", err)
   247  				}
   248  
   249  				dkm, err = rsa.DecryptOAEP(h(), h(), priv, cBytes, nil)
   250  			} else {
   251  				// Large exponent, use TestingOnlyLargeExponentPrivateKey.
   252  				priv, err := rsa.TestingOnlyNewLargeExponentPrivateKeyWithPrecomputation(nBytes, eBytes, d.Bytes(), pBytes, qBytes, dmp1Bytes, dmq1Bytes, iqmpBytes)
   253  				if err != nil {
   254  					return nil, fmt.Errorf("failed to create private key: %v", err)
   255  				}
   256  
   257  				dkm, err = rsa.TestingOnlyLargeExponentDecryptOAEP(h(), h(), priv, cBytes, nil)
   258  			}
   259  			if err != nil {
   260  				return nil, fmt.Errorf("OAEP decryption failed: %v", err)
   261  			}
   262  
   263  			return [][]byte{dkm}, nil
   264  		},
   265  	}
   266  }
   267  

View as plain text