From 9b84749e2f93ef75b1128962b7d5457745e87512 Mon Sep 17 00:00:00 2001 From: pcsx22 Date: Sat, 5 Sep 2020 16:59:08 -0700 Subject: [PATCH] Added sign/verify functions that takes digest instead of plain text --- key.go | 43 +++++++++++++++++++++++++++++++++++++++++++ key_test.go | 15 +++++++++++++++ shim.c | 28 ++++++++++++++++++++++++++++ shim.h | 7 +++++++ 4 files changed, 93 insertions(+) diff --git a/key.go b/key.go index 91ea98a7..8e1798ea 100644 --- a/key.go +++ b/key.go @@ -64,6 +64,8 @@ type PublicKey interface { // Verifies the data signature using PKCS1.15 VerifyPKCS1v15(method Method, data, sig []byte) error + VerifyHash([]byte, []byte) error + // MarshalPKIXPublicKeyPEM converts the public key to PEM-encoded PKIX // format MarshalPKIXPublicKeyPEM() (pem_block []byte, err error) @@ -101,6 +103,8 @@ type PrivateKey interface { // MarshalPKCS1PrivateKeyDER converts the private key to DER-encoded PKCS1 // format MarshalPKCS1PrivateKeyDER() (der_block []byte, err error) + + SignHash([]byte) ([]byte, error) } type pKey struct { @@ -117,6 +121,28 @@ func (key *pKey) BaseType() NID { return NID(C.EVP_PKEY_base_id(key.key)) } +func (key *pKey) SignHash(digest []byte) ([]byte, error) { + ctx := C.X_EVP_PKEY_CTX_new(key.key, nil) + defer C.X_EVP_PKEY_CTX_free(ctx) + + if C.X_EVP_PKEY_sign_init(ctx) <= 0 { + return nil, errors.New("Error initializing context") + } + + sig := make([]byte, 72, 72) + var sigblen C.size_t = 72 + + e := C.X_EVP_PKEY_sign(ctx, + ((*C.uchar)(unsafe.Pointer(&sig[0]))), + &sigblen, + (*C.uchar)(unsafe.Pointer(&digest[0])), + C.size_t(len(digest))) + if e <= 0 { + return nil, errors.New("Error signining") + } + return sig[:sigblen], nil +} + func (key *pKey) SignPKCS1v15(method Method, data []byte) ([]byte, error) { ctx := C.X_EVP_MD_CTX_new() @@ -165,6 +191,23 @@ func (key *pKey) SignPKCS1v15(method Method, data []byte) ([]byte, error) { } } +func (key *pKey) VerifyHash(digest, sig []byte) error { + ctx := C.X_EVP_PKEY_CTX_new(key.key, nil) + defer C.X_EVP_PKEY_CTX_free(ctx) + + if C.X_EVP_PKEY_verify_init(ctx) <= 0 { + return errors.New("Error initializing context") + } + if 1 != C.X_EVP_PKEY_verify(ctx, + ((*C.uchar)(unsafe.Pointer(&sig[0]))), + C.size_t(len(sig)), + (*C.uchar)(unsafe.Pointer(&digest[0])), + C.size_t(len(digest))) { + return errors.New("Signing Failed") + } + return 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) diff --git a/key_test.go b/key_test.go index 753e3784..bb1186e0 100644 --- a/key_test.go +++ b/key_test.go @@ -22,6 +22,7 @@ import ( "crypto/x509" "encoding/hex" pem_pkg "encoding/pem" + "fmt" "io/ioutil" "testing" ) @@ -254,6 +255,20 @@ func TestSignEC(t *testing.T) { t.Fatal(err) } }) + + t.Run("sha256WithExternalHash", func(t *testing.T) { + t.Parallel() + h, _ := SHA256(data) + sig, err := key.SignHash(h[:]) + if err != nil { + t.Fatal(err) + } + fmt.Println("Signature: ", sig) + err = key.VerifyHash(h[:], sig) + if err != nil { + t.Fatal(err) + } + }) } func TestSignED25519(t *testing.T) { diff --git a/shim.c b/shim.c index 6e680841..1bc123ad 100644 --- a/shim.c +++ b/shim.c @@ -58,6 +58,17 @@ int X_EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, return EVP_DigestSign(ctx, sigret, siglen, tbs, tbslen); } +int X_EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) { + return EVP_PKEY_sign_init(ctx); +} + +int X_EVP_PKEY_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { + return EVP_PKEY_sign(ctx, sig, siglen, tbs, tbslen); +} + +unsigned long X_ERR_get_error(){ + return ERR_get_error(); +} int X_EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey){ @@ -69,6 +80,15 @@ int X_EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, return EVP_DigestVerify(ctx, sigret, siglen, tbs, tbslen); } +int X_EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) { + return EVP_PKEY_verify_init(ctx); +} + +int X_EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { + return EVP_PKEY_verify(ctx, sig, siglen, tbs, tbslen); +} + + #else const int X_ED25519_SUPPORT = 0; @@ -116,10 +136,18 @@ EVP_MD_CTX* X_EVP_MD_CTX_new() { return EVP_MD_CTX_new(); } +EVP_PKEY_CTX* X_EVP_PKEY_CTX_new(EVP_PKEY *key, ENGINE *e){ + return EVP_PKEY_CTX_new(key, e); +} + void X_EVP_MD_CTX_free(EVP_MD_CTX* ctx) { EVP_MD_CTX_free(ctx); } +void X_EVP_PKEY_CTX_free(EVP_PKEY_CTX* ctx) { + EVP_PKEY_CTX_free(ctx); +} + static int x_bio_create(BIO *b) { BIO_set_shutdown(b, 1); BIO_set_init(b, 1); diff --git a/shim.h b/shim.h index b792822b..c44df1b8 100644 --- a/shim.h +++ b/shim.h @@ -106,6 +106,8 @@ extern const int X_ED25519_SUPPORT; extern int X_EVP_PKEY_ED25519; extern const EVP_MD *X_EVP_get_digestbyname(const char *name); extern EVP_MD_CTX *X_EVP_MD_CTX_new(); +extern EVP_PKEY_CTX* X_EVP_PKEY_CTX_new(EVP_PKEY *key, ENGINE *e); +extern void X_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); extern void X_EVP_MD_CTX_free(EVP_MD_CTX *ctx); extern const EVP_MD *X_EVP_md_null(); extern const EVP_MD *X_EVP_md5(); @@ -135,10 +137,12 @@ extern int X_EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key); extern int X_EVP_PKEY_assign_charp(EVP_PKEY *pkey, int type, char *key); extern int X_EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, EVP_PKEY *pkey); extern int X_EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type); +extern int X_EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); extern int X_EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); extern int X_EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey); extern int X_EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); extern int X_EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen, const unsigned char *tbs, size_t tbslen); +extern int X_EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen); extern int X_EVP_CIPHER_block_size(EVP_CIPHER *c); extern int X_EVP_CIPHER_key_length(EVP_CIPHER *c); extern int X_EVP_CIPHER_iv_length(EVP_CIPHER *c); @@ -150,6 +154,8 @@ extern void X_EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int padding); extern const EVP_CIPHER *X_EVP_CIPHER_CTX_cipher(EVP_CIPHER_CTX *ctx); extern int X_EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx); extern int X_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid); +extern int X_EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); +extern int X_EVP_PKEY_sign(EVP_PKEY_CTX *ctx,unsigned char *sig, size_t *siglen,const unsigned char *tbs, size_t tbslen); /* HMAC methods */ extern size_t X_HMAC_size(const HMAC_CTX *e); @@ -170,3 +176,4 @@ extern int X_X509_set_version(X509 *x, long version); /* PEM methods */ extern int X_PEM_write_bio_PrivateKey_traditional(BIO *bio, EVP_PKEY *key, const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb, void *u); +unsigned long X_ERR_get_error(); \ No newline at end of file