فهرست منبع

cmd/ca: prevent out-of-memory on 32bit systems (#1834) (#1852)

(cherry picked from commit 6fcb9263342dba356c0acab7d956169c95648c30)

Co-authored-by: sn0w <me@sn0w.re>
Wade Simmons 2 ماه پیش
والد
کامیت
c2ad75e459
2فایلهای تغییر یافته به همراه42 افزوده شده و 7 حذف شده
  1. 17 2
      cmd/nebula-cert/ca.go
  2. 25 5
      cmd/nebula-cert/ca_test.go

+ 17 - 2
cmd/nebula-cert/ca.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"io"
 	"math"
+	"math/bits"
 	"net/netip"
 	"os"
 	"strings"
@@ -44,6 +45,20 @@ type caFlags struct {
 }
 
 func newCaFlags() *caFlags {
+	// prevent running out of memory on 32-bit systems by defaulting to
+	// RFC9106's recommendation for memory-constrained environments
+	var (
+		defaultArgonMemory     uint
+		defaultArgonIterations uint
+	)
+	if bits.UintSize == 32 {
+		defaultArgonMemory = 64 * 1024
+		defaultArgonIterations = 3
+	} else {
+		defaultArgonMemory = 2 * 1024 * 1024
+		defaultArgonIterations = 1
+	}
+
 	cf := caFlags{set: flag.NewFlagSet("ca", flag.ContinueOnError)}
 	cf.set.Usage = func() {}
 	cf.name = cf.set.String("name", "", "Required: name of the certificate authority")
@@ -55,9 +70,9 @@ func newCaFlags() *caFlags {
 	cf.groups = cf.set.String("groups", "", "Optional: comma separated list of groups. This will limit which groups subordinate certs can use")
 	cf.networks = cf.set.String("networks", "", "Optional: comma separated list of ip address and network in CIDR notation. This will limit which ip addresses and networks subordinate certs can use in networks")
 	cf.unsafeNetworks = cf.set.String("unsafe-networks", "", "Optional: comma separated list of ip address and network in CIDR notation. This will limit which ip addresses and networks subordinate certs can use in unsafe networks")
-	cf.argonMemory = cf.set.Uint("argon-memory", 2*1024*1024, "Optional: Argon2 memory parameter (in KiB) used for encrypted private key passphrase")
+	cf.argonMemory = cf.set.Uint("argon-memory", defaultArgonMemory, "Optional: Argon2 memory parameter (in KiB) used for encrypted private key passphrase")
 	cf.argonParallelism = cf.set.Uint("argon-parallelism", 4, "Optional: Argon2 parallelism parameter used for encrypted private key passphrase")
-	cf.argonIterations = cf.set.Uint("argon-iterations", 1, "Optional: Argon2 iterations parameter used for encrypted private key passphrase")
+	cf.argonIterations = cf.set.Uint("argon-iterations", defaultArgonIterations, "Optional: Argon2 iterations parameter used for encrypted private key passphrase")
 	cf.encryption = cf.set.Bool("encrypt", false, "Optional: prompt for passphrase and write out-key in an encrypted format")
 	cf.curve = cf.set.String("curve", "25519", "EdDSA/ECDSA Curve (25519, P256)")
 	cf.p11url = p11Flag(cf.set)

+ 25 - 5
cmd/nebula-cert/ca_test.go

@@ -7,7 +7,9 @@ import (
 	"bytes"
 	"encoding/pem"
 	"errors"
+	"math/bits"
 	"os"
+	"strconv"
 	"strings"
 	"testing"
 	"time"
@@ -22,6 +24,18 @@ func Test_caSummary(t *testing.T) {
 }
 
 func Test_caHelp(t *testing.T) {
+	var (
+		defaultArgonMemory     string
+		defaultArgonIterations string
+	)
+	if bits.UintSize == 32 {
+		defaultArgonMemory = strconv.Itoa(64 * 1024)
+		defaultArgonIterations = strconv.Itoa(3)
+	} else {
+		defaultArgonMemory = strconv.Itoa(2 * 1024 * 1024)
+		defaultArgonIterations = strconv.Itoa(1)
+	}
+
 	ob := &bytes.Buffer{}
 	caHelp(ob)
 	assert.Equal(
@@ -29,9 +43,9 @@ func Test_caHelp(t *testing.T) {
 		"Usage of "+os.Args[0]+" ca <flags>: create a self signed certificate authority\n"+
 			"  Pass \"-\" to any path flag to read from stdin or write to stdout.\n"+
 			"  -argon-iterations uint\n"+
-			"    \tOptional: Argon2 iterations parameter used for encrypted private key passphrase (default 1)\n"+
+			"    \tOptional: Argon2 iterations parameter used for encrypted private key passphrase (default "+defaultArgonIterations+")\n"+
 			"  -argon-memory uint\n"+
-			"    \tOptional: Argon2 memory parameter (in KiB) used for encrypted private key passphrase (default 2097152)\n"+
+			"    \tOptional: Argon2 memory parameter (in KiB) used for encrypted private key passphrase (default "+defaultArgonMemory+")\n"+
 			"  -argon-parallelism uint\n"+
 			"    \tOptional: Argon2 parallelism parameter used for encrypted private key passphrase (default 4)\n"+
 			"  -curve string\n"+
@@ -188,10 +202,16 @@ func Test_ca(t *testing.T) {
 	k, _ := pem.Decode(rb)
 	ned, err := cert.UnmarshalNebulaEncryptedData(k.Bytes)
 	require.NoError(t, err)
-	// we won't know salt in advance, so just check start of string
-	assert.Equal(t, uint32(2*1024*1024), ned.EncryptionMetadata.Argon2Parameters.Memory)
+
+	if bits.UintSize == 32 {
+		assert.Equal(t, uint32(64*1024), ned.EncryptionMetadata.Argon2Parameters.Memory)
+		assert.Equal(t, uint32(3), ned.EncryptionMetadata.Argon2Parameters.Iterations)
+	} else {
+		assert.Equal(t, uint32(2*1024*1024), ned.EncryptionMetadata.Argon2Parameters.Memory)
+		assert.Equal(t, uint32(1), ned.EncryptionMetadata.Argon2Parameters.Iterations)
+	}
+
 	assert.Equal(t, uint8(4), ned.EncryptionMetadata.Argon2Parameters.Parallelism)
-	assert.Equal(t, uint32(1), ned.EncryptionMetadata.Argon2Parameters.Iterations)
 
 	// verify the key is valid and decrypt-able
 	var curve cert.Curve