github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/crypto/internal/boring/ecdsa.go (about) 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 && linux && (amd64 || arm64) && !android && !cmd_go_bootstrap && !msan 6 7 package boring 8 9 // #include "goboringcrypto.h" 10 import "C" 11 import ( 12 "errors" 13 "runtime" 14 "unsafe" 15 ) 16 17 type ecdsaSignature struct { 18 R, S BigInt 19 } 20 21 type PrivateKeyECDSA struct { 22 key *C.GO_EC_KEY 23 } 24 25 func (k *PrivateKeyECDSA) finalize() { 26 C._goboringcrypto_EC_KEY_free(k.key) 27 } 28 29 type PublicKeyECDSA struct { 30 key *C.GO_EC_KEY 31 } 32 33 func (k *PublicKeyECDSA) finalize() { 34 C._goboringcrypto_EC_KEY_free(k.key) 35 } 36 37 var errUnknownCurve = errors.New("boringcrypto: unknown elliptic curve") 38 39 func curveNID(curve string) (C.int, error) { 40 switch curve { 41 case "P-224": 42 return C.GO_NID_secp224r1, nil 43 case "P-256": 44 return C.GO_NID_X9_62_prime256v1, nil 45 case "P-384": 46 return C.GO_NID_secp384r1, nil 47 case "P-521": 48 return C.GO_NID_secp521r1, nil 49 } 50 return 0, errUnknownCurve 51 } 52 53 func NewPublicKeyECDSA(curve string, X, Y BigInt) (*PublicKeyECDSA, error) { 54 key, err := newECKey(curve, X, Y) 55 if err != nil { 56 return nil, err 57 } 58 k := &PublicKeyECDSA{key} 59 // Note: Because of the finalizer, any time k.key is passed to cgo, 60 // that call must be followed by a call to runtime.KeepAlive(k), 61 // to make sure k is not collected (and finalized) before the cgo 62 // call returns. 63 runtime.SetFinalizer(k, (*PublicKeyECDSA).finalize) 64 return k, nil 65 } 66 67 func newECKey(curve string, X, Y BigInt) (*C.GO_EC_KEY, error) { 68 nid, err := curveNID(curve) 69 if err != nil { 70 return nil, err 71 } 72 key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid) 73 if key == nil { 74 return nil, fail("EC_KEY_new_by_curve_name") 75 } 76 group := C._goboringcrypto_EC_KEY_get0_group(key) 77 pt := C._goboringcrypto_EC_POINT_new(group) 78 if pt == nil { 79 C._goboringcrypto_EC_KEY_free(key) 80 return nil, fail("EC_POINT_new") 81 } 82 bx := bigToBN(X) 83 by := bigToBN(Y) 84 ok := bx != nil && by != nil && C._goboringcrypto_EC_POINT_set_affine_coordinates_GFp(group, pt, bx, by, nil) != 0 && 85 C._goboringcrypto_EC_KEY_set_public_key(key, pt) != 0 86 if bx != nil { 87 C._goboringcrypto_BN_free(bx) 88 } 89 if by != nil { 90 C._goboringcrypto_BN_free(by) 91 } 92 C._goboringcrypto_EC_POINT_free(pt) 93 if !ok { 94 C._goboringcrypto_EC_KEY_free(key) 95 return nil, fail("EC_POINT_set_affine_coordinates_GFp") 96 } 97 return key, nil 98 } 99 100 func NewPrivateKeyECDSA(curve string, X, Y BigInt, D BigInt) (*PrivateKeyECDSA, error) { 101 key, err := newECKey(curve, X, Y) 102 if err != nil { 103 return nil, err 104 } 105 bd := bigToBN(D) 106 ok := bd != nil && C._goboringcrypto_EC_KEY_set_private_key(key, bd) != 0 107 if bd != nil { 108 C._goboringcrypto_BN_free(bd) 109 } 110 if !ok { 111 C._goboringcrypto_EC_KEY_free(key) 112 return nil, fail("EC_KEY_set_private_key") 113 } 114 k := &PrivateKeyECDSA{key} 115 // Note: Because of the finalizer, any time k.key is passed to cgo, 116 // that call must be followed by a call to runtime.KeepAlive(k), 117 // to make sure k is not collected (and finalized) before the cgo 118 // call returns. 119 runtime.SetFinalizer(k, (*PrivateKeyECDSA).finalize) 120 return k, nil 121 } 122 123 func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) { 124 size := C._goboringcrypto_ECDSA_size(priv.key) 125 sig := make([]byte, size) 126 var sigLen C.uint 127 if C._goboringcrypto_ECDSA_sign(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), &sigLen, priv.key) == 0 { 128 return nil, fail("ECDSA_sign") 129 } 130 runtime.KeepAlive(priv) 131 return sig[:sigLen], nil 132 } 133 134 func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, sig []byte) bool { 135 ok := C._goboringcrypto_ECDSA_verify(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), C.size_t(len(sig)), pub.key) != 0 136 runtime.KeepAlive(pub) 137 return ok 138 } 139 140 func GenerateKeyECDSA(curve string) (X, Y, D BigInt, err error) { 141 nid, err := curveNID(curve) 142 if err != nil { 143 return nil, nil, nil, err 144 } 145 key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid) 146 if key == nil { 147 return nil, nil, nil, fail("EC_KEY_new_by_curve_name") 148 } 149 defer C._goboringcrypto_EC_KEY_free(key) 150 if C._goboringcrypto_EC_KEY_generate_key_fips(key) == 0 { 151 return nil, nil, nil, fail("EC_KEY_generate_key_fips") 152 } 153 group := C._goboringcrypto_EC_KEY_get0_group(key) 154 pt := C._goboringcrypto_EC_KEY_get0_public_key(key) 155 bd := C._goboringcrypto_EC_KEY_get0_private_key(key) 156 if pt == nil || bd == nil { 157 return nil, nil, nil, fail("EC_KEY_get0_private_key") 158 } 159 bx := C._goboringcrypto_BN_new() 160 if bx == nil { 161 return nil, nil, nil, fail("BN_new") 162 } 163 defer C._goboringcrypto_BN_free(bx) 164 by := C._goboringcrypto_BN_new() 165 if by == nil { 166 return nil, nil, nil, fail("BN_new") 167 } 168 defer C._goboringcrypto_BN_free(by) 169 if C._goboringcrypto_EC_POINT_get_affine_coordinates_GFp(group, pt, bx, by, nil) == 0 { 170 return nil, nil, nil, fail("EC_POINT_get_affine_coordinates_GFp") 171 } 172 return bnToBig(bx), bnToBig(by), bnToBig(bd), nil 173 }