diff --git a/ctx.go b/ctx.go index ca057a4..7ad54a0 100644 --- a/ctx.go +++ b/ctx.go @@ -142,7 +142,7 @@ func NewCtxFromFiles(cert_file string, key_file string) (*Ctx, error) { return nil, err } - cert, err := LoadCertificate(cert_bytes) + cert, err := LoadCertificateFromPEM(cert_bytes) if err != nil { return nil, err } @@ -157,7 +157,7 @@ func NewCtxFromFiles(cert_file string, key_file string) (*Ctx, error) { return nil, err } - key, err := LoadPrivateKey(key_bytes) + key, err := LoadPrivateKeyFromPEM(key_bytes) if err != nil { return nil, err } diff --git a/oracle_stubs.go b/oracle_stubs.go index 0285e89..8132803 100644 --- a/oracle_stubs.go +++ b/oracle_stubs.go @@ -138,11 +138,11 @@ type PrivateKey interface { MarshalPKCS1PrivateKeyDER() (der_block []byte, err error) } -func LoadPrivateKey(pem_block []byte) (PrivateKey, error) +func LoadPrivateKeyFromPEM(pem_block []byte) (PrivateKey, error) type Certificate struct{} -func LoadCertificate(pem_block []byte) (*Certificate, error) +func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error) func (c *Certificate) MarshalPEM() (pem_block []byte, err error) diff --git a/pem.go b/pem.go index fe2d502..6cf3763 100644 --- a/pem.go +++ b/pem.go @@ -194,8 +194,8 @@ func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte, return ioutil.ReadAll(asAnyBio(bio)) } -// LoadPrivateKey loads a private key from a PEM-encoded block. -func LoadPrivateKey(pem_block []byte) (PrivateKey, error) { +// LoadPrivateKeyFromPEM loads a private key from a PEM-encoded block. +func LoadPrivateKeyFromPEM(pem_block []byte) (PrivateKey, error) { if len(pem_block) == 0 { return nil, errors.New("empty pem block") } @@ -229,8 +229,8 @@ func LoadPrivateKey(pem_block []byte) (PrivateKey, error) { return p, nil } -// LoadPublicKey loads a public key from a PEM-encoded block. -func LoadPublicKey(pem_block []byte) (PublicKey, error) { +// LoadPublicKeyFromPEM loads a public key from a PEM-encoded block. +func LoadPublicKeyFromPEM(pem_block []byte) (PublicKey, error) { if len(pem_block) == 0 { return nil, errors.New("empty pem block") } @@ -241,7 +241,42 @@ func LoadPublicKey(pem_block []byte) (PublicKey, error) { } defer C.BIO_free(bio) - rsakey := C.PEM_read_bio_RSAPublicKey(bio, nil, nil, nil) + rsakey := C.PEM_read_bio_RSA_PUBKEY(bio, nil, nil, nil) + if rsakey == nil { + return nil, errors.New("failed reading rsa key") + } + defer C.RSA_free(rsakey) + + // convert to PKEY + key := C.EVP_PKEY_new() + if key == nil { + return nil, errors.New("failed converting to evp_pkey") + } + if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 { + C.EVP_PKEY_free(key) + return nil, errors.New("failed converting to evp_pkey") + } + + p := &pKey{key: key} + runtime.SetFinalizer(p, func(p *pKey) { + C.EVP_PKEY_free(p.key) + }) + return p, nil +} + +// LoadPublicKeyFromDER loads a public key from a DER-encoded block. +func LoadPublicKeyFromDER(der_block []byte) (PublicKey, error) { + if len(der_block) == 0 { + return nil, errors.New("empty der block") + } + bio := C.BIO_new_mem_buf(unsafe.Pointer(&der_block[0]), + C.int(len(der_block))) + if bio == nil { + return nil, errors.New("failed creating bio") + } + defer C.BIO_free(bio) + + rsakey := C.d2i_RSA_PUBKEY_bio(bio, nil) if rsakey == nil { return nil, errors.New("failed reading rsa key") } @@ -269,8 +304,8 @@ type Certificate struct { ref interface{} } -// LoadCertificate loads an X509 certificate from a PEM-encoded block. -func LoadCertificate(pem_block []byte) (*Certificate, error) { +// LoadCertificateFromPEM loads an X509 certificate from a PEM-encoded block. +func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error) { if len(pem_block) == 0 { return nil, errors.New("empty pem block") } diff --git a/pem_test.go b/pem_test.go index 513a672..e1c1d47 100644 --- a/pem_test.go +++ b/pem_test.go @@ -8,16 +8,17 @@ import ( "crypto/tls" "crypto/x509" "encoding/hex" + pem_pkg "encoding/pem" "io/ioutil" "testing" ) func TestMarshal(t *testing.T) { - key, err := LoadPrivateKey(keyBytes) + key, err := LoadPrivateKeyFromPEM(keyBytes) if err != nil { t.Fatal(err) } - cert, err := LoadCertificate(certBytes) + cert, err := LoadCertificateFromPEM(certBytes) if err != nil { t.Fatal(err) } @@ -57,7 +58,8 @@ func TestMarshal(t *testing.T) { } tls_der := x509.MarshalPKCS1PrivateKey(tls_key) if !bytes.Equal(der, tls_der) { - t.Fatal("invalid private key der bytes: %s\n v.s. %s\n", hex.Dump(der), hex.Dump(tls_der)) + t.Fatal("invalid private key der bytes: %s\n v.s. %s\n", + hex.Dump(der), hex.Dump(tls_der)) } der, err = key.MarshalPKIXPublicKeyDER() @@ -73,4 +75,48 @@ func TestMarshal(t *testing.T) { ioutil.WriteFile("hardcoded", []byte(hex.Dump(tls_der)), 0644) t.Fatal("invalid public key der bytes") } + + pem, err = key.MarshalPKIXPublicKeyPEM() + if err != nil { + t.Fatal(err) + } + tls_pem := pem_pkg.EncodeToMemory(&pem_pkg.Block{ + Type: "PUBLIC KEY", Bytes: tls_der}) + if !bytes.Equal(pem, tls_pem) { + ioutil.WriteFile("generated", pem, 0644) + ioutil.WriteFile("hardcoded", tls_pem, 0644) + t.Fatal("invalid public key pem bytes") + } + + loaded_pubkey_from_pem, err := LoadPublicKeyFromPEM(pem) + if err != nil { + t.Fatal(err) + } + + loaded_pubkey_from_der, err := LoadPublicKeyFromDER(der) + if err != nil { + t.Fatal(err) + } + + new_der_from_pem, err := loaded_pubkey_from_pem.MarshalPKIXPublicKeyDER() + if err != nil { + t.Fatal(err) + } + + new_der_from_der, err := loaded_pubkey_from_der.MarshalPKIXPublicKeyDER() + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(new_der_from_der, tls_der) { + ioutil.WriteFile("generated", []byte(hex.Dump(new_der_from_der)), 0644) + ioutil.WriteFile("hardcoded", []byte(hex.Dump(tls_der)), 0644) + t.Fatal("invalid public key der bytes") + } + + if !bytes.Equal(new_der_from_pem, tls_der) { + ioutil.WriteFile("generated", []byte(hex.Dump(new_der_from_pem)), 0644) + ioutil.WriteFile("hardcoded", []byte(hex.Dump(tls_der)), 0644) + t.Fatal("invalid public key der bytes") + } } diff --git a/ssl_test.go b/ssl_test.go index 3db15cc..0bdc8fe 100644 --- a/ssl_test.go +++ b/ssl_test.go @@ -313,7 +313,7 @@ func OpenSSLConstructor(t testing.TB, server_conn, client_conn net.Conn) ( t.Fatal(err) } ctx.SetVerify(VerifyNone, passThruVerify(t)) - key, err := LoadPrivateKey(keyBytes) + key, err := LoadPrivateKeyFromPEM(keyBytes) if err != nil { t.Fatal(err) } @@ -321,7 +321,7 @@ func OpenSSLConstructor(t testing.TB, server_conn, client_conn net.Conn) ( if err != nil { t.Fatal(err) } - cert, err := LoadCertificate(certBytes) + cert, err := LoadCertificateFromPEM(certBytes) if err != nil { t.Fatal(err) } @@ -592,7 +592,7 @@ func TestOpenSSLLotsOfConns(t *testing.T) { if err != nil { t.Fatal(err) } - key, err := LoadPrivateKey(keyBytes) + key, err := LoadPrivateKeyFromPEM(keyBytes) if err != nil { t.Fatal(err) } @@ -600,7 +600,7 @@ func TestOpenSSLLotsOfConns(t *testing.T) { if err != nil { t.Fatal(err) } - cert, err := LoadCertificate(certBytes) + cert, err := LoadCertificateFromPEM(certBytes) if err != nil { t.Fatal(err) }