From abedd1b0f40d822a2447f9afbee2845a68d65f36 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sat, 4 Aug 2018 20:27:43 +0800 Subject: [PATCH] update go-api GetDigestNames() and GetCipherNames get supported algorithms with callbacks. --- go/gmssl/certificate.go | 4 +- go/gmssl/cipher.go | 188 ++++++++------------------------------ go/gmssl/digest.go | 65 +++++++------ go/gmssl/engine.go | 6 +- go/gmssl/error.go | 4 +- go/gmssl/mac.go | 54 +++-------- go/gmssl/version.go | 2 +- go/gmssltest/gmssltest.go | 81 ++++++++++++---- 8 files changed, 160 insertions(+), 244 deletions(-) diff --git a/go/gmssl/certificate.go b/go/gmssl/certificate.go index 9100d2cb..9c029e02 100644 --- a/go/gmssl/certificate.go +++ b/go/gmssl/certificate.go @@ -14,11 +14,11 @@ package gmssl #include #include -void _OPENSSL_free(void *p) { +static void _OPENSSL_free(void *p) { OPENSSL_free(p); } -long _BIO_get_mem_data(BIO *b, char **pp) { +static long _BIO_get_mem_data(BIO *b, char **pp) { return BIO_get_mem_data(b, pp); } diff --git a/go/gmssl/cipher.go b/go/gmssl/cipher.go index cebf9604..6d724332 100644 --- a/go/gmssl/cipher.go +++ b/go/gmssl/cipher.go @@ -2,7 +2,41 @@ package gmssl /* +#include #include +#include + +static void cb_cipher_names_len(const EVP_CIPHER *cipher, const char *from, + const char *to, void *x) { + if (cipher) { + *((int *)x) += strlen(EVP_CIPHER_name(cipher)) + 1; + } +} + +static void cb_cipher_names(const EVP_CIPHER *cipher, const char *from, + const char *to, void *x) { + if (cipher) { + if (strlen((char *)x) > 0) { + strcat((char *)x, ":"); + } + strcat((char *)x, EVP_CIPHER_name(cipher)); + } +} + +static char *get_cipher_names(void) { + char *ret = NULL; + int len = 0; + EVP_CIPHER_do_all_sorted(cb_cipher_names_len, &len); + if (!(ret = OPENSSL_zalloc(len))) { + return NULL; + } + EVP_CIPHER_do_all_sorted(cb_cipher_names, ret); + return ret; +} + +static void _OPENSSL_free(void *addr) { + OPENSSL_free(addr); +} */ import "C" @@ -10,159 +44,13 @@ import ( "errors" "unsafe" "runtime" + "strings" ) -/* generated by `gmssl list -cipher-algorithms | sort -f | uniq -i` */ func GetCipherNames() []string { - return []string{ - "AES-128-CBC", - "AES-128-CBC-HMAC-SHA1", - "AES-128-CBC-HMAC-SHA256", - "AES-128-CFB", - "AES-128-CFB1", - "AES-128-CFB8", - "AES-128-CTR", - "AES-128-ECB", - "AES-128-OCB", - "AES-128-OFB", - "AES-128-XTS", - "AES-192-CBC", - "AES-192-CFB", - "AES-192-CFB1", - "AES-192-CFB8", - "AES-192-CTR", - "AES-192-ECB", - "AES-192-OCB", - "AES-192-OFB", - "AES-256-CBC", - "AES-256-CBC-HMAC-SHA1", - "AES-256-CBC-HMAC-SHA256", - "AES-256-CFB", - "AES-256-CFB1", - "AES-256-CFB8", - "AES-256-CTR", - "AES-256-ECB", - "AES-256-OCB", - "AES-256-OFB", - "AES-256-XTS", - "AES128", - "aes128-wrap", - "AES192", - "aes192-wrap", - "AES256", - "aes256-wrap", - "BF", - "BF-CBC", - "BF-CFB", - "BF-ECB", - "BF-OFB", - "blowfish", - "CAMELLIA-128-CBC", - "CAMELLIA-128-CFB", - "CAMELLIA-128-CFB1", - "CAMELLIA-128-CFB8", - "CAMELLIA-128-CTR", - "CAMELLIA-128-ECB", - "CAMELLIA-128-OFB", - "CAMELLIA-192-CBC", - "CAMELLIA-192-CFB", - "CAMELLIA-192-CFB1", - "CAMELLIA-192-CFB8", - "CAMELLIA-192-CTR", - "CAMELLIA-192-ECB", - "CAMELLIA-192-OFB", - "CAMELLIA-256-CBC", - "CAMELLIA-256-CFB", - "CAMELLIA-256-CFB1", - "CAMELLIA-256-CFB8", - "CAMELLIA-256-CTR", - "CAMELLIA-256-ECB", - "CAMELLIA-256-OFB", - "CAMELLIA128", - "CAMELLIA192", - "CAMELLIA256", - "CAST", - "CAST-cbc", - "CAST5-CBC", - "CAST5-CFB", - "CAST5-ECB", - "CAST5-OFB", - "ChaCha20", - "ChaCha20-Poly1305", - "DES", - "DES-CBC", - "DES-CFB", - "DES-CFB1", - "DES-CFB8", - "DES-ECB", - "DES-EDE", - "DES-EDE-CBC", - "DES-EDE-CFB", - "DES-EDE-ECB", - "DES-EDE-OFB", - "DES-EDE3", - "DES-EDE3-CBC", - "DES-EDE3-CFB", - "DES-EDE3-CFB1", - "DES-EDE3-CFB8", - "DES-EDE3-ECB", - "DES-EDE3-OFB", - "DES-OFB", - "DES3", - "des3-wrap", - "DESX", - "DESX-CBC", - "id-aes128-CCM", - "id-aes128-GCM", - "id-aes128-wrap", - "id-aes128-wrap-pad", - "id-aes192-CCM", - "id-aes192-GCM", - "id-aes192-wrap", - "id-aes192-wrap-pad", - "id-aes256-CCM", - "id-aes256-GCM", - "id-aes256-wrap", - "id-aes256-wrap-pad", - "id-smime-alg-CMS3DESwrap", - "IDEA", - "IDEA-CBC", - "IDEA-CFB", - "IDEA-ECB", - "IDEA-OFB", - "RC2", - "rc2-128", - "rc2-40", - "RC2-40-CBC", - "rc2-64", - "RC2-64-CBC", - "RC2-CBC", - "RC2-CFB", - "RC2-ECB", - "RC2-OFB", - "RC4", - "RC4-40", - "RC4-HMAC-MD5", - "SEED", - "SEED-CBC", - "SEED-CFB", - "SEED-ECB", - "SEED-OFB", - "SMS4", - "SMS4-CBC", - "SMS4-CCM", - "SMS4-CFB", - "SMS4-CFB1", - "SMS4-CFB8", - "SMS4-CTR", - "SMS4-ECB", - "SMS4-GCM", - "SMS4-OCB", - "SMS4-OFB", - "SMS4-WRAP", - "SMS4-WRAP-PAD", - "SMS4-XTS", - } + cnames := C.get_cipher_names() + defer C._OPENSSL_free(unsafe.Pointer(cnames)) + return strings.Split(C.GoString(cnames), ":") } func GetCipherKeyLength(name string) (int, error) { diff --git a/go/gmssl/digest.go b/go/gmssl/digest.go index 0cd7f852..7a440263 100644 --- a/go/gmssl/digest.go +++ b/go/gmssl/digest.go @@ -3,39 +3,55 @@ package gmssl /* +#include #include +#include + +static void cb_digest_names_len(const EVP_MD *md, const char *from, + const char *to, + void *x) { + if (md) { + *((int *)x) += strlen(EVP_MD_name(md)) + 1; + } +} + +static void cb_digest_names(const EVP_MD *md, const char *from, + const char *to, void *x) { + if (md) { + if (strlen((char *)x) > 0) { + strcat((char *)x, ":"); + } + strcat((char *)x, EVP_MD_name(md)); + } +} + +static char *get_digest_names() { + char *ret = NULL; + int len = 0; + EVP_MD_do_all_sorted(cb_digest_names_len, &len); + if (!(ret = OPENSSL_zalloc(len))) { + return NULL; + } + EVP_MD_do_all_sorted(cb_digest_names, ret); + return ret; +} + +static void _OPENSSL_free(void *addr) { + OPENSSL_free(addr); +} */ import "C" import ( "unsafe" "runtime" + "strings" ) func GetDigestNames() []string { - return []string{ - "BLAKE2b512", - "BLAKE2s256", - "MD4", - "MD5", - "MD5-SHA1", - "MDC2", - "RIPEMD160", - "rmd160", - "SHA1", - "SHA224", - "SHA256", - "SHA384", - "SHA512", - "SM3", - "SHA1", - "SHA224", - "SHA256", - "SHA384", - "SHA512", - "SM3", - "whirlpool", - } + cnames := C.get_digest_names() + defer C._OPENSSL_free(unsafe.Pointer(cnames)) + return strings.Split(C.GoString(cnames), ":") } func GetDigestLength(name string) (int, error) { @@ -87,9 +103,6 @@ func (ctx *DigestContext) Update(data []byte) error { return nil } - - - func (ctx *DigestContext) Final() ([]byte, error) { outbuf := make([]byte, 64) outlen := C.uint(len(outbuf)) diff --git a/go/gmssl/engine.go b/go/gmssl/engine.go index 0f647c24..c6b812dc 100644 --- a/go/gmssl/engine.go +++ b/go/gmssl/engine.go @@ -10,7 +10,7 @@ package gmssl #include #include -char *get_errors() { +static char *get_errors() { char *ret; BIO *bio; char *data; @@ -25,11 +25,11 @@ char *get_errors() { return ret; } -EVP_PKEY *load_public_key(ENGINE *e, const char *id, char *pass) { +static EVP_PKEY *load_public_key(ENGINE *e, const char *id, char *pass) { return ENGINE_load_public_key(e, id, NULL, pass); } -EVP_PKEY *load_private_key(ENGINE *e, const char *id, char *pass) { +static EVP_PKEY *load_private_key(ENGINE *e, const char *id, char *pass) { return ENGINE_load_private_key(e, id, NULL, pass); } diff --git a/go/gmssl/error.go b/go/gmssl/error.go index 970f9b0c..0fcdeb38 100644 --- a/go/gmssl/error.go +++ b/go/gmssl/error.go @@ -19,14 +19,14 @@ import ( func GetErrors() error { bio := C.BIO_new(C.BIO_s_mem()) if bio == nil { - return errors.New("GetErrors function failure") + return errors.New("GetErrors function failure 1") } defer C.BIO_free(bio) C.ERR_print_errors(bio) var p *C.char len := C.bio_get_mem_data(bio, &p) if len <= 0 { - return errors.New("GetErrors function failure") + return errors.New("GetErrors function failure 2") } return errors.New(C.GoString(p)) } diff --git a/go/gmssl/mac.go b/go/gmssl/mac.go index fd0336db..1629db2b 100644 --- a/go/gmssl/mac.go +++ b/go/gmssl/mac.go @@ -13,47 +13,22 @@ import ( "runtime" ) -func GetMacNames(aliases bool) []string { - return []string{ - "HMAC-BLAKE2b512", - "HMAC-BLAKE2s256", - "HMAC-MD4", - "HMAC-MD5", - "HMAC-MD5-SHA1", - "HMAC-MDC2", - "HMAC-RIPEMD160", - "HMAC-rmd160", - "HMAC-SHA1", - "HMAC-SHA224", - "HMAC-SHA256", - "HMAC-SHA384", - "HMAC-SHA512", - "HMAC-SM3", - "HMAC-SHA1", - "HMAC-SHA224", - "HMAC-SHA256", - "HMAC-SHA384", - "HMAC-SHA512", - "HMAC-SM3", - "HMAC-whirlpool", - } -} - -func GetMacKeyLength(name string) (int, error) { - return 0, nil -} - func GetMacLength(name string) (int, error) { - return 0, nil + 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 MACContext struct { +type HMACContext struct { hctx *C.HMAC_CTX } -func NewMACContext(name string, eng *Engine, key []byte) ( - *MACContext, error) { - +func NewHMACContext(name string, eng *Engine, key []byte) ( + *HMACContext, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) md := C.EVP_get_digestbyname(cname) @@ -66,8 +41,8 @@ func NewMACContext(name string, eng *Engine, key []byte) ( return nil, GetErrors() } - ret := &MACContext{ctx} - runtime.SetFinalizer(ret, func(ret *MACContext) { + ret := &HMACContext{ctx} + runtime.SetFinalizer(ret, func(ret *HMACContext) { C.HMAC_CTX_free(ret.hctx) }) @@ -75,11 +50,10 @@ func NewMACContext(name string, eng *Engine, key []byte) ( unsafe.Pointer(&key[0]), C.int(len(key)), md, nil) { return nil, GetErrors() } - return ret, nil } -func (ctx *MACContext) Update(data []byte) error { +func (ctx *HMACContext) Update(data []byte) error { if len(data) == 0 { return nil } @@ -90,7 +64,7 @@ func (ctx *MACContext) Update(data []byte) error { return nil } -func (ctx *MACContext) Final() ([]byte, error) { +func (ctx *HMACContext) Final() ([]byte, error) { outbuf := make([]byte, 64) outlen := C.uint(len(outbuf)) if 1 != C.HMAC_Final(ctx.hctx, diff --git a/go/gmssl/version.go b/go/gmssl/version.go index 88dc29cc..3485845c 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 July 15 2018", + "GmSSL Go API 1.2 Aug 4 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 ca999961..886455de 100644 --- a/go/gmssltest/gmssltest.go +++ b/go/gmssltest/gmssltest.go @@ -28,13 +28,7 @@ func main() { } fmt.Println(""); - fmt.Println("Supported Message Authentication Codes:") - macs := gmssl.GetMacNames() - for _, mac := range macs { - fmt.Println(" " + mac) - } - fmt.Println(""); - + /* sm3 digest */ sm3, err := gmssl.NewDigestContext("SM3", nil) if err != nil { fmt.Println(err) @@ -55,45 +49,92 @@ func main() { } fmt.Printf("sm3(\"abc\") = %x\n", sm3digest) + /* hmac-sm3 */ hmac_sm3, err := gmssl.NewHMACContext("SM3", nil, []byte("this is the key")) if err != nil { - fmt.Println("shit1") + fmt.Println(err) return } if err := hmac_sm3.Update([]byte("hello")); err != nil { - fmt.Println("shit2") + fmt.Println(err) return } if err := hmac_sm3.Update([]byte("world")); err != nil { - fmt.Println("shit3") + fmt.Println(err) return } mactag, err := hmac_sm3.Final() if err != nil { - fmt.Println("shit4") + fmt.Println(err) return } fmt.Printf("hmac-sm3() = %x\n", mactag) - /* - key := []byte("key") - iv := []byte("iv") - sms4, err := gmssl.NewCipherContext("SMS4", nil, key, iv, true) + /* 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 } - ciphertext1, err := sms4.Update([]byte("hello")) + /* 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 } - ciphertext2, err := sms4.Final() + /* 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 } - ciphertext := make([]byte, 0, len(ciphertext1) + len(ciphertext2)) ciphertext = append(ciphertext, ciphertext1...) ciphertext = append(ciphertext, ciphertext2...) - fmt.Printf("%x", ciphertext) - */ + fmt.Printf("sms4(\"hello\") = %x\n", ciphertext) + + /* 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 + } + plaintext := make([]byte, 0, len(plaintext1) + len(plaintext2)) + plaintext = append(plaintext, plaintext1...) + plaintext = append(plaintext, plaintext2...) + fmt.Println(string(plaintext)) + }