Source file src/crypto/internal/fips140test/acvp_fips140v2.0_test.go

     1  // Copyright 2025 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
     6  
     7  package fipstest
     8  
     9  import (
    10  	"crypto/internal/fips140/mldsa"
    11  	_ "embed"
    12  	"fmt"
    13  )
    14  
    15  //go:embed acvp_capabilities_fips140v2.0.json
    16  var capabilitiesJson []byte
    17  
    18  var testConfigFile = "acvp_test_fips140v2.0.config.json"
    19  
    20  func init() {
    21  	commands["ML-DSA-44/keyGen"] = cmdMlDsaKeyGenAft(mldsa.NewPrivateKey44)
    22  	commands["ML-DSA-65/keyGen"] = cmdMlDsaKeyGenAft(mldsa.NewPrivateKey65)
    23  	commands["ML-DSA-87/keyGen"] = cmdMlDsaKeyGenAft(mldsa.NewPrivateKey87)
    24  	commands["ML-DSA-44/sigGen"] = cmdMlDsaSigGenAft()
    25  	commands["ML-DSA-65/sigGen"] = cmdMlDsaSigGenAft()
    26  	commands["ML-DSA-87/sigGen"] = cmdMlDsaSigGenAft()
    27  	commands["ML-DSA-44/sigVer"] = cmdMlDsaSigVerAft(mldsa.NewPublicKey44)
    28  	commands["ML-DSA-65/sigVer"] = cmdMlDsaSigVerAft(mldsa.NewPublicKey65)
    29  	commands["ML-DSA-87/sigVer"] = cmdMlDsaSigVerAft(mldsa.NewPublicKey87)
    30  }
    31  
    32  func cmdMlDsaKeyGenAft(keyGen func([]byte) (*mldsa.PrivateKey, error)) command {
    33  	return command{
    34  		requiredArgs: 1, // Seed
    35  		handler: func(args [][]byte) ([][]byte, error) {
    36  			seed := args[0]
    37  
    38  			sk, err := keyGen(seed)
    39  			if err != nil {
    40  				return nil, fmt.Errorf("generating ML-DSA 44 private key: %w", err)
    41  			}
    42  
    43  			// Important: we must return the full encoding of sk, not the seed.
    44  			return [][]byte{sk.PublicKey().Bytes(), mldsa.TestingOnlyPrivateKeySemiExpandedBytes(sk)}, nil
    45  		},
    46  	}
    47  }
    48  
    49  func cmdMlDsaSigGenAft() command {
    50  	return command{
    51  		requiredArgs: 5, // secret key, message, randomizer, mu, context
    52  		handler: func(args [][]byte) ([][]byte, error) {
    53  			skSmiExpanded := args[0]
    54  			message := args[1]         // Optional, exclusive with mu
    55  			randomizer := args[2]      // Optional
    56  			context := string(args[3]) // Optional
    57  			mu := args[4]              // Optional, exclusive with message
    58  
    59  			sk, err := mldsa.TestingOnlyNewPrivateKeyFromSemiExpanded(skSmiExpanded)
    60  			if err != nil {
    61  				return nil, fmt.Errorf("making ML-DSA private key from semi-expanded form: %w", err)
    62  			}
    63  
    64  			haveMessage := len(message) != 0
    65  			haveRandomizer := len(randomizer) != 0
    66  			haveMu := len(mu) != 0
    67  
    68  			var sig []byte
    69  			if haveMessage && !haveRandomizer && !haveMu {
    70  				sig, err = mldsa.SignDeterministic(sk, message, context)
    71  			} else if haveMessage && haveRandomizer && !haveMu {
    72  				sig, err = mldsa.TestingOnlySignWithRandom(sk, message, context, randomizer)
    73  			} else if !haveMessage && !haveRandomizer && haveMu {
    74  				sig, err = mldsa.SignExternalMuDeterministic(sk, mu)
    75  			} else if !haveMessage && haveRandomizer && haveMu {
    76  				sig, err = mldsa.TestingOnlySignExternalMuWithRandom(sk, mu, randomizer)
    77  			} else {
    78  				return nil, fmt.Errorf(
    79  					"unsupported ML-DSA sigGen args: have message=%v have randomizer=%v haveMu=%v haveContext=%v",
    80  					haveMessage, haveRandomizer, haveMu, len(context) != 0)
    81  			}
    82  
    83  			if err != nil {
    84  				return nil, fmt.Errorf("creating deterministic ML-DSA signature: %w", err)
    85  			}
    86  
    87  			return [][]byte{sig}, nil
    88  		},
    89  	}
    90  }
    91  
    92  func cmdMlDsaSigVerAft(pubKey func([]byte) (*mldsa.PublicKey, error)) command {
    93  	return command{
    94  		requiredArgs: 5, // public key, message, signature, context, mu
    95  		handler: func(args [][]byte) ([][]byte, error) {
    96  			pkRaw := args[0]
    97  			message := args[1] // Optional, exclusive with mu
    98  			signature := args[2]
    99  			context := string(args[3]) // Optional
   100  			mu := args[4]              // Optional, exclusive with message
   101  
   102  			pk, err := pubKey(pkRaw)
   103  			if err != nil {
   104  				return nil, fmt.Errorf("loading ML-DSA public key: %w", err)
   105  			}
   106  
   107  			haveMessage := len(message) != 0
   108  			haveMu := len(mu) != 0
   109  			if haveMessage && !haveMu {
   110  				err = mldsa.Verify(pk, message, signature, context)
   111  			} else if !haveMessage && haveMu {
   112  				err = mldsa.VerifyExternalMu(pk, mu, signature)
   113  			} else {
   114  				return nil, fmt.Errorf(
   115  					"unsupported ML-DSA sigVer args: have message=%v haveMu=%v haveContext=%v",
   116  					haveMessage, haveMu, len(context) != 0)
   117  			}
   118  
   119  			if err != nil {
   120  				return [][]byte{{0}}, nil
   121  			}
   122  
   123  			return [][]byte{{1}}, nil
   124  		},
   125  	}
   126  }
   127  

View as plain text