cast.mx raw

   1  // Copyright 2024 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 ecdsa
   6  
   7  import (
   8  	"bytes"
   9  	"crypto/internal/fips140"
  10  	_ "crypto/internal/fips140/check"
  11  	"crypto/internal/fips140/sha512"
  12  	"errors"
  13  	"sync"
  14  )
  15  
  16  func testPrivateKey() *PrivateKey {
  17  	// https://www.rfc-editor.org/rfc/rfc9500.html#section-2.3
  18  	return &PrivateKey{
  19  		pub: PublicKey{
  20  			curve: p256,
  21  			q: []byte{
  22  				0x04,
  23  				0x42, 0x25, 0x48, 0xF8, 0x8F, 0xB7, 0x82, 0xFF,
  24  				0xB5, 0xEC, 0xA3, 0x74, 0x44, 0x52, 0xC7, 0x2A,
  25  				0x1E, 0x55, 0x8F, 0xBD, 0x6F, 0x73, 0xBE, 0x5E,
  26  				0x48, 0xE9, 0x32, 0x32, 0xCC, 0x45, 0xC5, 0xB1,
  27  				0x6C, 0x4C, 0xD1, 0x0C, 0x4C, 0xB8, 0xD5, 0xB8,
  28  				0xA1, 0x71, 0x39, 0xE9, 0x48, 0x82, 0xC8, 0x99,
  29  				0x25, 0x72, 0x99, 0x34, 0x25, 0xF4, 0x14, 0x19,
  30  				0xAB, 0x7E, 0x90, 0xA4, 0x2A, 0x49, 0x42, 0x72},
  31  		},
  32  		d: []byte{
  33  			0xE6, 0xCB, 0x5B, 0xDD, 0x80, 0xAA, 0x45, 0xAE,
  34  			0x9C, 0x95, 0xE8, 0xC1, 0x54, 0x76, 0x67, 0x9F,
  35  			0xFE, 0xC9, 0x53, 0xC1, 0x68, 0x51, 0xE7, 0x11,
  36  			0xE7, 0x43, 0x93, 0x95, 0x89, 0xC6, 0x4F, 0xC1,
  37  		},
  38  	}
  39  }
  40  
  41  func testHash() []byte {
  42  	return []byte{
  43  		0x17, 0x1b, 0x1f, 0x5e, 0x9f, 0x8f, 0x8c, 0x5c,
  44  		0x42, 0xe8, 0x06, 0x59, 0x7b, 0x54, 0xc7, 0xb4,
  45  		0x49, 0x05, 0xa1, 0xdb, 0x3a, 0x3c, 0x31, 0xd3,
  46  		0xb7, 0x56, 0x45, 0x8c, 0xc2, 0xd6, 0x88, 0x62,
  47  		0x9e, 0xd6, 0x7b, 0x9b, 0x25, 0x68, 0xd6, 0xc6,
  48  		0x18, 0x94, 0x1e, 0xfe, 0xe3, 0x33, 0x78, 0xa6,
  49  		0xe1, 0xce, 0x13, 0x88, 0x81, 0x26, 0x02, 0x52,
  50  		0xdf, 0xc2, 0x0a, 0xf2, 0x67, 0x49, 0x0a, 0x20,
  51  	}
  52  }
  53  
  54  func fipsPCT[P Point[P]](c *Curve[P], k *PrivateKey) {
  55  	fips140.PCT("ECDSA PCT", func() error {
  56  		hash := testHash()
  57  		drbg := newDRBG(sha512.New, k.d, bits2octets(P256(), hash), nil)
  58  		sig, err := sign(c, k, drbg, hash)
  59  		if err != nil {
  60  			return err
  61  		}
  62  		return Verify(c, &k.pub, hash, sig)
  63  	})
  64  }
  65  
  66  var fipsSelfTest = sync.OnceFunc(func() {
  67  	fips140.CAST("ECDSA P-256 SHA2-512 sign and verify", func() error {
  68  		k := testPrivateKey()
  69  		Z := []byte{
  70  			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  71  			0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
  72  		}
  73  		persStr := []byte{
  74  			0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
  75  			0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
  76  		}
  77  		hash := testHash()
  78  		want := &Signature{
  79  			R: []byte{
  80  				0x33, 0x64, 0x96, 0xff, 0x8a, 0xfe, 0xaa, 0x0b,
  81  				0x2c, 0x4a, 0x1a, 0x97, 0x77, 0xcc, 0x84, 0xa5,
  82  				0x7e, 0x88, 0x1f, 0x16, 0x2d, 0xe0, 0x29, 0xf7,
  83  				0x62, 0xc2, 0x34, 0x18, 0x10, 0x9c, 0x69, 0x8a,
  84  			}, S: []byte{
  85  				0x97, 0x53, 0x2e, 0x13, 0x6e, 0xd0, 0x9b, 0x30,
  86  				0x8a, 0xdf, 0x4f, 0xe0, 0x54, 0x82, 0x14, 0x83,
  87  				0x5e, 0x93, 0xc7, 0x79, 0x4b, 0x18, 0xa3, 0xf1,
  88  				0x8a, 0x60, 0xae, 0x52, 0x31, 0xe4, 0x2e, 0x4e,
  89  			},
  90  		}
  91  		drbg := newDRBG(sha512.New, Z, nil, plainPersonalizationString(persStr))
  92  		got, err := sign(P256(), k, drbg, hash)
  93  		if err != nil {
  94  			return err
  95  		}
  96  		if err := verify(P256(), &k.pub, hash, got); err != nil {
  97  			return err
  98  		}
  99  		if !bytes.Equal(got.R, want.R) || !bytes.Equal(got.S, want.S) {
 100  			return errors.New("unexpected result")
 101  		}
 102  		return nil
 103  	})
 104  })
 105  
 106  var fipsSelfTestDeterministic = sync.OnceFunc(func() {
 107  	fips140.CAST("DetECDSA P-256 SHA2-512 sign", func() error {
 108  		k := testPrivateKey()
 109  		hash := testHash()
 110  		want := &Signature{
 111  			R: []byte{
 112  				0x9f, 0xc3, 0x83, 0x32, 0x6e, 0xd9, 0x4f, 0x8e,
 113  				0x24, 0xa0, 0x19, 0xef, 0x1d, 0x3a, 0xc3, 0x55,
 114  				0xdd, 0x4b, 0x98, 0xae, 0x78, 0xa7, 0xaf, 0xd3,
 115  				0xfd, 0xf3, 0x22, 0x1c, 0x8b, 0xd6, 0x11, 0x7b,
 116  			}, S: []byte{
 117  				0xd6, 0x52, 0x87, 0x41, 0x71, 0xbd, 0x66, 0xd1,
 118  				0xaf, 0x6c, 0x61, 0xdd, 0xd8, 0xa7, 0xbb, 0xd2,
 119  				0xf7, 0xd5, 0x47, 0x70, 0xe9, 0xe4, 0xac, 0x0a,
 120  				0xb9, 0xfa, 0x0f, 0xbd, 0x3b, 0x9b, 0xc2, 0xfe,
 121  			},
 122  		}
 123  		drbg := newDRBG(sha512.New, k.d, bits2octets(P256(), hash), nil)
 124  		got, err := sign(P256(), k, drbg, hash)
 125  		if err != nil {
 126  			return err
 127  		}
 128  		if err := verify(P256(), &k.pub, hash, got); err != nil {
 129  			return err
 130  		}
 131  		if !bytes.Equal(got.R, want.R) || !bytes.Equal(got.S, want.S) {
 132  			return errors.New("unexpected result")
 133  		}
 134  		return nil
 135  	})
 136  })
 137