// SetEllipticCurve sets the elliptic curve used by the SSL context to // enable an ECDH cipher suite to be selected during the handshake. func (c *Ctx) SetEllipticCurve(curve EllipticCurve) error { runtime.LockOSThread() defer runtime.UnlockOSThread() k := C.EC_KEY_new_by_curve_name(C.int(curve)) if k == nil { return errors.New("Unknown curve") } defer C.EC_KEY_free(k) if int(C.SSL_CTX_set_tmp_ecdh_not_a_macro(c.ctx, k)) != 1 { return errorFromErrorQueue() } return nil }
// GenerateKey returns a public/private key pair. The private key is // generated using the given reader, which must return random data. // TODO(runcom): add support for Go stdlib `elliptic.Curve`, for now unsupported func GenerateKey(curve elliptic.Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) { // rand isn't used with openssl... // for go stdlib compatibility //c, _ := curve.(*elliptic.CurveParams) // to use this pkg c, ok := curve.(CurveParams) if !ok { return nil, nil, nil, errors.New("provided curve is unsupported") } k := C.EC_KEY_new() if k == nil { return nil, nil, nil, errors.New("can't create key") } defer C.EC_KEY_free(k) if C.EC_KEY_set_group(k, c.curve) != 1 { return nil, nil, nil, errors.New("can't set ec_group on key") } if C.EC_KEY_generate_key(k) != 1 { return nil, nil, nil, errors.New("can't generate key") } blen := C.i2d_ECPrivateKey(k, nil) if blen == 0 { return nil, nil, nil, errors.New("can't get private key") } buf := make([]C.uchar, int(blen)) pkey := (*C.uchar)(&buf[0]) if C.i2d_ECPrivateKey(k, &pkey) == 0 { return nil, nil, nil, errors.New("can't get private key") } point := C.EC_KEY_get0_public_key(k) if point == nil { return nil, nil, nil, errors.New("can't get public key") } defer C.EC_POINT_free(point) rx := C.BN_new() if rx == nil { return nil, nil, nil, errors.New("error creating big num") } defer C.BN_free(rx) ry := C.BN_new() if ry == nil { return nil, nil, nil, errors.New("errors creating big num") } defer C.BN_free(ry) if C.EC_POINT_get_affine_coordinates_GFp(c.curve, point, rx, ry, nil) != 1 { return nil, nil, nil, errors.New("can't get public key") } x, _ = new(big.Int).SetString(C.GoString(C.BN_bn2hex(rx)), 16) y, _ = new(big.Int).SetString(C.GoString(C.BN_bn2hex(ry)), 16) priv = C.GoBytes(unsafe.Pointer(pkey), C.int(blen)) return priv, x, y, nil }