| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- // Copyright (C) 2017. See AUTHORS.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package openssl
- // #include "shim.h"
- import "C"
- import (
- "errors"
- "io/ioutil"
- "runtime"
- "unsafe"
- )
- type Method *C.EVP_MD
- var (
- SHA1_Method Method = C.X_EVP_sha1()
- SHA256_Method Method = C.X_EVP_sha256()
- SHA512_Method Method = C.X_EVP_sha512()
- )
- type PublicKey interface {
- // Verifies the data signature using PKCS1.15
- VerifyPKCS1v15(method Method, data, sig []byte) error
- // MarshalPKIXPublicKeyPEM converts the public key to PEM-encoded PKIX
- // format
- MarshalPKIXPublicKeyPEM() (pem_block []byte, err error)
- // MarshalPKIXPublicKeyDER converts the public key to DER-encoded PKIX
- // format
- MarshalPKIXPublicKeyDER() (der_block []byte, err error)
- evpPKey() *C.EVP_PKEY
- }
- type PrivateKey interface {
- PublicKey
- // Signs the data using PKCS1.15
- SignPKCS1v15(Method, []byte) ([]byte, error)
- // MarshalPKCS1PrivateKeyPEM converts the private key to PEM-encoded PKCS1
- // format
- MarshalPKCS1PrivateKeyPEM() (pem_block []byte, err error)
- // MarshalPKCS1PrivateKeyDER converts the private key to DER-encoded PKCS1
- // format
- MarshalPKCS1PrivateKeyDER() (der_block []byte, err error)
- }
- type pKey struct {
- key *C.EVP_PKEY
- }
- func (key *pKey) evpPKey() *C.EVP_PKEY { return key.key }
- func (key *pKey) SignPKCS1v15(method Method, data []byte) ([]byte, error) {
- ctx := C.X_EVP_MD_CTX_new()
- defer C.X_EVP_MD_CTX_free(ctx)
- if 1 != C.X_EVP_SignInit(ctx, method) {
- return nil, errors.New("signpkcs1v15: failed to init signature")
- }
- if len(data) > 0 {
- if 1 != C.X_EVP_SignUpdate(
- ctx, unsafe.Pointer(&data[0]), C.uint(len(data))) {
- return nil, errors.New("signpkcs1v15: failed to update signature")
- }
- }
- sig := make([]byte, C.X_EVP_PKEY_size(key.key))
- var sigblen C.uint
- if 1 != C.X_EVP_SignFinal(ctx,
- ((*C.uchar)(unsafe.Pointer(&sig[0]))), &sigblen, key.key) {
- return nil, errors.New("signpkcs1v15: failed to finalize signature")
- }
- return sig[:sigblen], nil
- }
- func (key *pKey) VerifyPKCS1v15(method Method, data, sig []byte) error {
- ctx := C.X_EVP_MD_CTX_new()
- defer C.X_EVP_MD_CTX_free(ctx)
- if 1 != C.X_EVP_VerifyInit(ctx, method) {
- return errors.New("verifypkcs1v15: failed to init verify")
- }
- if len(data) > 0 {
- if 1 != C.X_EVP_VerifyUpdate(
- ctx, unsafe.Pointer(&data[0]), C.uint(len(data))) {
- return errors.New("verifypkcs1v15: failed to update verify")
- }
- }
- if 1 != C.X_EVP_VerifyFinal(ctx,
- ((*C.uchar)(unsafe.Pointer(&sig[0]))), C.uint(len(sig)), key.key) {
- return errors.New("verifypkcs1v15: failed to finalize verify")
- }
- return nil
- }
- func (key *pKey) MarshalPKCS1PrivateKeyPEM() (pem_block []byte,
- err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- rsa := (*C.RSA)(C.X_EVP_PKEY_get1_RSA(key.key))
- if rsa == nil {
- return nil, errors.New("failed getting rsa key")
- }
- defer C.RSA_free(rsa)
- if int(C.PEM_write_bio_RSAPrivateKey(bio, rsa, nil, nil, C.int(0), nil,
- nil)) != 1 {
- return nil, errors.New("failed dumping private key")
- }
- return ioutil.ReadAll(asAnyBio(bio))
- }
- func (key *pKey) MarshalPKCS1PrivateKeyDER() (der_block []byte,
- err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- rsa := (*C.RSA)(C.X_EVP_PKEY_get1_RSA(key.key))
- if rsa == nil {
- return nil, errors.New("failed getting rsa key")
- }
- defer C.RSA_free(rsa)
- if int(C.i2d_RSAPrivateKey_bio(bio, rsa)) != 1 {
- return nil, errors.New("failed dumping private key der")
- }
- return ioutil.ReadAll(asAnyBio(bio))
- }
- func (key *pKey) MarshalPKIXPublicKeyPEM() (pem_block []byte,
- err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- rsa := (*C.RSA)(C.X_EVP_PKEY_get1_RSA(key.key))
- if rsa == nil {
- return nil, errors.New("failed getting rsa key")
- }
- defer C.RSA_free(rsa)
- if int(C.PEM_write_bio_RSA_PUBKEY(bio, rsa)) != 1 {
- return nil, errors.New("failed dumping public key pem")
- }
- return ioutil.ReadAll(asAnyBio(bio))
- }
- func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte,
- err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- rsa := (*C.RSA)(C.X_EVP_PKEY_get1_RSA(key.key))
- if rsa == nil {
- return nil, errors.New("failed getting rsa key")
- }
- defer C.RSA_free(rsa)
- if int(C.i2d_RSA_PUBKEY_bio(bio, rsa)) != 1 {
- return nil, errors.New("failed dumping public key der")
- }
- return ioutil.ReadAll(asAnyBio(bio))
- }
- // 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")
- }
- bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
- C.int(len(pem_block)))
- if bio == nil {
- return nil, errors.New("failed creating bio")
- }
- defer C.BIO_free(bio)
- rsakey := C.PEM_read_bio_RSAPrivateKey(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.X_EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed converting to evp_pkey")
- }
- if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
- C.X_EVP_PKEY_free(key)
- return nil, errors.New("failed converting to evp_pkey")
- }
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.X_EVP_PKEY_free(p.key)
- })
- return p, nil
- }
- // LoadPrivateKeyFromPEMWithPassword loads a private key from a PEM-encoded block.
- func LoadPrivateKeyFromPEMWithPassword(pem_block []byte, password string) (
- PrivateKey, error) {
- if len(pem_block) == 0 {
- return nil, errors.New("empty pem block")
- }
- bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
- C.int(len(pem_block)))
- if bio == nil {
- return nil, errors.New("failed creating bio")
- }
- defer C.BIO_free(bio)
- cs := C.CString(password)
- defer C.free(unsafe.Pointer(cs))
- rsakey := C.PEM_read_bio_RSAPrivateKey(bio, nil, nil, unsafe.Pointer(cs))
- if rsakey == nil {
- return nil, errors.New("failed reading rsa key")
- }
- defer C.RSA_free(rsakey)
- // convert to PKEY
- key := C.X_EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed converting to evp_pkey")
- }
- if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
- C.X_EVP_PKEY_free(key)
- return nil, errors.New("failed converting to evp_pkey")
- }
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.X_EVP_PKEY_free(p.key)
- })
- return p, nil
- }
- // LoadPrivateKeyFromDER loads a private key from a DER-encoded block.
- func LoadPrivateKeyFromDER(der_block []byte) (PrivateKey, 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_RSAPrivateKey_bio(bio, nil)
- if rsakey == nil {
- return nil, errors.New("failed reading rsa key")
- }
- defer C.RSA_free(rsakey)
- // convert to PKEY
- key := C.X_EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed converting to evp_pkey")
- }
- if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
- C.X_EVP_PKEY_free(key)
- return nil, errors.New("failed converting to evp_pkey")
- }
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.X_EVP_PKEY_free(p.key)
- })
- return p, nil
- }
- // LoadPrivateKeyFromPEMWidthPassword loads a private key from a PEM-encoded block.
- // Backwards-compatible with typo
- func LoadPrivateKeyFromPEMWidthPassword(pem_block []byte, password string) (
- PrivateKey, error) {
- return LoadPrivateKeyFromPEMWithPassword(pem_block, password)
- }
- // 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")
- }
- bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
- C.int(len(pem_block)))
- if bio == nil {
- return nil, errors.New("failed creating bio")
- }
- defer C.BIO_free(bio)
- 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.X_EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed converting to evp_pkey")
- }
- if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
- C.X_EVP_PKEY_free(key)
- return nil, errors.New("failed converting to evp_pkey")
- }
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.X_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")
- }
- defer C.RSA_free(rsakey)
- // convert to PKEY
- key := C.X_EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed converting to evp_pkey")
- }
- if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
- C.X_EVP_PKEY_free(key)
- return nil, errors.New("failed converting to evp_pkey")
- }
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.X_EVP_PKEY_free(p.key)
- })
- return p, nil
- }
- // GenerateRSAKey generates a new RSA private key with an exponent of 3.
- func GenerateRSAKey(bits int) (PrivateKey, error) {
- return GenerateRSAKeyWithExponent(bits, 3)
- }
- // GenerateRSAKeyWithExponent generates a new RSA private key.
- func GenerateRSAKeyWithExponent(bits int, exponent int) (PrivateKey, error) {
- rsa := C.RSA_generate_key(C.int(bits), C.ulong(exponent), nil, nil)
- if rsa == nil {
- return nil, errors.New("failed to generate RSA key")
- }
- key := C.X_EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed to allocate EVP_PKEY")
- }
- if C.X_EVP_PKEY_assign_charp(key, C.EVP_PKEY_RSA, (*C.char)(unsafe.Pointer(rsa))) != 1 {
- C.X_EVP_PKEY_free(key)
- return nil, errors.New("failed to assign RSA key")
- }
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.X_EVP_PKEY_free(p.key)
- })
- return p, nil
- }
|