diff --git a/key.go b/key.go index ed721dd..d8be548 100644 --- a/key.go +++ b/key.go @@ -370,3 +370,60 @@ func GenerateRSAKeyWithExponent(bits int, exponent int) (PrivateKey, error) { }) return p, nil } + +// GenerateECKey generates a new elliptic curve private key on the speicified +// curve. +func GenerateECKey(curve EllipticCurve) (PrivateKey, error) { + var rc C.int + + // Create context for parameter generation + paramCtx := C.EVP_PKEY_CTX_new_id(C.EVP_PKEY_EC, nil) + if paramCtx == nil { + return nil, errors.New("failed creating EC parameter generation context") + } + defer C.EVP_PKEY_CTX_free(paramCtx) + + // Intialize the parameter generation + rc = C.EVP_PKEY_paramgen_init(paramCtx) + if rc != 1 { + return nil, errors.New("failed initializing EC parameter generation context") + } + + // Set curve in EC parameter generation context + rc = C.X_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(paramCtx, C.int(curve)) + if rc != 1 { + return nil, errors.New("failed setting curve in EC parameter generation context") + } + + // Create parameter object + var params *C.EVP_PKEY + rc = C.EVP_PKEY_paramgen(paramCtx, ¶ms) + if rc != 1 { + return nil, errors.New("failed creating EC key generation parameters") + } + defer C.EVP_PKEY_free(params) + + // Create context for the key generation + keyCtx := C.EVP_PKEY_CTX_new(params, nil) + if keyCtx == nil { + return nil, errors.New("failed creating EC key generation context") + } + defer C.EVP_PKEY_CTX_free(keyCtx) + + // Generate the key + var privKey *C.EVP_PKEY + rc = C.EVP_PKEY_keygen_init(keyCtx) + if rc != 1 { + return nil, errors.New("failed initializing EC key generation context") + } + rc = C.EVP_PKEY_keygen(keyCtx, &privKey) + if rc != 1 { + return nil, errors.New("failed generating EC private key") + } + + p := &pKey{key: privKey} + runtime.SetFinalizer(p, func(p *pKey) { + C.X_EVP_PKEY_free(p.key) + }) + return p, nil +} diff --git a/key_test.go b/key_test.go index 8baa2c6..73c2dd9 100644 --- a/key_test.go +++ b/key_test.go @@ -158,6 +158,21 @@ func TestGenerate(t *testing.T) { } } +func TestGenerateEC(t *testing.T) { + key, err := GenerateECKey(Prime256v1) + if err != nil { + t.Fatal(err) + } + _, err = key.MarshalPKIXPublicKeyPEM() + if err != nil { + t.Fatal(err) + } + _, err = key.MarshalPKCS1PrivateKeyPEM() + if err != nil { + t.Fatal(err) + } +} + func TestSign(t *testing.T) { key, _ := GenerateRSAKey(1024) data := []byte("the quick brown fox jumps over the lazy dog") diff --git a/shim.c b/shim.c index 8f2685c..8c6a770 100644 --- a/shim.c +++ b/shim.c @@ -634,6 +634,10 @@ const EVP_CIPHER *X_EVP_CIPHER_CTX_cipher(EVP_CIPHER_CTX *ctx) { return EVP_CIPHER_CTX_cipher(ctx); } +int X_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) { + return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); +} + size_t X_HMAC_size(const HMAC_CTX *e) { return HMAC_size(e); } diff --git a/shim.h b/shim.h index 6e46ffc..bbfa7df 100644 --- a/shim.h +++ b/shim.h @@ -27,6 +27,7 @@ #include #include #include +#include #ifndef SSL_MODE_RELEASE_BUFFERS #define SSL_MODE_RELEASE_BUFFERS 0 @@ -139,6 +140,7 @@ extern int X_EVP_CIPHER_CTX_key_length(EVP_CIPHER_CTX *ctx); extern int X_EVP_CIPHER_CTX_iv_length(EVP_CIPHER_CTX *ctx); 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); /* HMAC methods */ extern size_t X_HMAC_size(const HMAC_CTX *e); diff --git a/ssl_test.go b/ssl_test.go index f18f1dd..a743a73 100644 --- a/ssl_test.go +++ b/ssl_test.go @@ -81,6 +81,11 @@ ucCCa4lOGgPtXJ0Qf1c8yq5vh4yqkQjrgUTkr+CFDGR6y4CxmNDQxEMYIajaIiSY qmgvgyRayemfO2zR0CPgC6wSoGBth+xW6g+WA8y0z76ZSaWpFi8lVM4= -----END RSA PRIVATE KEY----- `) + prime256v1KeyBytes = []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIB/XL0zZSsAu+IQF1AI/nRneabb2S126WFlvvhzmYr1KoAoGCCqGSM49 +AwEHoUQDQgAESSFGWwF6W1hoatKGPPorh4+ipyk0FqpiWdiH+4jIiU39qtOeZGSh +1QgSbzfdHxvoYI0FXM+mqE7wec0kIvrrHw== +-----END EC PRIVATE KEY-----`) ) func NetPipe(t testing.TB) (net.Conn, net.Conn) {