Source file src/crypto/ecdsa/boring.go

     1  // Copyright 2017 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  //go:build boringcrypto
     6  
     7  package ecdsa
     8  
     9  import (
    10  	"crypto/internal/boring"
    11  	"crypto/internal/boring/bbig"
    12  	"crypto/internal/boring/bcache"
    13  	"math/big"
    14  )
    15  
    16  // Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
    17  //
    18  // The first operation on a PublicKey or PrivateKey makes a parallel
    19  // BoringCrypto key and saves it in pubCache or privCache.
    20  //
    21  // We could just assume that once used in a Sign or Verify operation,
    22  // a particular key is never again modified, but that has not been a
    23  // stated assumption before. Just in case there is any existing code that
    24  // does modify the key between operations, we save the original values
    25  // alongside the cached BoringCrypto key and check that the real key
    26  // still matches before using the cached key. The theory is that the real
    27  // operations are significantly more expensive than the comparison.
    28  
    29  var pubCache bcache.Cache[PublicKey, boringPub]
    30  var privCache bcache.Cache[PrivateKey, boringPriv]
    31  
    32  func init() {
    33  	pubCache.Register()
    34  	privCache.Register()
    35  }
    36  
    37  type boringPub struct {
    38  	key  *boring.PublicKeyECDSA
    39  	orig PublicKey
    40  }
    41  
    42  func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) {
    43  	b := pubCache.Get(pub)
    44  	if b != nil && publicKeyEqual(&b.orig, pub) {
    45  		return b.key, nil
    46  	}
    47  
    48  	b = new(boringPub)
    49  	b.orig = copyPublicKey(pub)
    50  	key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y))
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	b.key = key
    55  	pubCache.Put(pub, b)
    56  	return key, nil
    57  }
    58  
    59  type boringPriv struct {
    60  	key  *boring.PrivateKeyECDSA
    61  	orig PrivateKey
    62  }
    63  
    64  func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) {
    65  	b := privCache.Get(priv)
    66  	if b != nil && privateKeyEqual(&b.orig, priv) {
    67  		return b.key, nil
    68  	}
    69  
    70  	b = new(boringPriv)
    71  	b.orig = copyPrivateKey(priv)
    72  	key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y), bbig.Enc(b.orig.D))
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	b.key = key
    77  	privCache.Put(priv, b)
    78  	return key, nil
    79  }
    80  
    81  func publicKeyEqual(k1, k2 *PublicKey) bool {
    82  	return k1.X != nil &&
    83  		k1.Curve.Params() == k2.Curve.Params() &&
    84  		k1.X.Cmp(k2.X) == 0 &&
    85  		k1.Y.Cmp(k2.Y) == 0
    86  }
    87  
    88  func privateKeyEqual(k1, k2 *PrivateKey) bool {
    89  	return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) &&
    90  		k1.D.Cmp(k2.D) == 0
    91  }
    92  
    93  func copyPublicKey(k *PublicKey) PublicKey {
    94  	return PublicKey{
    95  		Curve: k.Curve,
    96  		X:     new(big.Int).Set(k.X),
    97  		Y:     new(big.Int).Set(k.Y),
    98  	}
    99  }
   100  
   101  func copyPrivateKey(k *PrivateKey) PrivateKey {
   102  	return PrivateKey{
   103  		PublicKey: copyPublicKey(&k.PublicKey),
   104  		D:         new(big.Int).Set(k.D),
   105  	}
   106  }
   107  

View as plain text