github.com/letsencrypt/boulder@v0.20251208.0/goodkey/good_key_test.go (about)

     1  package goodkey
     2  
     3  import (
     4  	"context"
     5  	"crypto/ecdsa"
     6  	"crypto/elliptic"
     7  	"crypto/rand"
     8  	"crypto/rsa"
     9  	"fmt"
    10  	"math/big"
    11  	"testing"
    12  
    13  	"github.com/letsencrypt/boulder/test"
    14  )
    15  
    16  // testingPolicy is a simple policy which allows all of the key types, so that
    17  // the unit tests can exercise checks against all key types.
    18  var testingPolicy = &KeyPolicy{allowedKeys: AllowedKeys{
    19  	RSA2048: true, RSA3072: true, RSA4096: true,
    20  	ECDSAP256: true, ECDSAP384: true, ECDSAP521: true,
    21  }}
    22  
    23  func TestUnknownKeyType(t *testing.T) {
    24  	notAKey := struct{}{}
    25  	err := testingPolicy.GoodKey(context.Background(), notAKey)
    26  	test.AssertError(t, err, "Should have rejected a key of unknown type")
    27  	test.AssertEquals(t, err.Error(), "unsupported key type struct {}")
    28  }
    29  
    30  func TestNilKey(t *testing.T) {
    31  	err := testingPolicy.GoodKey(context.Background(), nil)
    32  	test.AssertError(t, err, "Should have rejected a nil key")
    33  	test.AssertEquals(t, err.Error(), "unsupported key type <nil>")
    34  }
    35  
    36  func TestSmallModulus(t *testing.T) {
    37  	pubKey := rsa.PublicKey{
    38  		N: big.NewInt(0),
    39  		E: 65537,
    40  	}
    41  	// 2040 bits
    42  	_, ok := pubKey.N.SetString("104192126510885102608953552259747211060428328569316484779167706297543848858189721071301121307701498317286069484848193969810800653457088975832436062805901725915630417996487259956349018066196416400386483594314258078114607080545265502078791826837453107382149801328758721235866366842649389274931060463277516954884108984101391466769505088222180613883737986792254164577832157921425082478871935498631777878563742033332460445633026471887331001305450139473524438241478798689974351175769895824322173301257621327448162705637127373457350813027123239805772024171112299987923305882261194120410409098448380641378552305583392176287", 10)
    43  	if !ok {
    44  		t.Errorf("error parsing pubkey modulus")
    45  	}
    46  	err := testingPolicy.GoodKey(context.Background(), &pubKey)
    47  	test.AssertError(t, err, "Should have rejected too-short key")
    48  	test.AssertEquals(t, err.Error(), "key size not supported: 2040")
    49  }
    50  
    51  func TestLargeModulus(t *testing.T) {
    52  	pubKey := rsa.PublicKey{
    53  		N: big.NewInt(0),
    54  		E: 65537,
    55  	}
    56  	// 4097 bits
    57  	_, ok := pubKey.N.SetString("1528586537844618544364689295678280797814937047039447018548513699782432768815684971832418418955305671838918285565080181315448131784543332408348488544125812746629522583979538961638790013578302979210481729874191053412386396889481430969071543569003141391030053024684850548909056275565684242965892176703473950844930842702506635531145654194239072799616096020023445127233557468234181352398708456163013484600764686209741158795461806441111028922165846800488957692595308009319392149669715238691709012014980470238746838534949750493558807218940354555205690667168930634644030378921382266510932028134500172599110460167962515262077587741235811653717121760943005253103187409557573174347385738572144714188928416780963680160418832333908040737262282830643745963536624555340279793555475547508851494656512855403492456740439533790565640263514349940712999516725281940465613417922773583725174223806589481568984323871222072582132221706797917380250216291620957692131931099423995355390698925093903005385497308399692769135287821632877871068909305276870015125960884987746154344006895331078411141197233179446805991116541744285238281451294472577537413640009811940462311100056023815261650331552185459228689469446389165886801876700815724561451940764544990177661873073", 10)
    58  	if !ok {
    59  		t.Errorf("error parsing pubkey modulus")
    60  	}
    61  	err := testingPolicy.GoodKey(context.Background(), &pubKey)
    62  	test.AssertError(t, err, "Should have rejected too-long key")
    63  	test.AssertEquals(t, err.Error(), "key size not supported: 4097")
    64  }
    65  
    66  func TestModulusModulo8(t *testing.T) {
    67  	bigOne := big.NewInt(1)
    68  	key := rsa.PublicKey{
    69  		N: bigOne.Lsh(bigOne, 2048),
    70  		E: 5,
    71  	}
    72  	err := testingPolicy.GoodKey(context.Background(), &key)
    73  	test.AssertError(t, err, "Should have rejected modulus with length not divisible by 8")
    74  	test.AssertEquals(t, err.Error(), "key size not supported: 2049")
    75  }
    76  
    77  var mod2048 = big.NewInt(0).Sub(big.NewInt(0).Lsh(big.NewInt(1), 2048), big.NewInt(1))
    78  
    79  func TestNonStandardExp(t *testing.T) {
    80  	evenMod := big.NewInt(0).Add(big.NewInt(1).Lsh(big.NewInt(1), 2047), big.NewInt(2))
    81  	key := rsa.PublicKey{
    82  		N: evenMod,
    83  		E: (1 << 16),
    84  	}
    85  	err := testingPolicy.GoodKey(context.Background(), &key)
    86  	test.AssertError(t, err, "Should have rejected non-standard exponent")
    87  	test.AssertEquals(t, err.Error(), "key exponent must be 65537")
    88  }
    89  
    90  func TestEvenModulus(t *testing.T) {
    91  	evenMod := big.NewInt(0).Add(big.NewInt(1).Lsh(big.NewInt(1), 2047), big.NewInt(2))
    92  	key := rsa.PublicKey{
    93  		N: evenMod,
    94  		E: (1 << 16) + 1,
    95  	}
    96  	err := testingPolicy.GoodKey(context.Background(), &key)
    97  	test.AssertError(t, err, "Should have rejected even modulus")
    98  	test.AssertEquals(t, err.Error(), "key divisible by small prime")
    99  }
   100  
   101  func TestModulusDivisibleBySmallPrime(t *testing.T) {
   102  	key := rsa.PublicKey{
   103  		N: mod2048,
   104  		E: (1 << 16) + 1,
   105  	}
   106  	err := testingPolicy.GoodKey(context.Background(), &key)
   107  	test.AssertError(t, err, "Should have rejected modulus divisible by 3")
   108  	test.AssertEquals(t, err.Error(), "key divisible by small prime")
   109  }
   110  
   111  func TestROCA(t *testing.T) {
   112  	n, ok := big.NewInt(1).SetString("19089470491547632015867380494603366846979936677899040455785311493700173635637619562546319438505971838982429681121352968394792665704951454132311441831732124044135181992768774222852895664400681270897445415599851900461316070972022018317962889565731866601557238345786316235456299813772607869009873279585912430769332375239444892105064608255089298943707214066350230292124208314161171265468111771687514518823144499250339825049199688099820304852696380797616737008621384107235756455735861506433065173933123259184114000282435500939123478591192413006994709825840573671701120771013072419520134975733578923370992644987545261926257", 10)
   113  	if !ok {
   114  		t.Fatal("failed to parse")
   115  	}
   116  	key := rsa.PublicKey{
   117  		N: n,
   118  		E: 65537,
   119  	}
   120  	err := testingPolicy.GoodKey(context.Background(), &key)
   121  	test.AssertError(t, err, "Should have rejected ROCA-weak key")
   122  	test.AssertEquals(t, err.Error(), "key generated by vulnerable Infineon-based hardware")
   123  }
   124  
   125  func TestGoodKey(t *testing.T) {
   126  	private, err := rsa.GenerateKey(rand.Reader, 2048)
   127  	test.AssertNotError(t, err, "Error generating key")
   128  	test.AssertNotError(t, testingPolicy.GoodKey(context.Background(), &private.PublicKey), "Should have accepted good key")
   129  }
   130  
   131  func TestECDSABadCurve(t *testing.T) {
   132  	for _, curve := range invalidCurves {
   133  		private, err := ecdsa.GenerateKey(curve, rand.Reader)
   134  		test.AssertNotError(t, err, "Error generating key")
   135  		err = testingPolicy.GoodKey(context.Background(), &private.PublicKey)
   136  		test.AssertError(t, err, "Should have rejected key with unsupported curve")
   137  		test.AssertEquals(t, err.Error(), fmt.Sprintf("ECDSA curve %s not allowed", curve.Params().Name))
   138  	}
   139  }
   140  
   141  var invalidCurves = []elliptic.Curve{
   142  	elliptic.P224(),
   143  }
   144  
   145  var validCurves = []elliptic.Curve{
   146  	elliptic.P256(),
   147  	elliptic.P384(),
   148  	elliptic.P521(),
   149  }
   150  
   151  func TestECDSAGoodKey(t *testing.T) {
   152  	for _, curve := range validCurves {
   153  		private, err := ecdsa.GenerateKey(curve, rand.Reader)
   154  		test.AssertNotError(t, err, "Error generating key")
   155  		test.AssertNotError(t, testingPolicy.GoodKey(context.Background(), &private.PublicKey), "Should have accepted good key")
   156  	}
   157  }
   158  
   159  func TestECDSANotOnCurveX(t *testing.T) {
   160  	for _, curve := range validCurves {
   161  		// Change a public key so that it is no longer on the curve.
   162  		private, err := ecdsa.GenerateKey(curve, rand.Reader)
   163  		test.AssertNotError(t, err, "Error generating key")
   164  
   165  		private.X.Add(private.X, big.NewInt(1))
   166  		err = testingPolicy.GoodKey(context.Background(), &private.PublicKey)
   167  		test.AssertError(t, err, "Should not have accepted key not on the curve")
   168  		test.AssertEquals(t, err.Error(), "key point is not on the curve")
   169  	}
   170  }
   171  
   172  func TestECDSANotOnCurveY(t *testing.T) {
   173  	for _, curve := range validCurves {
   174  		// Again with Y.
   175  		private, err := ecdsa.GenerateKey(curve, rand.Reader)
   176  		test.AssertNotError(t, err, "Error generating key")
   177  
   178  		// Change the public key so that it is no longer on the curve.
   179  		private.Y.Add(private.Y, big.NewInt(1))
   180  		err = testingPolicy.GoodKey(context.Background(), &private.PublicKey)
   181  		test.AssertError(t, err, "Should not have accepted key not on the curve")
   182  		test.AssertEquals(t, err.Error(), "key point is not on the curve")
   183  	}
   184  }
   185  
   186  func TestECDSANegative(t *testing.T) {
   187  	for _, curve := range validCurves {
   188  		// Check that negative X is not accepted.
   189  		private, err := ecdsa.GenerateKey(curve, rand.Reader)
   190  		test.AssertNotError(t, err, "Error generating key")
   191  
   192  		private.X.Neg(private.X)
   193  		err = testingPolicy.GoodKey(context.Background(), &private.PublicKey)
   194  		test.AssertError(t, err, "Should not have accepted key with negative X")
   195  		test.AssertEquals(t, err.Error(), "key x, y must not be negative")
   196  
   197  		// Check that negative Y is not accepted.
   198  		private.X.Neg(private.X)
   199  		private.Y.Neg(private.Y)
   200  		err = testingPolicy.GoodKey(context.Background(), &private.PublicKey)
   201  		test.AssertError(t, err, "Should not have accepted key with negative Y")
   202  		test.AssertEquals(t, err.Error(), "key x, y must not be negative")
   203  	}
   204  }
   205  
   206  func TestECDSAXOutsideField(t *testing.T) {
   207  	for _, curve := range validCurves {
   208  		// Check that X outside [0, p-1] is not accepted.
   209  		private, err := ecdsa.GenerateKey(curve, rand.Reader)
   210  		test.AssertNotError(t, err, "Error generating key")
   211  
   212  		private.X.Mul(private.X, private.Curve.Params().P)
   213  		err = testingPolicy.GoodKey(context.Background(), &private.PublicKey)
   214  		test.AssertError(t, err, "Should not have accepted key with a X > p-1")
   215  		test.AssertEquals(t, err.Error(), "key x, y must not exceed P-1")
   216  	}
   217  }
   218  
   219  func TestECDSAYOutsideField(t *testing.T) {
   220  	for _, curve := range validCurves {
   221  		// Check that Y outside [0, p-1] is not accepted.
   222  		private, err := ecdsa.GenerateKey(curve, rand.Reader)
   223  		test.AssertNotError(t, err, "Error generating key")
   224  
   225  		private.X.Mul(private.Y, private.Curve.Params().P)
   226  		err = testingPolicy.GoodKey(context.Background(), &private.PublicKey)
   227  		test.AssertError(t, err, "Should not have accepted key with a Y > p-1")
   228  		test.AssertEquals(t, err.Error(), "key x, y must not exceed P-1")
   229  	}
   230  }
   231  
   232  func TestECDSAIdentity(t *testing.T) {
   233  	for _, curve := range validCurves {
   234  		// The point at infinity is 0,0, it should not be accepted.
   235  		public := ecdsa.PublicKey{
   236  			Curve: curve,
   237  			X:     big.NewInt(0),
   238  			Y:     big.NewInt(0),
   239  		}
   240  
   241  		err := testingPolicy.GoodKey(context.Background(), &public)
   242  		test.AssertError(t, err, "Should not have accepted key with point at infinity")
   243  		test.AssertEquals(t, err.Error(), "key x, y must not be the point at infinity")
   244  	}
   245  }
   246  
   247  func TestNonRefKey(t *testing.T) {
   248  	private, err := rsa.GenerateKey(rand.Reader, 2048)
   249  	test.AssertNotError(t, err, "Error generating key")
   250  	test.AssertError(t, testingPolicy.GoodKey(context.Background(), private.PublicKey), "Accepted non-reference key")
   251  }
   252  
   253  func TestDBBlocklistAccept(t *testing.T) {
   254  	for _, testCheck := range []BlockedKeyCheckFunc{
   255  		nil,
   256  		func(context.Context, []byte) (bool, error) {
   257  			return false, nil
   258  		},
   259  	} {
   260  		policy, err := NewPolicy(nil, testCheck)
   261  		test.AssertNotError(t, err, "NewKeyPolicy failed")
   262  
   263  		k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   264  		test.AssertNotError(t, err, "ecdsa.GenerateKey failed")
   265  		err = policy.GoodKey(context.Background(), k.Public())
   266  		test.AssertNotError(t, err, "GoodKey failed with a non-blocked key")
   267  	}
   268  }
   269  
   270  func TestDBBlocklistReject(t *testing.T) {
   271  	testCheck := func(context.Context, []byte) (bool, error) {
   272  		return true, nil
   273  	}
   274  
   275  	policy, err := NewPolicy(nil, testCheck)
   276  	test.AssertNotError(t, err, "NewKeyPolicy failed")
   277  
   278  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   279  	test.AssertNotError(t, err, "ecdsa.GenerateKey failed")
   280  	err = policy.GoodKey(context.Background(), k.Public())
   281  	test.AssertError(t, err, "GoodKey didn't fail with a blocked key")
   282  	test.AssertErrorIs(t, err, ErrBadKey)
   283  	test.AssertEquals(t, err.Error(), "public key is forbidden")
   284  }
   285  
   286  func TestDefaultAllowedKeys(t *testing.T) {
   287  	policy, err := NewPolicy(nil, nil)
   288  	test.AssertNotError(t, err, "NewPolicy with nil config failed")
   289  	test.Assert(t, policy.allowedKeys.RSA2048, "RSA 2048 should be allowed")
   290  	test.Assert(t, policy.allowedKeys.RSA3072, "RSA 3072 should be allowed")
   291  	test.Assert(t, policy.allowedKeys.RSA4096, "RSA 4096 should be allowed")
   292  	test.Assert(t, policy.allowedKeys.ECDSAP256, "NIST P256 should be allowed")
   293  	test.Assert(t, policy.allowedKeys.ECDSAP384, "NIST P384 should be allowed")
   294  	test.Assert(t, !policy.allowedKeys.ECDSAP521, "NIST P521 should not be allowed")
   295  
   296  	policy, err = NewPolicy(&Config{}, nil)
   297  	test.AssertNotError(t, err, "NewPolicy with nil config.AllowedKeys failed")
   298  	test.Assert(t, policy.allowedKeys.RSA2048, "RSA 2048 should be allowed")
   299  	test.Assert(t, policy.allowedKeys.RSA3072, "RSA 3072 should be allowed")
   300  	test.Assert(t, policy.allowedKeys.RSA4096, "RSA 4096 should be allowed")
   301  	test.Assert(t, policy.allowedKeys.ECDSAP256, "NIST P256 should be allowed")
   302  	test.Assert(t, policy.allowedKeys.ECDSAP384, "NIST P384 should be allowed")
   303  	test.Assert(t, !policy.allowedKeys.ECDSAP521, "NIST P521 should not be allowed")
   304  }
   305  
   306  func TestRSAStrangeSize(t *testing.T) {
   307  	k := &rsa.PublicKey{N: big.NewInt(10)}
   308  	err := testingPolicy.GoodKey(context.Background(), k)
   309  	test.AssertError(t, err, "expected GoodKey to fail")
   310  	test.AssertEquals(t, err.Error(), "key size not supported: 4")
   311  }
   312  
   313  func TestCheckPrimeFactorsTooClose(t *testing.T) {
   314  	type testCase struct {
   315  		name         string
   316  		p            string
   317  		q            string
   318  		expectRounds int
   319  	}
   320  
   321  	testCases := []testCase{
   322  		{
   323  			// The factors 59 and 101 multiply to 5959. The values a and b calculated
   324  			// by Fermat's method will be 80 and 21. The ceil of the square root of
   325  			// 5959 is 78. Therefore it takes 3 rounds of Fermat's method to find the
   326  			// factors.
   327  			name:         "tiny",
   328  			p:            "101",
   329  			q:            "59",
   330  			expectRounds: 3,
   331  		},
   332  		{
   333  			// These factors differ only in their second-to-last digit. They're so close
   334  			// that a single iteration of Fermat's method is sufficient to find them.
   335  			name:         "very close",
   336  			p:            "12451309173743450529024753538187635497858772172998414407116324997634262083672423797183640278969532658774374576700091736519352600717664126766443002156788367",
   337  			q:            "12451309173743450529024753538187635497858772172998414407116324997634262083672423797183640278969532658774374576700091736519352600717664126766443002156788337",
   338  			expectRounds: 1,
   339  		},
   340  		{
   341  			// These factors differ by slightly more than 2^256, which takes fourteen
   342  			// rounds to factor.
   343  			name:         "still too close",
   344  			p:            "11779932606551869095289494662458707049283241949932278009554252037480401854504909149712949171865707598142483830639739537075502512627849249573564209082969463",
   345  			q:            "11779932606551869095289494662458707049283241949932278009554252037480401854503793357623711855670284027157475142731886267090836872063809791989556295953329083",
   346  			expectRounds: 14,
   347  		},
   348  		{
   349  			// These factors come from a real canon printer in the wild with a broken
   350  			// key generation mechanism.
   351  			name:         "canon printer (2048 bit, 1 round)",
   352  			p:            "155536235030272749691472293262418471207550926406427515178205576891522284497518443889075039382254334975506248481615035474816604875321501901699955105345417152355947783063521554077194367454070647740704883461064399268622437721385112646454393005862535727615809073410746393326688230040267160616554768771412289114449",
   353  			q:            "155536235030272749691472293262418471207550926406427515178205576891522284497518443889075039382254334975506248481615035474816604875321501901699955105345417152355947783063521554077194367454070647740704883461064399268622437721385112646454393005862535727615809073410746393326688230040267160616554768771412289114113",
   354  			expectRounds: 1,
   355  		},
   356  		{
   357  			// These factors come from a real innsbruck printer in the wild with a
   358  			// broken key generation mechanism.
   359  			name:         "innsbruck printer (4096 bit, 1 round)",
   360  			p:            "25868808535211632564072019392873831934145242707953960515208595626279836366691068618582894100813803673421320899654654938470888358089618966238341690624345530870988951109006149164192566967552401505863871260691612081236189439839963332690997129144163260418447718577834226720411404568398865166471102885763673744513186211985402019037772108416694793355840983833695882936201196462579254234744648546792097397517107797153785052856301942321429858537224127598198913168345965493941246097657533085617002572245972336841716321849601971924830462771411171570422802773095537171762650402420866468579928479284978914972383512240254605625661",
   361  			q:            "25868808535211632564072019392873831934145242707953960515208595626279836366691068618582894100813803673421320899654654938470888358089618966238341690624345530870988951109006149164192566967552401505863871260691612081236189439839963332690997129144163260418447718577834226720411404568398865166471102885763673744513186211985402019037772108416694793355840983833695882936201196462579254234744648546792097397517107797153785052856301942321429858537224127598198913168345965493941246097657533085617002572245972336841716321849601971924830462771411171570422802773095537171762650402420866468579928479284978914972383512240254605624819",
   362  			expectRounds: 1,
   363  		},
   364  		{
   365  			// FIPS requires that |p-q| > 2^(nlen/2 - 100). For example, a 2048-bit
   366  			// RSA key must have prime factors with a difference of at least 2^924.
   367  			// These two factors have a difference of exactly 2^924 + 4, just *barely*
   368  			// FIPS-compliant. Their first different digit is in column 52 of this
   369  			// file, which makes them vastly further apart than the cases above. Their
   370  			// product cannot be factored even with 100,000,000 rounds of Fermat's
   371  			// Algorithm.
   372  			name:         "barely FIPS compliant (2048 bit)",
   373  			p:            "151546560166767007654995655231369126386504564489055366370313539237722892921762327477057109592614214965864835328962951695621854530739049166771701397343693962526456985866167580660948398404000483264137738772983130282095332559392185543017295488346592188097443414824871619976114874896240350402349774470198190454623",
   374  			q:            "151546560166767007654995655231510939369872272987323309037144546294925352276321214430320942815891873491060949332482502812040326472743233767963240491605860423063942576391584034077877871768428333113881339606298282107984376151546711223157061364850161576363709081794948857957944390170575452970542651659150041855843",
   375  			expectRounds: -1,
   376  		},
   377  	}
   378  
   379  	for _, tc := range testCases {
   380  		t.Run(tc.name, func(t *testing.T) {
   381  			p, ok := new(big.Int).SetString(tc.p, 10)
   382  			if !ok {
   383  				t.Fatalf("failed to load prime factor p (%s)", tc.p)
   384  			}
   385  
   386  			q, ok := new(big.Int).SetString(tc.q, 10)
   387  			if !ok {
   388  				t.Fatalf("failed to load prime factor q (%s)", tc.q)
   389  			}
   390  
   391  			n := new(big.Int).Mul(p, q)
   392  			err := checkPrimeFactorsTooClose(n, 100)
   393  
   394  			if tc.expectRounds > 0 {
   395  				test.AssertError(t, err, "failed to factor n")
   396  				test.AssertContains(t, err.Error(), fmt.Sprintf("p: %s", tc.p))
   397  				test.AssertContains(t, err.Error(), fmt.Sprintf("q: %s", tc.q))
   398  				test.AssertContains(t, err.Error(), fmt.Sprintf("in %d rounds", tc.expectRounds))
   399  			} else {
   400  				test.AssertNil(t, err, "factored the unfactorable")
   401  			}
   402  		})
   403  	}
   404  }
   405  
   406  func benchFermat(rounds int, b *testing.B) {
   407  	n := big.NewInt(0)
   408  	n.SetString("801622717394169050106926578578301725055526605503706912100006286161529273473377413824975745384114446662904851914935980611269769546695796451504160869649117000521094368058953989236438103975426680952076533198797388295193391779933559668812684470909409457778161223896975426492372231040386646816154793996920467596916193680611886097694746368434138296683172992347929528214464827172059378866098534956467670429228681248968588692628197119606249988365750115578731538804653322115223303388019261933988266126675740797091559541980722545880793708750882230374320698192373040882555154628949384420712168289605526223733016176898368282023301917856921049583659644200174763940543991507836551835324807116188739389620816364505209568211448815747330488813651206715564392791134964121857454359816296832013457790067067190116393364546525054134704119475840526673114964766611499226043189928040037210929720682839683846078550615582181112536768195193557758454282232948765374797970874053642822355832904812487562117265271449547063765654262549173209805579494164339236981348054782533307762260970390747872669357067489756517340817289701322583209366268084923373164395703994945233187987667632964509271169622904359262117908604555420100186491963838567445541249128944592555657626247", 10)
   409  	for b.Loop() {
   410  		if checkPrimeFactorsTooClose(n, rounds) != nil {
   411  			b.Fatal("factored the unfactorable!")
   412  		}
   413  	}
   414  }
   415  
   416  func BenchmarkFermat1(b *testing.B)     { benchFermat(1, b) }
   417  func BenchmarkFermat10(b *testing.B)    { benchFermat(10, b) }
   418  func BenchmarkFermat100(b *testing.B)   { benchFermat(100, b) }
   419  func BenchmarkFermat1000(b *testing.B)  { benchFermat(1000, b) }
   420  func BenchmarkFermat10000(b *testing.B) { benchFermat(10000, b) }