Source file src/crypto/crypto_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  package crypto_test
     6  
     7  import (
     8  	"bytes"
     9  	"crypto"
    10  	"crypto/rand"
    11  	"crypto/rsa"
    12  	"crypto/sha256"
    13  	"crypto/x509"
    14  	"encoding/pem"
    15  	"errors"
    16  	"fmt"
    17  	"internal/testenv"
    18  	"io"
    19  	"io/fs"
    20  	"os"
    21  	"path/filepath"
    22  	"regexp"
    23  	"strings"
    24  	"testing"
    25  )
    26  
    27  type messageSignerOnly struct {
    28  	k *rsa.PrivateKey
    29  }
    30  
    31  func (s *messageSignerOnly) Public() crypto.PublicKey {
    32  	return s.k.Public()
    33  }
    34  
    35  func (s *messageSignerOnly) Sign(_ io.Reader, _ []byte, _ crypto.SignerOpts) ([]byte, error) {
    36  	return nil, errors.New("unimplemented")
    37  }
    38  
    39  func (s *messageSignerOnly) SignMessage(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
    40  	h := opts.HashFunc().New()
    41  	h.Write(msg)
    42  	digest := h.Sum(nil)
    43  	return s.k.Sign(rand, digest, opts)
    44  }
    45  
    46  func TestSignMessage(t *testing.T) {
    47  	block, _ := pem.Decode([]byte(strings.ReplaceAll(
    48  		`-----BEGIN RSA TESTING KEY-----
    49  MIIEowIBAAKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAVSPtRkqso
    50  tWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTfMul8b/CZjP2Ob0LdpYrNH6l5hvFE
    51  89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92UE68mOyUVXGweJIVDdxqdMoPvNNU
    52  l86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/LUK43YvJh+rhv4nKuF7iHjVjBd9s
    53  B6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKNe6kUhKJ1luB7S27ZkvB3tSTT3P59
    54  3VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9TEwIDAQABAoIBAEEYiyDP29vCzx/+
    55  dS3LqnI5BjUuJhXUnc6AWX/PCgVAO+8A+gZRgvct7PtZb0sM6P9ZcLrweomlGezI
    56  FrL0/6xQaa8bBr/ve/a8155OgcjFo6fZEw3Dz7ra5fbSiPmu4/b/kvrg+Br1l77J
    57  aun6uUAs1f5B9wW+vbR7tzbT/mxaUeDiBzKpe15GwcvbJtdIVMa2YErtRjc1/5B2
    58  BGVXyvlJv0SIlcIEMsHgnAFOp1ZgQ08aDzvilLq8XVMOahAhP1O2A3X8hKdXPyrx
    59  IVWE9bS9ptTo+eF6eNl+d7htpKGEZHUxinoQpWEBTv+iOoHsVunkEJ3vjLP3lyI/
    60  fY0NQ1ECgYEA3RBXAjgvIys2gfU3keImF8e/TprLge1I2vbWmV2j6rZCg5r/AS0u
    61  pii5CvJ5/T5vfJPNgPBy8B/yRDs+6PJO1GmnlhOkG9JAIPkv0RBZvR0PMBtbp6nT
    62  Y3yo1lwamBVBfY6rc0sLTzosZh2aGoLzrHNMQFMGaauORzBFpY5lU50CgYEAzPHl
    63  u5DI6Xgep1vr8QvCUuEesCOgJg8Yh1UqVoY/SmQh6MYAv1I9bLGwrb3WW/7kqIoD
    64  fj0aQV5buVZI2loMomtU9KY5SFIsPV+JuUpy7/+VE01ZQM5FdY8wiYCQiVZYju9X
    65  Wz5LxMNoz+gT7pwlLCsC4N+R8aoBk404aF1gum8CgYAJ7VTq7Zj4TFV7Soa/T1eE
    66  k9y8a+kdoYk3BASpCHJ29M5R2KEA7YV9wrBklHTz8VzSTFTbKHEQ5W5csAhoL5Fo
    67  qoHzFFi3Qx7MHESQb9qHyolHEMNx6QdsHUn7rlEnaTTyrXh3ifQtD6C0yTmFXUIS
    68  CW9wKApOrnyKJ9nI0HcuZQKBgQCMtoV6e9VGX4AEfpuHvAAnMYQFgeBiYTkBKltQ
    69  XwozhH63uMMomUmtSG87Sz1TmrXadjAhy8gsG6I0pWaN7QgBuFnzQ/HOkwTm+qKw
    70  AsrZt4zeXNwsH7QXHEJCFnCmqw9QzEoZTrNtHJHpNboBuVnYcoueZEJrP8OnUG3r
    71  UjmopwKBgAqB2KYYMUqAOvYcBnEfLDmyZv9BTVNHbR2lKkMYqv5LlvDaBxVfilE0
    72  2riO4p6BaAdvzXjKeRrGNEKoHNBpOSfYCOM16NjL8hIZB1CaV3WbT5oY+jp7Mzd5
    73  7d56RZOE+ERK2uz/7JX9VSsM/LbH9pJibd4e8mikDS9ntciqOH/3
    74  -----END RSA TESTING KEY-----`, "TESTING KEY", "PRIVATE KEY")))
    75  	k, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
    76  
    77  	msg := []byte("hello :)")
    78  
    79  	h := crypto.SHA256.New()
    80  	h.Write(msg)
    81  	digest := h.Sum(nil)
    82  
    83  	sig, err := crypto.SignMessage(k, rand.Reader, msg, &rsa.PSSOptions{Hash: crypto.SHA256})
    84  	if err != nil {
    85  		t.Fatalf("SignMessage failed with Signer: %s", err)
    86  	}
    87  	if err := rsa.VerifyPSS(&k.PublicKey, crypto.SHA256, digest, sig, nil); err != nil {
    88  		t.Errorf("VerifyPSS failed for Signer signature: %s", err)
    89  	}
    90  
    91  	sig, err = crypto.SignMessage(&messageSignerOnly{k}, rand.Reader, msg, &rsa.PSSOptions{Hash: crypto.SHA256})
    92  	if err != nil {
    93  		t.Fatalf("SignMessage failed with MessageSigner: %s", err)
    94  	}
    95  	if err := rsa.VerifyPSS(&k.PublicKey, crypto.SHA256, digest, sig, nil); err != nil {
    96  		t.Errorf("VerifyPSS failed for MessageSigner signature: %s", err)
    97  	}
    98  }
    99  
   100  func TestDisallowedAssemblyInstructions(t *testing.T) {
   101  	// This test enforces the cryptography assembly policy rule that we do not
   102  	// use BYTE or WORD instructions, since these instructions can obscure what
   103  	// the assembly is actually doing. If we do not support specific
   104  	// instructions in the assembler, we should not be using them until we do.
   105  	//
   106  	// Instead of using the output of the 'go tool asm' tool, we take the simple
   107  	// approach and just search the text of .s files for usage of BYTE and WORD.
   108  	// We do this because the assembler itself will sometimes insert WORD
   109  	// instructions for things like function preambles etc.
   110  
   111  	boringSigPath := filepath.Join("internal", "boring", "sig")
   112  
   113  	matcher, err := regexp.Compile(`(^|;)\s(BYTE|WORD)\s`)
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  	if err := filepath.WalkDir(filepath.Join(testenv.GOROOT(t), "src/crypto"), func(path string, d fs.DirEntry, err error) error {
   118  		if err != nil {
   119  			t.Fatal(err)
   120  		}
   121  		if d.IsDir() || !strings.HasSuffix(path, ".s") {
   122  			return nil
   123  		}
   124  		if strings.Contains(path, boringSigPath) {
   125  			return nil
   126  		}
   127  
   128  		f, err := os.ReadFile(path)
   129  		if err != nil {
   130  			t.Fatal(err)
   131  		}
   132  
   133  		i := 1
   134  		for line := range bytes.Lines(f) {
   135  			if matcher.Match(line) {
   136  				t.Errorf("%s:%d assembly contains BYTE or WORD instruction (%q)", path, i, string(line))
   137  			}
   138  			i++
   139  		}
   140  
   141  		return nil
   142  	}); err != nil {
   143  		t.Fatal(err)
   144  	}
   145  }
   146  
   147  func TestRegisterHashLimits(t *testing.T) {
   148  	// maxHash is not exported, so we just use its value. If maxHash ever changes
   149  	// this will need to be updated.
   150  	for _, h := range []crypto.Hash{0, 20} {
   151  		t.Run(fmt.Sprintf("h=%d", h), func(t *testing.T) {
   152  			defer func() {
   153  				if r := recover(); r == nil {
   154  					t.Errorf("RegisterHash did not panic for %v", h)
   155  				}
   156  			}()
   157  			crypto.RegisterHash(h, sha256.New)
   158  		})
   159  	}
   160  }
   161  

View as plain text