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

View as plain text