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