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

View as plain text