return nil, err
}
k := &PublicKeyECDSA{key}
+ // Note: Because of the finalizer, any time k.key is passed to cgo,
+ // that call must be followed by a call to runtime.KeepAlive(k),
+ // to make sure k is not collected (and finalized) before the cgo
+ // call returns.
runtime.SetFinalizer(k, (*PublicKeyECDSA).finalize)
return k, nil
}
return nil, fail("EC_KEY_set_private_key")
}
k := &PrivateKeyECDSA{key}
+ // Note: Because of the finalizer, any time k.key is passed to cgo,
+ // that call must be followed by a call to runtime.KeepAlive(k),
+ // to make sure k is not collected (and finalized) before the cgo
+ // call returns.
runtime.SetFinalizer(k, (*PrivateKeyECDSA).finalize)
return k, nil
}
if C._goboringcrypto_ECDSA_sign(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), &sigLen, priv.key) == 0 {
return nil, fail("ECDSA_sign")
}
+ runtime.KeepAlive(priv)
return sig[:sigLen], nil
}
if err != nil {
return false
}
- return 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
+ 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
+ runtime.KeepAlive(pub)
+ return ok
}
func GenerateKeyECDSA(curve string) (X, Y, D *big.Int, err error) {
return nil, fail("BN_bin2bn")
}
k := &PublicKeyRSA{key: key}
+ // Note: Because of the finalizer, any time k.key is passed to cgo,
+ // that call must be followed by a call to runtime.KeepAlive(k),
+ // to make sure k is not collected (and finalized) before the cgo
+ // call returns.
runtime.SetFinalizer(k, (*PublicKeyRSA).finalize)
return k, nil
}
return nil, fail("BN_bin2bn")
}
k := &PrivateKeyRSA{key: key}
+ // Note: Because of the finalizer, any time k.key is passed to cgo,
+ // that call must be followed by a call to runtime.KeepAlive(k),
+ // to make sure k is not collected (and finalized) before the cgo
+ // call returns.
runtime.SetFinalizer(k, (*PrivateKeyRSA).finalize)
return k, nil
}
return pkey, ctx, nil
}
-func cryptRSA(key *C.GO_RSA,
+func cryptRSA(gokey interface{}, key *C.GO_RSA,
padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash,
init func(*C.GO_EVP_PKEY_CTX) C.int,
crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.size_t, *C.uint8_t, C.size_t) C.int,
if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) == 0 {
return nil, fail("EVP_PKEY_decrypt/encrypt")
}
+ runtime.KeepAlive(gokey) // keep key from being freed before now
return out[:outLen], nil
}
func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) {
- return cryptRSA(priv.key, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, decryptInit, decrypt, ciphertext)
+ return cryptRSA(priv, priv.key, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, decryptInit, decrypt, ciphertext)
}
func EncryptRSAOAEP(h hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) {
- return cryptRSA(pub.key, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, encryptInit, encrypt, msg)
+ return cryptRSA(pub, pub.key, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, encryptInit, encrypt, msg)
}
func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
- return cryptRSA(priv.key, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
+ return cryptRSA(priv, priv.key, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
}
func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
- return cryptRSA(pub.key, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
+ return cryptRSA(pub, pub.key, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
}
func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
- return cryptRSA(priv.key, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
+ return cryptRSA(priv, priv.key, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
}
func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
- return cryptRSA(pub.key, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
+ return cryptRSA(pub, pub.key, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
}
// These dumb wrappers work around the fact that cgo functions cannot be used as values directly.
if C._goboringcrypto_RSA_sign_pss_mgf1(priv.key, &outLen, base(out), C.size_t(len(out)), base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen)) == 0 {
return nil, fail("RSA_sign_pss_mgf1")
}
+ runtime.KeepAlive(priv)
return out[:outLen], nil
}
if C._goboringcrypto_RSA_verify_pss_mgf1(pub.key, base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen), base(sig), C.size_t(len(sig))) == 0 {
return fail("RSA_verify_pss_mgf1")
}
+ runtime.KeepAlive(pub)
return nil
}
if C._goboringcrypto_RSA_sign_raw(priv.key, &outLen, base(out), C.size_t(len(out)), base(hashed), C.size_t(len(hashed)), C.GO_RSA_PKCS1_PADDING) == 0 {
return nil, fail("RSA_sign_raw")
}
+ runtime.KeepAlive(priv)
return out[:outLen], nil
}
if C._goboringcrypto_RSA_sign(nid, base(hashed), C.uint(len(hashed)), base(out), &outLen, priv.key) == 0 {
return nil, fail("RSA_sign")
}
+ runtime.KeepAlive(priv)
return out[:outLen], nil
}
if subtle.ConstantTimeCompare(hashed, out[:outLen]) != 1 {
return fail("RSA_verify")
}
+ runtime.KeepAlive(pub)
return nil
}
md := cryptoHashToMD(h)
if C._goboringcrypto_RSA_verify(nid, base(hashed), C.size_t(len(hashed)), base(sig), C.size_t(len(sig)), pub.key) == 0 {
return fail("RSA_verify")
}
+ runtime.KeepAlive(pub)
return nil
}