]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Add preliminary ecdsa keys support in DKIM
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 13 Sep 2017 18:37:08 +0000 (19:37 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 13 Sep 2017 18:37:08 +0000 (19:37 +0100)
src/libserver/dkim.c

index a60f0fa94e16c7c538dbf9f91302e6835df03bb2..d98befc14cd4208cfb898198b9296ce52bbff072 100644 (file)
@@ -67,6 +67,11 @@ enum rspamd_sign_type {
        DKIM_SIGN_ECDSASHA512
 };
 
+enum rspamd_dkim_key_type {
+       RSPAMD_DKIM_KEY_RSA = 0,
+       RSPAMD_DKIM_KEY_ECDSA
+};
+
 #define RSPAMD_DKIM_MAX_ARC_IDX 10
 
 #define msg_err_dkim(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
@@ -129,7 +134,11 @@ struct rspamd_dkim_key_s {
        guint keylen;
        gsize decoded_len;
        guint ttl;
-       RSA *key_rsa;
+       union {
+               RSA *key_rsa;
+               EC_KEY *key_ecdsa;
+       } key;
+       enum rspamd_dkim_key_type type;
        BIO *key_bio;
        EVP_PKEY *key_evp;
        ref_entry_t ref;
@@ -1156,7 +1165,7 @@ struct rspamd_dkim_key_cbdata {
 
 static rspamd_dkim_key_t *
 rspamd_dkim_make_key (rspamd_dkim_context_t *ctx, const gchar *keydata,
-               guint keylen, GError **err)
+               guint keylen, enum rspamd_dkim_key_type type, GError **err)
 {
        rspamd_dkim_key_t *key = NULL;
 
@@ -1170,6 +1179,7 @@ rspamd_dkim_make_key (rspamd_dkim_context_t *ctx, const gchar *keydata,
        key->keydata = g_slice_alloc0 (keylen + 1);
        key->decoded_len = keylen;
        key->keylen = keylen;
+       key->type = type;
 
        rspamd_cryptobox_base64_decode (keydata, keylen, key->keydata,
                        &key->decoded_len);
@@ -1198,16 +1208,31 @@ rspamd_dkim_make_key (rspamd_dkim_context_t *ctx, const gchar *keydata,
                return NULL;
        }
 
-       key->key_rsa = EVP_PKEY_get1_RSA (key->key_evp);
+       if (type == RSPAMD_DKIM_KEY_RSA) {
+               key->key.key_rsa = EVP_PKEY_get1_RSA (key->key_evp);
 
-       if (key->key_rsa == NULL) {
-               g_set_error (err,
-                       DKIM_ERROR,
-                       DKIM_SIGERROR_KEYFAIL,
-                       "cannot extract rsa key from evp key");
-               REF_RELEASE (key);
+               if (key->key.key_rsa == NULL) {
+                       g_set_error (err,
+                                       DKIM_ERROR,
+                                       DKIM_SIGERROR_KEYFAIL,
+                                       "cannot extract rsa key from evp key");
+                       REF_RELEASE (key);
 
-               return NULL;
+                       return NULL;
+               }
+       }
+       else {
+               key->key.key_ecdsa = EVP_PKEY_get1_EC_KEY (key->key_evp);
+
+               if (key->key.key_ecdsa == NULL) {
+                       g_set_error (err,
+                                       DKIM_ERROR,
+                                       DKIM_SIGERROR_KEYFAIL,
+                                       "cannot extract ecdsa key from evp key");
+                       REF_RELEASE (key);
+
+                       return NULL;
+               }
        }
 
        return key;
@@ -1223,8 +1248,16 @@ rspamd_dkim_key_free (rspamd_dkim_key_t *key)
        if (key->key_evp) {
                EVP_PKEY_free (key->key_evp);
        }
-       if (key->key_rsa) {
-               RSA_free (key->key_rsa);
+
+       if (key->type == RSPAMD_DKIM_KEY_RSA) {
+               if (key->key.key_rsa) {
+                       RSA_free (key->key.key_rsa);
+               }
+       }
+       else {
+               if (key->key.key_ecdsa) {
+                       EC_KEY_free (key->key.key_ecdsa);
+               }
        }
        if (key->key_bio) {
                BIO_free (key->key_bio);
@@ -1295,7 +1328,8 @@ rspamd_dkim_parse_key (rspamd_dkim_context_t *ctx, const gchar *txt,
                                        *keylen = len;
                                }
 
-                               return rspamd_dkim_make_key (ctx, c, len, err);
+                               return rspamd_dkim_make_key (ctx, c, len,
+                                               RSPAMD_DKIM_KEY_RSA, err);
                        }
                        else {
                                p++;
@@ -2257,17 +2291,32 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx,
        if (ctx->sig_alg == DKIM_SIGN_RSASHA1) {
                nid = NID_sha1;
        }
-       else if (ctx->sig_alg == DKIM_SIGN_RSASHA256) {
+       else if (ctx->sig_alg == DKIM_SIGN_RSASHA256 ||
+                       ctx->sig_alg == DKIM_SIGN_ECDSASHA256) {
                nid = NID_sha256;
        }
+       else if (ctx->sig_alg == DKIM_SIGN_RSASHA512 ||
+                       ctx->sig_alg == DKIM_SIGN_ECDSASHA512) {
+               nid = NID_sha512;
+       }
        else {
                /* Not reached */
                nid = NID_sha1;
        }
 
-       if (RSA_verify (nid, raw_digest, dlen, ctx->b, ctx->blen, key->key_rsa) != 1) {
-               msg_debug_dkim ("rsa verify failed");
-               res = DKIM_REJECT;
+       if (key->type == RSPAMD_DKIM_KEY_RSA) {
+               if (RSA_verify (nid, raw_digest, dlen, ctx->b, ctx->blen,
+                               key->key.key_rsa) != 1) {
+                       msg_debug_dkim ("rsa verify failed");
+                       res = DKIM_REJECT;
+               }
+       }
+       else {
+               if (ECDSA_verify (nid, raw_digest, dlen, ctx->b, ctx->blen,
+                               key->key.key_ecdsa) != 1) {
+                       msg_debug_dkim ("ecdsa verify failed");
+                       res = DKIM_REJECT;
+               }
        }
 
        if (ctx->common.type == RSPAMD_DKIM_ARC_SEAL && res == DKIM_CONTINUE) {