diff --git a/go/gmssl/build.go b/go/gmssl/build.go index beb35f56..b91121b0 100755 --- a/go/gmssl/build.go +++ b/go/gmssl/build.go @@ -5,5 +5,16 @@ package gmssl /* #cgo darwin CFLAGS: -I/usr/local/include #cgo darwin LDFLAGS: -L/usr/local/lib -lcrypto + +#include +#include + +long _BIO_get_mem_data(BIO *b, char **pp) { + return BIO_get_mem_data(b, pp); +} + +void _OPENSSL_free(void *addr) { + OPENSSL_free(addr); +} */ import "C" diff --git a/go/gmssl/certificate.go b/go/gmssl/certificate.go index 9c029e02..5a8c350b 100644 --- a/go/gmssl/certificate.go +++ b/go/gmssl/certificate.go @@ -14,14 +14,8 @@ package gmssl #include #include -static void _OPENSSL_free(void *p) { - OPENSSL_free(p); -} - -static long _BIO_get_mem_data(BIO *b, char **pp) { - return BIO_get_mem_data(b, pp); -} - +extern long _BIO_get_mem_data(BIO *b, char **pp); +extern void _OPENSSL_free(void *addr); */ import "C" @@ -35,7 +29,7 @@ type Certificate struct { x509 *C.X509 } -func ReadCertificateFromPEM(pem string, pass string) (*Certificate, error) { +func NewCertificateFromPEM(pem string, pass string) (*Certificate, error) { cpem := C.CString(pem) defer C.free(unsafe.Pointer(cpem)) cpass := C.CString(pass) @@ -114,6 +108,11 @@ func (cert *Certificate) GetPublicKey() (*PublicKey, error) { }) return ret, nil } + +func (cert *Certificate) GetText() (string, error) { + return "", nil +} + func (cert *Certificate) CheckPrivateKey(skey *PrivateKey) error { if 1 != C.X509_check_private_key(cert.x509, skey.pkey) { err := GetErrors() @@ -124,4 +123,3 @@ func (cert *Certificate) CheckPrivateKey(skey *PrivateKey) error { } return nil } - diff --git a/go/gmssl/cipher.go b/go/gmssl/cipher.go index 6d724332..0c77d03b 100644 --- a/go/gmssl/cipher.go +++ b/go/gmssl/cipher.go @@ -34,9 +34,7 @@ static char *get_cipher_names(void) { return ret; } -static void _OPENSSL_free(void *addr) { - OPENSSL_free(addr); -} +extern void _OPENSSL_free(void *addr); */ import "C" @@ -87,7 +85,7 @@ type CipherContext struct { ctx *C.EVP_CIPHER_CTX } -func NewCipherContext(name string, eng *Engine, key, iv []byte, encrypt bool) ( +func NewCipherContext(name string, key, iv []byte, encrypt bool) ( *CipherContext, error) { cname := C.CString(name) diff --git a/go/gmssl/digest.go b/go/gmssl/digest.go index 7a440263..56c00dd6 100644 --- a/go/gmssl/digest.go +++ b/go/gmssl/digest.go @@ -5,6 +5,7 @@ package gmssl /* #include #include +#include #include static void cb_digest_names_len(const EVP_MD *md, const char *from, @@ -36,9 +37,7 @@ static char *get_digest_names() { return ret; } -static void _OPENSSL_free(void *addr) { - OPENSSL_free(addr); -} +extern void _OPENSSL_free(void *addr); */ import "C" @@ -64,32 +63,38 @@ func GetDigestLength(name string) (int, error) { return int(C.EVP_MD_size(md)), nil } +func GetDigestBlockSize(name string) (int, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + md := C.EVP_get_digestbyname(cname) + if md == nil { + return 0, GetErrors() + } + return int(C.EVP_MD_block_size(md)), nil +} + type DigestContext struct { ctx *C.EVP_MD_CTX } -func NewDigestContext(name string, eng *Engine) (*DigestContext, error) { +func NewDigestContext(name string) (*DigestContext, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) md := C.EVP_get_digestbyname(cname) if md == nil { return nil, GetErrors() } - ctx := C.EVP_MD_CTX_new() if ctx == nil { return nil, GetErrors() } - ret := &DigestContext{ctx} runtime.SetFinalizer(ret, func(ret *DigestContext) { C.EVP_MD_CTX_free(ret.ctx) }) - - if 1 != C.EVP_DigestInit(ctx, md) { + if 1 != C.EVP_DigestInit_ex(ctx, md, nil) { return nil, GetErrors() } - return ret, nil } @@ -106,8 +111,19 @@ func (ctx *DigestContext) Update(data []byte) error { func (ctx *DigestContext) Final() ([]byte, error) { outbuf := make([]byte, 64) outlen := C.uint(len(outbuf)) - if 1 != C.EVP_DigestFinal(ctx.ctx, (*C.uchar)(unsafe.Pointer(&outbuf[0])), &outlen) { + if 1 != C.EVP_DigestFinal_ex(ctx.ctx, (*C.uchar)(unsafe.Pointer(&outbuf[0])), &outlen) { return nil, GetErrors() } return outbuf[:outlen], nil } + +func (ctx *DigestContext) Reset() error { + md := C.EVP_MD_CTX_md(ctx.ctx) + if md == nil { + return GetErrors() + } + if 1 != C.EVP_DigestInit_ex(ctx.ctx, md, nil) { + return GetErrors() + } + return nil +} diff --git a/go/gmssl/engine.go b/go/gmssl/engine.go index c6b812dc..c3f6cad0 100644 --- a/go/gmssl/engine.go +++ b/go/gmssl/engine.go @@ -9,30 +9,6 @@ package gmssl #include #include #include - -static char *get_errors() { - char *ret; - BIO *bio; - char *data; - long len; - if (!(bio = BIO_new(BIO_s_mem()))) { - return (char *)NULL; - } - ERR_print_errors(bio); - len = BIO_get_mem_data(bio, &data); - ret = OPENSSL_strdup(data); - BIO_free(bio); - return ret; -} - -static EVP_PKEY *load_public_key(ENGINE *e, const char *id, char *pass) { - return ENGINE_load_public_key(e, id, NULL, pass); -} - -static EVP_PKEY *load_private_key(ENGINE *e, const char *id, char *pass) { - return ENGINE_load_private_key(e, id, NULL, pass); -} - */ import "C" @@ -61,7 +37,7 @@ type Engine struct { engine *C.ENGINE; } -func GetEngineByName(name string) (*Engine, error) { +func NewEngineByName(name string) (*Engine, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) eng := C.ENGINE_by_id(cname) @@ -79,6 +55,10 @@ func GetEngineByName(name string) (*Engine, error) { return ret, nil } +func (e *Engine) GetCommands() ([]string, error) { + return []string{"SO_PATH"}, nil +} + func (e *Engine) RunCommand(name, arg string) error { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -99,7 +79,8 @@ func (e *Engine) GetPrivateKey(id string, pass string) (*PrivateKey, error) { defer C.free(unsafe.Pointer(cid)) cpass := C.CString(pass) defer C.free(unsafe.Pointer(cpass)) - sk := C.load_private_key(e.engine, cid, cpass) + sk := C.ENGINE_load_private_key(e.engine, cid, nil, + unsafe.Pointer(cpass)) if sk == nil { return nil, GetErrors() } @@ -111,7 +92,9 @@ func (e *Engine) GetPublicKey(id string, pass string) (*PublicKey, error) { defer C.free(unsafe.Pointer(cid)) cpass := C.CString(pass) defer C.free(unsafe.Pointer(cpass)) - pk := C.load_public_key(e.engine, cid, cpass) + + pk := C.ENGINE_load_public_key(e.engine, cid, nil, + unsafe.Pointer(cpass)) if pk == nil { return nil, GetErrors() } diff --git a/go/gmssl/error.go b/go/gmssl/error.go index 0fcdeb38..7616cb9c 100644 --- a/go/gmssl/error.go +++ b/go/gmssl/error.go @@ -5,10 +5,8 @@ package gmssl #include #include -long bio_get_mem_data(BIO *bio, char **pp) { - return BIO_get_mem_data(bio, pp); -} +extern long _BIO_get_mem_data(BIO *b, char **pp); */ import "C" @@ -24,7 +22,7 @@ func GetErrors() error { defer C.BIO_free(bio) C.ERR_print_errors(bio) var p *C.char - len := C.bio_get_mem_data(bio, &p) + len := C._BIO_get_mem_data(bio, &p) if len <= 0 { return errors.New("GetErrors function failure 2") } diff --git a/go/gmssl/hmac.go b/go/gmssl/hmac.go new file mode 100644 index 00000000..e8befed1 --- /dev/null +++ b/go/gmssl/hmac.go @@ -0,0 +1,79 @@ +/* +build cgo */ + +package gmssl + +/* +#include +#include +*/ +import "C" + +import ( + "unsafe" + "runtime" +) + +func GetMacLength(name string) (int, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + md := C.EVP_get_digestbyname(cname) + if md == nil { + return 0, GetErrors() + } + return int(C.EVP_MD_size(md)), nil +} + +type HMACContext struct { + hctx *C.HMAC_CTX +} + +func NewHMACContext(name string, key []byte) ( + *HMACContext, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + md := C.EVP_get_digestbyname(cname) + if md == nil { + return nil, GetErrors() + } + ctx := C.HMAC_CTX_new() + if ctx == nil { + return nil, GetErrors() + } + ret := &HMACContext{ctx} + runtime.SetFinalizer(ret, func(ret *HMACContext) { + C.HMAC_CTX_free(ret.hctx) + }) + if 1 != C.HMAC_Init_ex(ctx, + unsafe.Pointer(&key[0]), C.int(len(key)), md, nil) { + return nil, GetErrors() + } + return ret, nil +} + +func (ctx *HMACContext) Update(data []byte) error { + if len(data) == 0 { + return nil + } + if 1 != C.HMAC_Update(ctx.hctx, + (*C.uchar)(unsafe.Pointer(&data[0])), C.size_t(len(data))) { + return GetErrors() + } + return nil +} + +func (ctx *HMACContext) Final() ([]byte, error) { + outbuf := make([]byte, 64) + outlen := C.uint(len(outbuf)) + if 1 != C.HMAC_Final(ctx.hctx, + (*C.uchar)(unsafe.Pointer(&outbuf[0])), &outlen) { + return nil, GetErrors() + } + return outbuf[:outlen], nil +} + +func (ctx *HMACContext) Reset() error { + if 1 != C.HMAC_Init_ex(ctx.hctx, nil, 0, nil, nil) { + return GetErrors() + } + return nil +} diff --git a/go/gmssl/pkey.go b/go/gmssl/pkey.go index 9db80540..9935bb3f 100644 --- a/go/gmssl/pkey.go +++ b/go/gmssl/pkey.go @@ -10,11 +10,12 @@ package gmssl #include #include #include +#include #include #include #include -extern long bio_get_mem_data(BIO *bio, char **pp); +extern long _BIO_get_mem_data(BIO *bio, char **pp); EVP_PKEY_CTX *new_pkey_keygen_ctx(const char *alg, ENGINE *e) { EVP_PKEY_CTX *ret = NULL; @@ -326,7 +327,6 @@ static int get_exch_info(const char *alg, int *ppkey_type, int *pec_scheme, ecdh_kdf_type = NID_sha384; break; case NID_dhSinglePass_cofactorDH_sha512kdf_scheme: - pkey_type = EVP_PKEY_EC; ec_scheme = NID_secg_scheme; ecdh_cofactor_mode = 1; ecdh_kdf_type = NID_sha512; @@ -461,6 +461,7 @@ unsigned char *sk_sign(EVP_PKEY *sk, const char *alg, const unsigned char *dgst, if (!(sig = OPENSSL_zalloc(EVP_PKEY_size(sk)))) { goto end; } + *siglen = EVP_PKEY_size(sk); if (EVP_PKEY_sign(ctx, sig, siglen, dgst, dgstlen) <= 0) { goto end; } @@ -478,11 +479,14 @@ int pk_verify(EVP_PKEY *pk, const char *alg, const unsigned char *dgst, EVP_PKEY_CTX *ctx = NULL; if (!(ctx = EVP_PKEY_CTX_new(pk, e))) { + printf("%s %d: error\n", __FILE__, __LINE__); goto end; } if (!EVP_PKEY_verify_init(ctx)) { + printf("%s %d: error\n", __FILE__, __LINE__); goto end; } + if (EVP_PKEY_id(pk) == EVP_PKEY_EC && EC_GROUP_get_curve_name( EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pk))) == NID_sm2p256v1) { if (EVP_PKEY_CTX_set_ec_scheme(ctx, NID_sm_scheme) <= 0) { @@ -490,6 +494,8 @@ int pk_verify(EVP_PKEY *pk, const char *alg, const unsigned char *dgst, } } if ((ret = EVP_PKEY_verify(ctx, sig, siglen, dgst, dgstlen)) <= 0) { + printf("ret = %d\n", ret); + ERR_print_errors_fp(stderr); goto end; } end: @@ -507,6 +513,7 @@ import "C" import ( "unsafe" + "errors" "runtime" ) @@ -521,63 +528,87 @@ func GetPublicKeyAlgorithmNames() []string { } func GetSignAlgorithmNames(pkey string) ([]string, error) { - return []string{ - "sm2sign", - "ecdsa-with-Recommended", - "ecdsa-with-SHA1", - "ecdsa-with-SHA256", - "ecdsa-with-SHA512", - "RSA-SHA1", - "RSA-SHA256", - "RSA-SHA512", - "DSA-SHA1", - }, nil + if pkey == "EC" { + return []string{ + "sm2sign", + "ecdsa-with-Recommended", + "ecdsa-with-SHA1", + "ecdsa-with-SHA256", + "ecdsa-with-SHA512", + }, nil + } else if pkey == "RSA" { + return []string{ + "RSA-SHA1", + "RSA-SHA256", + "RSA-SHA512", + }, nil + } else if pkey == "DSA" { + return []string{ + "DSA-SHA1", + }, nil + } else { + return nil, errors.New("Invalid public key algorithm") + } } func GetPublicKeyEncryptionNames(pkey string) ([]string, error) { - return []string{ - "RSAES-OAEP", - "ecies-recommendedParameters", - "ecies-specifiedParameters", - "ecies-with-x9-63-sha1-xor-hmac", - "ecies-with-x9-63-sha256-xor-hmac", - "ecies-with-x9-63-sha512-xor-hmac", - "ecies-with-x9-63-sha1-aes128-cbc-hmac", - "ecies-with-x9-63-sha256-aes128-cbc-hmac", - "ecies-with-x9-63-sha512-aes256-cbc-hmac", - "ecies-with-x9-63-sha256-aes128-ctr-hmac", - "ecies-with-x9-63-sha512-aes256-ctr-hmac", - "ecies-with-x9-63-sha256-aes128-cbc-hmac-half", - "ecies-with-x9-63-sha512-aes256-cbc-hmac-half", - "ecies-with-x9-63-sha256-aes128-ctr-hmac-half", - "ecies-with-x9-63-sha512-aes256-ctr-hmac-half", - "ecies-with-x9-63-sha1-aes128-cbc-cmac", - "ecies-with-x9-63-sha256-aes128-cbc-cmac", - "ecies-with-x9-63-sha512-aes256-cbc-cmac", - "ecies-with-x9-63-sha256-aes128-ctr-cmac", - "ecies-with-x9-63-sha512-aes256-ctr-cmac", - "sm2encrypt-with-sm3", - "sm2encrypt-with-sha1", - "sm2encrypt-with-sha256", - "sm2encrypt-with-sha512", - }, nil + if pkey == "RSA" { + return []string{ + "RSAES-OAEP", + }, nil + } else if pkey == "EC" { + return []string { + "ecies-recommendedParameters", + "ecies-specifiedParameters", + "ecies-with-x9-63-sha1-xor-hmac", + "ecies-with-x9-63-sha256-xor-hmac", + "ecies-with-x9-63-sha512-xor-hmac", + "ecies-with-x9-63-sha1-aes128-cbc-hmac", + "ecies-with-x9-63-sha256-aes128-cbc-hmac", + "ecies-with-x9-63-sha512-aes256-cbc-hmac", + "ecies-with-x9-63-sha256-aes128-ctr-hmac", + "ecies-with-x9-63-sha512-aes256-ctr-hmac", + "ecies-with-x9-63-sha256-aes128-cbc-hmac-half", + "ecies-with-x9-63-sha512-aes256-cbc-hmac-half", + "ecies-with-x9-63-sha256-aes128-ctr-hmac-half", + "ecies-with-x9-63-sha512-aes256-ctr-hmac-half", + "ecies-with-x9-63-sha1-aes128-cbc-cmac", + "ecies-with-x9-63-sha256-aes128-cbc-cmac", + "ecies-with-x9-63-sha512-aes256-cbc-cmac", + "ecies-with-x9-63-sha256-aes128-ctr-cmac", + "ecies-with-x9-63-sha512-aes256-ctr-cmac", + "sm2encrypt-with-sm3", + "sm2encrypt-with-sha1", + "sm2encrypt-with-sha256", + "sm2encrypt-with-sha512", + }, nil + } else { + return nil, errors.New("Invalid public key algorithm") + } } func GetDeriveKeyAlgorithmNames(pkey string) ([]string, error) { - return []string{ - "sm2exchange", - "dhSinglePass-stdDH-sha1kdf-scheme", - "dhSinglePass-stdDH-sha224kdf-scheme", - "dhSinglePass-stdDH-sha256kdf-scheme", - "dhSinglePass-stdDH-sha384kdf-scheme", - "dhSinglePass-stdDH-sha512kdf-scheme", - "dhSinglePass-cofactorDH-sha1kdf-scheme", - "dhSinglePass-cofactorDH-sha224kdf-scheme", - "dhSinglePass-cofactorDH-sha256kdf-scheme", - "dhSinglePass-cofactorDH-sha384kdf-scheme", - "dhSinglePass-cofactorDH-sha512kdf-scheme", - "dhKeyAgreement", - }, nil + if pkey == "EC" { + return []string{ + "sm2exchange", + }, nil + } else if pkey == "DH" { + return []string{ + "dhSinglePass-stdDH-sha1kdf-scheme", + "dhSinglePass-stdDH-sha224kdf-scheme", + "dhSinglePass-stdDH-sha256kdf-scheme", + "dhSinglePass-stdDH-sha384kdf-scheme", + "dhSinglePass-stdDH-sha512kdf-scheme", + "dhSinglePass-cofactorDH-sha1kdf-scheme", + "dhSinglePass-cofactorDH-sha224kdf-scheme", + "dhSinglePass-cofactorDH-sha256kdf-scheme", + "dhSinglePass-cofactorDH-sha384kdf-scheme", + "dhSinglePass-cofactorDH-sha512kdf-scheme", + "dhKeyAgreement", + }, nil + } else { + return nil, errors.New("No algorithm supported") + } } type PublicKey struct { @@ -588,10 +619,17 @@ type PrivateKey struct { pkey *C.EVP_PKEY } -func GeneratePrivateKey(alg string, args map[string]string, eng Engine) (*PrivateKey, error) { +func GeneratePrivateKey(alg string, args map[string]string, eng *Engine) (*PrivateKey, error) { calg := C.CString(alg) defer C.free(unsafe.Pointer(calg)) - ctx := C.new_pkey_keygen_ctx(calg, eng.engine) + + ctx := C.new_pkey_keygen_ctx(calg, nil) + /* + if eng != nil { + ctx := C.new_pkey_keygen_ctx(calg, eng.engine) + } + */ + if ctx == nil { return nil, GetErrors() } @@ -687,18 +725,20 @@ func (sk *PrivateKey) GetPEM(cipher string, pass string) (string, error) { return "", GetErrors() } + /* FIXME: PKCS #5 can not use SM4 */ if 1 != C.PEM_write_bio_PrivateKey(bio, sk.pkey, - C.EVP_sms4_cbc(), nil, C.int(0), nil, unsafe.Pointer(cpass)) { + C.EVP_des_ede3_cbc(), nil, C.int(0), nil, unsafe.Pointer(cpass)) { + C.ERR_print_errors_fp(C.stderr) return "", GetErrors() } var p *C.char - len := C.bio_get_mem_data(bio, &p) + len := C._BIO_get_mem_data(bio, &p) if len <= 0 { return "", GetErrors() } - return C.GoString(p), nil + return C.GoString(p)[:len], nil } func (sk *PrivateKey) GetPublicKeyPEM() (string, error) { @@ -711,11 +751,11 @@ func (sk *PrivateKey) GetPublicKeyPEM() (string, error) { return "", GetErrors() } var p *C.char - len := C.bio_get_mem_data(bio, &p) + len := C._BIO_get_mem_data(bio, &p) if len <= 0 { return "", GetErrors() } - return C.GoString(p), nil + return C.GoString(p)[:len], nil } func (sk *PrivateKey) GetText() (string, error) { @@ -724,15 +764,15 @@ func (sk *PrivateKey) GetText() (string, error) { return "", GetErrors() } defer C.BIO_free(bio) - if 1 != C.EVP_PKEY_print_private(bio, sk.pkey, 4, nil) { + if 1 != C.EVP_PKEY_print_private(bio, sk.pkey, 0, nil) { return "", GetErrors() } var p *C.char - len := C.bio_get_mem_data(bio, &p) + len := C._BIO_get_mem_data(bio, &p) if len <= 0 { return "", GetErrors() } - return C.GoString(p), nil + return C.GoString(p)[:len], nil } func NewPublicKeyFromPEM(pem string)(*PublicKey, error) { @@ -764,11 +804,11 @@ func (pk *PublicKey) GetPEM() (string, error) { return "", GetErrors() } var p *C.char - len := C.bio_get_mem_data(bio, &p) + len := C._BIO_get_mem_data(bio, &p) if len <= 0 { return "", GetErrors() } - return C.GoString(p), nil + return C.GoString(p)[:len], nil } func (pk *PublicKey) GetText() (string, error) { @@ -781,59 +821,63 @@ func (pk *PublicKey) GetText() (string, error) { return "", GetErrors() } var p *C.char - len := C.bio_get_mem_data(bio, &p) + len := C._BIO_get_mem_data(bio, &p) if len <= 0 { return "", GetErrors() } - return C.GoString(p), nil + return C.GoString(p)[:len], nil } -func (pk *PublicKey) Encrypt(alg string, in []byte, eng Engine) ([]byte, error) { +func (pk *PublicKey) Encrypt(alg string, in []byte, eng *Engine) ([]byte, error) { calg := C.CString(alg) defer C.free(unsafe.Pointer(calg)) var outlen C.size_t out := C.pk_encrypt(pk.pkey, calg, (*C.uchar)(&in[0]), - C.size_t(len(in)), &outlen, eng.engine) + C.size_t(len(in)), &outlen, nil) if out == nil { return nil, GetErrors() } return C.GoBytes(unsafe.Pointer(out), C.int(outlen)), nil } -func (sk *PrivateKey) Decrypt(alg string, in []byte, eng Engine) ([]byte, error) { +func (sk *PrivateKey) Decrypt(alg string, in []byte, eng *Engine) ([]byte, error) { calg := C.CString(alg) defer C.free(unsafe.Pointer(calg)) var outlen C.size_t out := C.sk_decrypt(sk.pkey, calg, (*C.uchar)(&in[0]), - C.size_t(len(in)), &outlen, eng.engine) + C.size_t(len(in)), &outlen, nil) if out == nil { return nil, GetErrors() } return C.GoBytes(unsafe.Pointer(out), C.int(outlen)), nil } -func (sk *PrivateKey) Sign(alg string, dgst []byte, eng Engine) ([]byte, error) { +func (sk *PrivateKey) Sign(alg string, dgst []byte, eng *Engine) ([]byte, error) { calg := C.CString(alg) defer C.free(unsafe.Pointer(calg)) var siglen C.size_t - sig := C.sk_sign(sk.pkey, calg, (*C.uchar)(&dgst[0]), C.size_t(len(dgst)), &siglen, eng.engine) + sig := C.sk_sign(sk.pkey, calg, (*C.uchar)(&dgst[0]), + C.size_t(len(dgst)), &siglen, nil) if sig == nil { + C.ERR_print_errors_fp(C.stderr) return nil, GetErrors() } return C.GoBytes(unsafe.Pointer(sig), C.int(siglen)), nil } -func (pk *PublicKey) Verify(alg string, dgst, sig []byte, eng Engine) error { +func (pk *PublicKey) Verify(alg string, dgst, sig []byte, eng *Engine) error { calg := C.CString(alg) defer C.free(unsafe.Pointer(calg)) + if 1 != C.pk_verify(pk.pkey, calg, (*C.uchar)(&dgst[0]), C.size_t(len(dgst)), - (*C.uchar)(&sig[0]), C.size_t(len(sig)), eng.engine) { + (*C.uchar)(&sig[0]), C.size_t(len(sig)), nil) { + C.ERR_print_errors_fp(C.stderr) return GetErrors() } return nil } -func (sk *PrivateKey) DeriveKey(alg string, peer PublicKey, eng Engine) ([]byte, error) { +func (sk *PrivateKey) DeriveKey(alg string, peer PublicKey, eng *Engine) ([]byte, error) { calg := C.CString(alg) defer C.free(unsafe.Pointer(calg)) var keylen C.size_t diff --git a/go/gmssl/rand.go b/go/gmssl/rand.go index ede21259..4f84e09f 100644 --- a/go/gmssl/rand.go +++ b/go/gmssl/rand.go @@ -20,6 +20,5 @@ func GenerateRandom(length int) ([]byte, error) { if C.RAND_bytes((*C.uchar)(&outbuf[0]), C.int(length)) <= 0 { return nil, GetErrors() } - return outbuf[:length], nil } diff --git a/go/gmssl/sm3/sm3.go b/go/gmssl/sm3/sm3.go index 3f43bf37..606d0497 100644 --- a/go/gmssl/sm3/sm3.go +++ b/go/gmssl/sm3/sm3.go @@ -11,7 +11,7 @@ type digest struct { func New() hash.Hash { d := new(digest) - ctx, err := gmssl.NewDigestContext("SM3", nil) + ctx, err := gmssl.NewDigestContext("SM3") if err != nil { return nil } @@ -36,10 +36,7 @@ func (d *digest) Size() int { } func (d *digest) Reset() { - err := d.ctx.Reset() - if err != nil { - // do something? - } + _ = d.ctx.Reset() } func (d *digest) Write(p []byte) (int, error) { diff --git a/go/gmssl/version.go b/go/gmssl/version.go index 3485845c..bcdef80d 100644 --- a/go/gmssl/version.go +++ b/go/gmssl/version.go @@ -8,7 +8,7 @@ import "C" func GetVersions() []string { versions := []string { - "GmSSL Go API 1.2 Aug 4 2018", + "GmSSL Go API 1.3 Aug 6 2018", C.GoString(C.OpenSSL_version(C.OPENSSL_VERSION)), C.GoString(C.OpenSSL_version(C.OPENSSL_BUILT_ON)), C.GoString(C.OpenSSL_version(C.OPENSSL_CFLAGS)), diff --git a/go/gmssltest/gmssltest.go b/go/gmssltest/gmssltest.go index 3f4e2581..de54fe8d 100644 --- a/go/gmssltest/gmssltest.go +++ b/go/gmssltest/gmssltest.go @@ -11,135 +11,164 @@ func main() { versions := gmssl.GetVersions() fmt.Println("GmSSL Versions:") for _, version := range versions { - fmt.Println(" " + version) + fmt.Println(" " + version) } - fmt.Println(""); + fmt.Println("") - fmt.Println("Supported Digest Algorithms:") + fmt.Print("Digest Algorithms:") digests := gmssl.GetDigestNames() for _, digest := range digests { - fmt.Println(" " + digest) + fmt.Print(" " + digest) } - fmt.Println(""); + fmt.Println("\n") - fmt.Println("Supported Ciphers:") + fmt.Print("Ciphers:") ciphers := gmssl.GetCipherNames() for _, cipher := range ciphers { - fmt.Println(" " + cipher) + fmt.Print(" " + cipher) } - fmt.Println(""); + fmt.Println("\n") - /* sm3 digest */ - sm3ctx, err := gmssl.NewDigestContext("SM3", nil) - if err != nil { - fmt.Println(err) - return + fmt.Println("Public Key Algorithms:") + pkey_algs := gmssl.GetPublicKeyAlgorithmNames() + for _, pkey_alg := range pkey_algs { + fmt.Print(" " + pkey_alg + ":") + sign_algs, _ := gmssl.GetSignAlgorithmNames(pkey_alg) + for _, sign_alg := range sign_algs { + fmt.Print(" " + sign_alg) + } + pkey_encs, _ := gmssl.GetPublicKeyEncryptionNames(pkey_alg) + for _, pkey_enc := range pkey_encs { + fmt.Print(" " + pkey_enc) + } + derive_algs, _ := gmssl.GetDeriveKeyAlgorithmNames(pkey_alg) + for _, derive_alg := range derive_algs { + fmt.Print(" " + derive_alg) + } + fmt.Println("") } - if err := sm3ctx.Update([]byte("a")); err != nil { - fmt.Println(err) - return - } - if err := sm3ctx.Update([]byte("bc")); err != nil { - fmt.Println(err) - return - } - sm3digest, err := sm3ctx.Final() - if err != nil { - fmt.Println(err) - return + fmt.Println("") + + /* Engines */ + fmt.Print("Engines:") + engines := gmssl.GetEngineNames() + for _, engine := range engines { + fmt.Print(" " + engine) } + fmt.Println("\n"); + + /* SM3 digest with GmSSL-Go API */ + sm3ctx, _ := gmssl.NewDigestContext("SM3") + sm3ctx.Update([]byte("a")) + sm3ctx.Update([]byte("bc")) + sm3digest, _ := sm3ctx.Final() fmt.Printf("sm3(\"abc\") = %x\n", sm3digest) + /* SM3 digest with Go hash.Hash API */ sm3hash := sm3.New() sm3hash.Write([]byte("abc")) fmt.Printf("sm3(\"abc\") = %x\n", sm3hash.Sum(nil)) - /* hmac-sm3 */ - hmac_sm3, err := gmssl.NewHMACContext("SM3", nil, []byte("this is the key")) - if err != nil { - fmt.Println(err) - return - } - if err := hmac_sm3.Update([]byte("ab")); err != nil { - fmt.Println(err) - return - } - if err := hmac_sm3.Update([]byte("c")); err != nil { - fmt.Println(err) - return - } - mactag, err := hmac_sm3.Final() - if err != nil { - fmt.Println(err) - return - } + /* HMAC-SM3 */ + hmac_sm3, _ := gmssl.NewHMACContext("SM3", []byte("this is the key")) + hmac_sm3.Update([]byte("ab")) + hmac_sm3.Update([]byte("c")) + mactag, _ := hmac_sm3.Final() fmt.Printf("hmac-sm3(\"abc\") = %x\n", mactag) - /* generate random key */ - keylen, err := gmssl.GetCipherKeyLength("SMS4") - if err != nil { - fmt.Println(err) - return - } - key, err := gmssl.GenerateRandom(keylen) - if err != nil { - fmt.Println(err) - return - } + /* Generate random key and IV */ + keylen, _ := gmssl.GetCipherKeyLength("SMS4") + key, _ := gmssl.GenerateRandom(keylen) + ivlen, _ := gmssl.GetCipherIVLength("SMS4") + iv, _ := gmssl.GenerateRandom(ivlen) - /* generate random iv */ - ivlen, err := gmssl.GetCipherIVLength("SMS4") - if err != nil { - fmt.Println(err) - return - } - iv, err := gmssl.GenerateRandom(ivlen) - if err != nil { - fmt.Println(err) - return - } - - /* encrypt */ - encryptor, err := gmssl.NewCipherContext("SMS4", nil, key, iv, true) - if err != nil { - fmt.Println(err) - return - } - ciphertext1, err := encryptor.Update([]byte("hello")) - if err != nil { - fmt.Println(err) - return - } - ciphertext2, err := encryptor.Final() - if err != nil { - fmt.Println(err) - return - } + /* SMS4-CBC Encrypt/Decrypt */ + encryptor, _ := gmssl.NewCipherContext("SMS4", key, iv, true) + ciphertext1, _ := encryptor.Update([]byte("hello")) + ciphertext2, _ := encryptor.Final() ciphertext := make([]byte, 0, len(ciphertext1) + len(ciphertext2)) ciphertext = append(ciphertext, ciphertext1...) ciphertext = append(ciphertext, ciphertext2...) - /* decrypt */ - decryptor, err := gmssl.NewCipherContext("SMS4", nil, key, iv, false) - if err != nil { - fmt.Println(err) - return - } - plaintext1, err := decryptor.Update(ciphertext) - if err != nil { - fmt.Println(err) - return - } - plaintext2, err := decryptor.Final() - if err != nil { - fmt.Println(err) - return - } + decryptor, _ := gmssl.NewCipherContext("SMS4", key, iv, false) + plaintext1, _ := decryptor.Update(ciphertext) + plaintext2, _ := decryptor.Final() plaintext := make([]byte, 0, len(plaintext1) + len(plaintext2)) plaintext = append(plaintext, plaintext1...) plaintext = append(plaintext, plaintext2...) fmt.Printf("sms4(\"%s\") = %x\n", plaintext, ciphertext) + fmt.Println() + + /* private key */ + rsa_args := map[string]string { + "rsa_keygen_bits": "2048", + "rsa_keygen_pubexp" : "65537", + } + + rsa, err := gmssl.GeneratePrivateKey("RSA", rsa_args, nil) + if err != nil { + fmt.Println(err) + return + } + rsa_pem, err := rsa.GetPublicKeyPEM() + if err != nil { + fmt.Println(err) + return + } + fmt.Println(rsa_pem) + + /* Engine */ + eng, _ := gmssl.NewEngineByName(engines[1]) + cmds, _ := eng.GetCommands() + for _, cmd := range cmds { + fmt.Print(" " + cmd) + } + fmt.Println() + + /* SM2 key pair operations */ + sm2keygenargs := map[string]string { + "ec_paramgen_curve": "sm2p256v1", + "ec_param_enc": "named_curve", + } + sm2sk, _ := gmssl.GeneratePrivateKey("EC", sm2keygenargs, nil) + sm2sktxt, _ := sm2sk.GetText() + sm2skpem, _ := sm2sk.GetPEM("SMS4", "password") + sm2pkpem, _ := sm2sk.GetPublicKeyPEM() + + fmt.Println(sm2sktxt) + fmt.Println(sm2skpem) + fmt.Println(sm2pkpem) + + sm2pk, _ := gmssl.NewPublicKeyFromPEM(sm2pkpem) + sm2pktxt, _ := sm2pk.GetText() + sm2pkpem_, _ := sm2pk.GetPEM() + + fmt.Println(sm2pktxt) + fmt.Println(sm2pkpem_) + + /* SM2 sign/verification */ + sm3ctx.Reset() + sm3ctx.Update([]byte("message")) + tbs, _ := sm3ctx.Final() + + sig, _ := sm2sk.Sign("sm2sign", tbs, nil) + fmt.Printf("sm2sign(sm3(\"message\")) = %x\n", sig) + + if ret := sm2pk.Verify("sm2sign", tbs, sig, nil); ret != nil { + fmt.Printf("sm2 verify failure\n") + } else { + fmt.Printf("sm2 verify success\n") + } + + /* SM2 encrypt */ + sm2msg := "01234567891123456789212345678931234567894123456789512345678961234567897123" + sm2encalg := "sm2encrypt-with-sm3" + sm2ciphertext, _ := sm2pk.Encrypt(sm2encalg, []byte(sm2msg), nil) + sm2plaintext, _ := sm2sk.Decrypt(sm2encalg, sm2ciphertext, nil) + fmt.Printf("sm2enc(\"%s\") = %x\n", sm2plaintext, sm2ciphertext) + if sm2msg != string(sm2plaintext) { + fmt.Println("SM2 encryption/decryption failure") + } } -