/*
* PDKIM - a RFC4871 (DKIM) implementation
*
- * Copyright (C) 2009 - 2015 Tom Kistner <tom@duncanthrax.net>
+ * Copyright (C) 2009 - 2016 Tom Kistner <tom@duncanthrax.net>
+ * Copyright (C) 2016 Jeremy Harris <jgh@exim.org>
*
* http://duncanthrax.net/pdkim/
*
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
+#include "../exim.h"
-#include "../mytypes.h"
-#include "pdkim.h"
-#include "pdkim-rsa.h"
-#include "polarssl/sha1.h"
-#include "polarssl/sha2.h"
-#include "polarssl/rsa.h"
-#include "polarssl/base64.h"
+#ifndef DISABLE_DKIM /* entire file */
+
+#ifndef SUPPORT_TLS
+# error Need SUPPORT_TLS for DKIM
+#endif
+
+#include "crypt_ver.h"
+
+#ifdef RSA_OPENSSL
+# include <openssl/rsa.h>
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#elif defined(RSA_GNUTLS)
+# include <gnutls/gnutls.h>
+# include <gnutls/x509.h>
+# include <gnutls/abstract.h>
+#endif
+
+#ifdef SHA_GNUTLS
+# include <gnutls/crypto.h>
+#elif defined(SHA_POLARSSL)
+# include "polarssl/sha1.h"
+# include "polarssl/sha2.h"
+#endif
+
+#include "pdkim.h"
#define PDKIM_SIGNATURE_VERSION "1"
#define PDKIM_PUB_RECORD_VERSION "DKIM1"
int canon_headers;
int canon_body;
} pdkim_combined_canon_entry;
+
pdkim_combined_canon_entry pdkim_combined_canons[] = {
{ "simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
{ "simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
};
-const char *pdkim_verify_status_str(int status) {
+/* -------------------------------------------------------------------------- */
+
+const char *
+pdkim_verify_status_str(int status)
+{
switch(status) {
case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
default: return "PDKIM_VERIFY_UNKNOWN";
}
}
-const char *pdkim_verify_ext_status_str(int ext_status) {
+
+const char *
+pdkim_verify_ext_status_str(int ext_status)
+{
switch(ext_status) {
case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
- case PDKIM_VERIFY_INVALID_PUBKEY_PARSING: return "PDKIM_VERIFY_INVALID_PUBKEY_PARSING";
+ case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
+ case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
default: return "PDKIM_VERIFY_UNKNOWN";
}
}
/* -------------------------------------------------------------------------- */
/* Print debugging functions */
-#ifdef PDKIM_DEBUG
void
-pdkim_quoteprint(FILE *stream, const char *data, int len, int lf)
+pdkim_quoteprint(const char *data, int len, int lf)
{
int i;
const unsigned char *p = (const unsigned char *)data;
-for (i = 0; i<len; i++)
+for (i = 0; i < len; i++)
{
const int c = p[i];
switch (c)
{
- case ' ' : fprintf(stream, "{SP}"); break;
- case '\t': fprintf(stream, "{TB}"); break;
- case '\r': fprintf(stream, "{CR}"); break;
- case '\n': fprintf(stream, "{LF}"); break;
- case '{' : fprintf(stream, "{BO}"); break;
- case '}' : fprintf(stream, "{BC}"); break;
+ case ' ' : debug_printf("{SP}"); break;
+ case '\t': debug_printf("{TB}"); break;
+ case '\r': debug_printf("{CR}"); break;
+ case '\n': debug_printf("{LF}"); break;
+ case '{' : debug_printf("{BO}"); break;
+ case '}' : debug_printf("{BC}"); break;
default:
if ( (c < 32) || (c > 127) )
- fprintf(stream, "{%02x}", c);
+ debug_printf("{%02x}", c);
else
- fputc(c, stream);
+ debug_printf("%c", c);
break;
}
}
if (lf)
- fputc('\n', stream);
+ debug_printf("\n");
}
void
-pdkim_hexprint(FILE *stream, const char *data, int len, int lf)
+pdkim_hexprint(const char *data, int len, int lf)
{
int i;
const unsigned char *p = (const unsigned char *)data;
-for (i =0 ; i<len; i++)
- {
- const int c = p[i];
- fprintf(stream, "%02x", c);
- }
+for (i = 0 ; i < len; i++)
+ debug_printf("%02x", p[i]);
if (lf)
- fputc('\n', stream);
+ debug_printf("\n");
}
-#endif
-/* -------------------------------------------------------------------------- */
-/* Simple string list implementation for convinience */
-pdkim_stringlist *
-pdkim_append_stringlist(pdkim_stringlist *base, char *str)
+
+/* String package: should be replaced by Exim standard ones */
+
+static pdkim_stringlist *
+pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
{
pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
return new_entry;
}
-pdkim_stringlist *
-pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
-{
-pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
-
-if (!new_entry) return NULL;
-memset(new_entry, 0, sizeof(pdkim_stringlist));
-if (!(new_entry->value = strdup(str))) return NULL;
-if (base)
- new_entry->next = base;
-return new_entry;
-}
-
/* -------------------------------------------------------------------------- */
/* A small "growing string" implementation to escape malloc/realloc hell */
-pdkim_str *
+static pdkim_str *
pdkim_strnew (const char *cstr)
{
unsigned int len = cstr ? strlen(cstr) : 0;
return p;
}
-char *
+static char *
pdkim_strncat(pdkim_str *str, const char *data, int len)
{
if ((str->allocated - str->len) < (len+1))
return str->str;
}
-char *
+static char *
pdkim_strcat(pdkim_str *str, const char *cstr)
{
return pdkim_strncat(str, cstr, strlen(cstr));
}
-char *
-pdkim_numcat(pdkim_str *str, unsigned long num)
-{
-char minibuf[20];
-snprintf(minibuf, 20, "%lu", num);
-return pdkim_strcat(str, minibuf);
-}
-
-char *
+static char *
pdkim_strtrim(pdkim_str *str)
{
char *p = str->str;
return str->str;
}
-char *
+static char *
pdkim_strclear(pdkim_str *str)
{
str->str[0] = '\0';
return str->str;
}
-void
+static void
pdkim_strfree(pdkim_str *str)
{
if (!str) return;
/* -------------------------------------------------------------------------- */
-void
+static void
pdkim_free_pubkey(pdkim_pubkey *pub)
{
if (pub)
if (pub->keytype ) free(pub->keytype);
if (pub->srvtype ) free(pub->srvtype);
if (pub->notes ) free(pub->notes);
- if (pub->key ) free(pub->key);
+/* if (pub->key ) free(pub->key); */
free(pub);
}
}
/* -------------------------------------------------------------------------- */
-void
+static void
pdkim_free_sig(pdkim_signature *sig)
{
if (sig)
free(c);
}
- if (sig->sigdata ) free(sig->sigdata);
- if (sig->bodyhash ) free(sig->bodyhash);
if (sig->selector ) free(sig->selector);
if (sig->domain ) free(sig->domain);
if (sig->identity ) free(sig->identity);
if (sig->rsa_privkey ) free(sig->rsa_privkey);
if (sig->sign_headers ) free(sig->sign_headers);
if (sig->signature_header) free(sig->signature_header);
- if (sig->sha1_body ) free(sig->sha1_body);
- if (sig->sha2_body ) free(sig->sha2_body);
if (sig->pubkey) pdkim_free_pubkey(sig->pubkey);
"start". Returns the position of the header name in
the list. */
-int
+static int
header_name_match(const char *header,
char *tick,
int do_tick)
/* Performs "relaxed" canonicalization of a header. The returned pointer needs
to be free()d. */
-char *
+static char *
pdkim_relax_header (char *header, int crlf)
{
BOOL past_field_name = FALSE;
/* -------------------------------------------------------------------------- */
#define PDKIM_QP_ERROR_DECODE -1
-char *
+static char *
pdkim_decode_qp_char(char *qp_p, int *c)
{
char *initial_pos = qp_p;
{
/* Do hex conversion */
*c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
- *c != isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
+ *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
return qp_p + 2;
}
/* -------------------------------------------------------------------------- */
-char *
+static char *
pdkim_decode_qp(char *str)
{
int nchar = 0;
/* -------------------------------------------------------------------------- */
-char *
+static char *
pdkim_decode_base64(char *str, int *num_decoded)
{
int dlen = 0;
char *res;
+int old_pool = store_pool;
-base64_decode(NULL, &dlen, (unsigned char *)str, strlen(str));
+/* There is a store-reset between header & body reception
+so cannot use the main pool */
-if (!(res = malloc(dlen+1)))
- return NULL;
-if (base64_decode((unsigned char *)res, &dlen, (unsigned char *)str, strlen(str)) != 0)
- {
- free(res);
- return NULL;
- }
+store_pool = POOL_PERM;
+dlen = b64decode(US str, USS &res);
+store_pool = old_pool;
+
+if (dlen < 0) return NULL;
if (num_decoded) *num_decoded = dlen;
return res;
/* -------------------------------------------------------------------------- */
-char *
+static char *
pdkim_encode_base64(char *str, int num)
{
-int dlen = 0;
-char *res;
-
-base64_encode(NULL, &dlen, (unsigned char *)str, num);
+char * ret;
+int old_pool = store_pool;
-if (!(res = malloc(dlen+1)))
- return NULL;
-if (base64_encode((unsigned char *)res, &dlen, (unsigned char *)str, num) != 0)
- {
- free(res);
- return NULL;
- }
-return res;
+store_pool = POOL_PERM;
+ret = CS b64encode(US str, num);
+store_pool = old_pool;
+return ret;
}
#define PDKIM_HDR_TAG 1
#define PDKIM_HDR_VALUE 2
-pdkim_signature *
+static pdkim_signature *
pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr)
{
pdkim_signature *sig ;
{
pdkim_strtrim(cur_val);
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream, " %s=%s\n", cur_tag->str, cur_val->str);
-#endif
+ DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);
switch (cur_tag->str[0])
{
case 'z':
sig->copiedheaders = pdkim_decode_qp(cur_val->str); break;
default:
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream, " Unknown tag encountered\n");
-#endif
+ DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
break;
}
}
while (q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
*q = '\0'; q--; /*XXX questionable code layout; possible bug */
-#ifdef PDKIM_DEBUG
-if (ctx->debug_stream)
+DEBUG(D_acl)
{
- fprintf(ctx->debug_stream,
+ debug_printf(
"PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- pdkim_quoteprint(ctx->debug_stream,
- sig->rawsig_no_b_val,
- strlen(sig->rawsig_no_b_val), 1);
- fprintf(ctx->debug_stream,
+ pdkim_quoteprint(sig->rawsig_no_b_val, strlen(sig->rawsig_no_b_val), 1);
+ debug_printf(
"PDKIM >> Sig size: %4d bits\n", sig->sigdata_len*8);
- fprintf(ctx->debug_stream,
+ debug_printf(
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
}
-#endif
+
+#ifdef SHA_OPENSSL
+
+SHA1_Init (&sig->sha1_body);
+SHA256_Init(&sig->sha2_body);
+
+#elif defined(SHA_GNUTLS)
+
+gnutls_hash_init(&sig->sha_body,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256);
+
+#elif defined(SHA_POLARSSL)
if ( !(sig->sha1_body = malloc(sizeof(sha1_context)))
|| !(sig->sha2_body = malloc(sizeof(sha2_context)))
sha1_starts(sig->sha1_body);
sha2_starts(sig->sha2_body, 0);
+#endif /* SHA impl */
+
return sig;
}
/* -------------------------------------------------------------------------- */
-pdkim_pubkey *
+static pdkim_pubkey *
pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record)
{
pdkim_pubkey *pub;
if (cur_tag->len > 0)
{
pdkim_strtrim(cur_val);
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream, " %s=%s\n", cur_tag->str, cur_val->str);
-#endif
+ DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);
switch (cur_tag->str[0])
{
if (strchr(cur_val->str, 's') != NULL) pub->no_subdomaining = 1;
break;
default:
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream, " Unknown tag encountered\n");
-#endif
+ DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
break;
}
}
/* -------------------------------------------------------------------------- */
-int
+static int
pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
{
pdkim_signature *sig = ctx->sig;
if (canon_len > 0)
{
+#ifdef SHA_GNUTLS
+ gnutls_hash(sig->sha_body, canon_data, canon_len);
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_update(sig->sha1_body, (unsigned char *)canon_data, canon_len);
+# ifdef SHA_OPENSSL
+ SHA1_Update (&sig->sha1_body, canon_data, canon_len);
else
- sha2_update(sig->sha2_body, (unsigned char *)canon_data, canon_len);
+ SHA256_Update(&sig->sha2_body, canon_data, canon_len);
+# elif defined(SHA_POLARSSL)
+ sha1_update(sig->sha1_body, US canon_data, canon_len);
+ else
+ sha2_update(sig->sha2_body, US canon_data, canon_len);
+# endif
+#endif
sig->signed_body_bytes += canon_len;
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- pdkim_quoteprint(ctx->debug_stream, canon_data, canon_len, 1);
-#endif
+ DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len, 1);
}
sig = sig->next;
/* -------------------------------------------------------------------------- */
-int
+static int
pdkim_finish_bodyhash(pdkim_ctx *ctx)
{
-pdkim_signature *sig = ctx->sig;
+pdkim_signature *sig;
/* Traverse all signatures */
-while (sig)
+for (sig = ctx->sig; sig; sig = sig->next)
{ /* Finish hashes */
- unsigned char bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
+ uschar bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
+#ifdef SHA_GNUTLS
+ gnutls_hash_output(sig->sha_body, bh);
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
+# ifdef SHA_OPENSSL
+ SHA1_Final (bh, &sig->sha1_body);
+ else
+ SHA256_Final(bh, &sig->sha2_body);
+# elif defined(SHA_POLARSSL)
sha1_finish(sig->sha1_body, bh);
else
sha2_finish(sig->sha2_body, bh);
+# endif
+#endif
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
+ DEBUG(D_acl)
{
- fprintf(ctx->debug_stream, "PDKIM [%s] Body bytes hashed: %lu\n",
- sig->domain, sig->signed_body_bytes);
- fprintf(ctx->debug_stream, "PDKIM [%s] bh computed: ", sig->domain);
- pdkim_hexprint(ctx->debug_stream, (char *)bh,
- (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32, 1);
+ debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
+ "PDKIM [%s] bh computed: ",
+ sig->domain, sig->signed_body_bytes, sig->domain);
+ pdkim_hexprint((char *)bh, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32, 1);
}
-#endif
/* SIGNING -------------------------------------------------------------- */
if (ctx->mode == PDKIM_MODE_SIGN)
{
- sig->bodyhash_len = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
-
- if (!(sig->bodyhash = malloc(sig->bodyhash_len)))
- return PDKIM_ERR_OOM;
- memcpy(sig->bodyhash, bh, sig->bodyhash_len);
+ sig->bodyhash_len = sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20:32;
+ sig->bodyhash = CS string_copyn(US bh, sig->bodyhash_len);
/* If bodylength limit is set, and we have received less bytes
than the requested amount, effectively remove the limit tag. */
if (memcmp(bh, sig->bodyhash,
(sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32) == 0)
{
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream, "PDKIM [%s] Body hash verified OK\n",
- sig->domain);
-#endif
+ DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
}
else
{
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
+ DEBUG(D_acl)
{
- fprintf(ctx->debug_stream, "PDKIM [%s] bh signature: ", sig->domain);
- pdkim_hexprint(ctx->debug_stream, sig->bodyhash,
- (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32, 1);
- fprintf(ctx->debug_stream, "PDKIM [%s] Body hash did NOT verify\n",
- sig->domain);
+ debug_printf("PDKIM [%s] bh signature: ", sig->domain);
+ pdkim_hexprint(sig->bodyhash,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32, 1);
+ debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
}
-#endif
sig->verify_status = PDKIM_VERIFY_FAIL;
sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
}
}
-
- sig = sig->next;
}
return PDKIM_OK;
/* -------------------------------------------------------------------------- */
/* Callback from pdkim_feed below for processing complete body lines */
-int
+static int
pdkim_bodyline_complete(pdkim_ctx *ctx)
{
char *p = ctx->linebuf;
if (ctx->seen_eod) goto BAIL;
/* We've always got one extra byte to stuff a zero ... */
-ctx->linebuf[(ctx->linebuf_offset)] = '\0';
+ctx->linebuf[ctx->linebuf_offset] = '\0';
-if (ctx->input_mode == PDKIM_INPUT_SMTP)
+/* Terminate on EOD marker */
+if (memcmp(p, ".\r\n", 3) == 0)
{
- /* Terminate on EOD marker */
- if (memcmp(p, ".\r\n", 3) == 0)
- {
- /* In simple body mode, if any empty lines were buffered,
- replace with one. rfc 4871 3.4.3 */
- if ( sig && sig->canon_body == PDKIM_CANON_SIMPLE
- && sig->signed_body_bytes == 0
- && ctx->num_buffered_crlf > 0
- )
- pdkim_update_bodyhash(ctx, "\r\n", 2);
+ /* In simple body mode, if any empty lines were buffered,
+ replace with one. rfc 4871 3.4.3 */
+ /*XXX checking the signed-body-bytes is a gross hack; I think
+ it indicates that all linebreaks should be buffered, including
+ the one terminating a text line */
+ if ( sig && sig->canon_body == PDKIM_CANON_SIMPLE
+ && sig->signed_body_bytes == 0
+ && ctx->num_buffered_crlf > 0
+ )
+ pdkim_update_bodyhash(ctx, "\r\n", 2);
- ctx->seen_eod = 1;
- goto BAIL;
- }
- /* Unstuff dots */
- if (memcmp(p, "..", 2) == 0)
- {
- p++;
- n--;
- }
+ ctx->seen_eod = TRUE;
+ goto BAIL;
+ }
+/* Unstuff dots */
+if (memcmp(p, "..", 2) == 0)
+ {
+ p++;
+ n--;
}
/* Empty lines need to be buffered until we find a non-empty line */
/* Callback from pdkim_feed below for processing complete headers */
#define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
-int
+static int
pdkim_header_complete(pdkim_ctx *ctx)
{
-pdkim_signature *sig = ctx->sig;
-
/* Special case: The last header can have an extra \r appended */
if ( (ctx->cur_header->len > 1) &&
(ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') )
/* SIGNING -------------------------------------------------------------- */
if (ctx->mode == PDKIM_MODE_SIGN)
- for ( ; sig; sig = sig->next) /* Traverse all signatures */
+ {
+ pdkim_signature *sig;
+
+ for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
if (header_name_match(ctx->cur_header->str,
sig->sign_headers?
sig->sign_headers:
return PDKIM_ERR_OOM;
sig->headers = list;
}
+ }
+/* VERIFICATION ----------------------------------------------------------- */
/* DKIM-Signature: headers are added to the verification list */
if (ctx->mode == PDKIM_MODE_VERIFY)
{
pdkim_signature *new_sig;
/* Create and chain new signature block */
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream,
+ DEBUG(D_acl) debug_printf(
"PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-#endif
if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str)))
{
last_sig->next = new_sig;
}
}
-#ifdef PDKIM_DEBUG
else
- if (ctx->debug_stream)
- {
- fprintf(ctx->debug_stream, "Error while parsing signature header\n");
- fprintf(ctx->debug_stream,
+ DEBUG(D_acl) debug_printf(
+ "Error while parsing signature header\n"
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
- }
-#endif
}
/* every other header is stored for signature verification */
if (ctx->past_headers)
{
/* Processing body byte */
- ctx->linebuf[(ctx->linebuf_offset)++] = c;
+ ctx->linebuf[ctx->linebuf_offset++] = c;
if (c == '\n')
{
int rc = pdkim_bodyline_complete(ctx); /* End of line */
int rc = pdkim_header_complete(ctx); /* Seen last header line */
if (rc != PDKIM_OK) return rc;
- ctx->past_headers = 1;
+ ctx->past_headers = TRUE;
ctx->seen_lf = 0;
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream,
+ DEBUG(D_acl) debug_printf(
"PDKIM >> Hashed body data, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-#endif
continue;
}
else
- ctx->seen_lf = 1;
+ ctx->seen_lf = TRUE;
}
else if (ctx->seen_lf)
{
int rc = pdkim_header_complete(ctx); /* End of header */
if (rc != PDKIM_OK) return rc;
}
- ctx->seen_lf = 0;
+ ctx->seen_lf = FALSE;
}
}
* "pad"
*
* no guarantees are made for output given out-of range input. like tag
- * names loinger than 78, or bogus col. Input is assumed to be free of line breaks.
+ * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
*/
static char *
/* -------------------------------------------------------------------------- */
-char *
+static char *
pdkim_create_header(pdkim_signature *sig, int final)
{
char *rc = NULL;
BAIL:
pdkim_strfree(hdr);
if (canon_all) pdkim_strfree(canon_all);
-if (base64_bh) free(base64_bh);
-if (base64_b ) free(base64_b);
return rc;
}
pdkim_update_bodyhash(ctx, "\r\n", 2);
}
else
- {
- /* For non-smtp input, check if there's an unfinished line in the
- body line buffer. If that is the case, we must add a CRLF to the
- hash to properly terminate the message. */
- if ((ctx->input_mode == PDKIM_INPUT_NORMAL) && ctx->linebuf_offset)
- {
- pdkim_update_bodyhash(ctx, ctx->linebuf, ctx->linebuf_offset);
- pdkim_update_bodyhash(ctx, "\r\n", 2);
- }
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream,
+ DEBUG(D_acl) debug_printf(
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
-#endif
- }
/* Build (and/or evaluate) body hash */
if (pdkim_finish_bodyhash(ctx) != PDKIM_OK)
while (sig)
{
+#ifdef SHA_OPENSSL
+ SHA_CTX sha1_headers;
+ SHA256_CTX sha2_headers;
+#elif defined(SHA_GNUTLS)
+ gnutls_hash_hd_t sha_headers;
+#elif defined(SHA_POLARSSL)
sha1_context sha1_headers;
sha2_context sha2_headers;
+#endif
+
char *sig_hdr;
char headerhash[32];
+#ifdef RSA_GNUTLS
+ uschar * hdata = NULL;
+ int hdata_alloc = 0;
+ int hdata_size = 0;
+#endif
+
+#ifdef SHA_GNUTLS
+ gnutls_hash_init(&sha_headers,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256);
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
+# ifdef SHA_OPENSSL
+ SHA1_Init(&sha1_headers);
+ else
+ SHA256_Init(&sha2_headers);
+# elif defined(SHA_POLARSSL)
sha1_starts(&sha1_headers);
else
sha2_starts(&sha2_headers, 0);
-
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream,
- "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
+# endif
#endif
+ DEBUG(D_acl) debug_printf(
+ "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
+
/* SIGNING ---------------------------------------------------------------- */
/* When signing, walk through our header list and add them to the hash. As we
go, construct a list of the header's names to use for the h= parameter. */
return PDKIM_ERR_OOM;
/* Feed header to the hash algorithm */
+#ifdef SHA_GNUTLS
+ gnutls_hash(sha_headers, rh, strlen(rh));
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_update(&(sha1_headers), (unsigned char *)rh, strlen(rh));
+# ifdef SHA_OPENSSL
+ SHA1_Update (&sha1_headers, rh, strlen(rh));
+ else
+ SHA256_Update(&sha2_headers, rh, strlen(rh));
+# elif defined(SHA_POLARSSL)
+ sha1_update(&sha1_headers, US rh, strlen(rh));
else
- sha2_update(&(sha2_headers), (unsigned char *)rh, strlen(rh));
+ sha2_update(&sha2_headers, US rh, strlen(rh));
+# endif
+#endif
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
+#ifdef RSA_GNUTLS
+ /* Remember headers block for signing */
+ hdata = string_append(hdata, &hdata_alloc, &hdata_size, 1, rh);
#endif
+
+ DEBUG(D_acl) pdkim_quoteprint(rh, strlen(rh), 1);
free(rh);
}
}
return PDKIM_ERR_OOM;
/* Feed header to the hash algorithm */
+#ifdef SHA_GNUTLS
+ gnutls_hash(sha_headers, rh, strlen(rh));
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_update(&sha1_headers, (unsigned char *)rh, strlen(rh));
+# ifdef SHA_OPENSSL
+ SHA1_Update (&sha1_headers, rh, strlen(rh));
else
- sha2_update(&sha2_headers, (unsigned char *)rh, strlen(rh));
-
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
+ SHA256_Update(&sha2_headers, rh, strlen(rh));
+# elif defined(SHA_POLARSSL)
+ sha1_update(&sha1_headers, US rh, strlen(rh));
+ else
+ sha2_update(&sha2_headers, US rh, strlen(rh));
+# endif
#endif
+
+ DEBUG(D_acl) pdkim_quoteprint(rh, strlen(rh), 1);
free(rh);
hdrs->tag = 1;
break;
free(b);
}
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream,
+ DEBUG(D_acl) debug_printf(
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
-#endif
/* SIGNING ---------------------------------------------------------------- */
if (ctx->mode == PDKIM_MODE_SIGN)
sig_hdr = relaxed_hdr;
}
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
+ DEBUG(D_acl)
{
- fprintf(ctx->debug_stream,
+ debug_printf(
"PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
- pdkim_quoteprint(ctx->debug_stream, sig_hdr, strlen(sig_hdr), 1);
- fprintf(ctx->debug_stream,
+ pdkim_quoteprint(sig_hdr, strlen(sig_hdr), 1);
+ debug_printf(
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
}
-#endif
/* Finalize header hash */
+#ifdef SHA_GNUTLS
+ gnutls_hash(sha_headers, sig_hdr, strlen(sig_hdr));
+ gnutls_hash_output(sha_headers, headerhash);
+#else
if (sig->algo == PDKIM_ALGO_RSA_SHA1)
+# ifdef SHA_OPENSSL
{
- sha1_update(&sha1_headers, (unsigned char *)sig_hdr, strlen(sig_hdr));
- sha1_finish(&sha1_headers, (unsigned char *)headerhash);
-
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- {
- fprintf(ctx->debug_stream, "PDKIM [%s] hh computed: ", sig->domain);
- pdkim_hexprint(ctx->debug_stream, headerhash, 20, 1);
- }
-#endif
+ SHA1_Update(&sha1_headers, sig_hdr, strlen(sig_hdr));
+ SHA1_Final(US headerhash, &sha1_headers);
}
else
{
- sha2_update(&sha2_headers, (unsigned char *)sig_hdr, strlen(sig_hdr));
- sha2_finish(&sha2_headers, (unsigned char *)headerhash);
-
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- {
- fprintf(ctx->debug_stream, "PDKIM [%s] hh computed: ", sig->domain);
- pdkim_hexprint(ctx->debug_stream, headerhash, 32, 1);
- }
+ SHA256_Update(&sha2_headers, sig_hdr, strlen(sig_hdr));
+ SHA256_Final(US headerhash, &sha2_headers);
+ }
+# elif defined(SHA_POLARSSL)
+ {
+ sha1_update(&sha1_headers, US sig_hdr, strlen(sig_hdr));
+ sha1_finish(&sha1_headers, US headerhash);
+ }
+ else
+ {
+ sha2_update(&sha2_headers, US sig_hdr, strlen(sig_hdr));
+ sha2_finish(&sha2_headers, US headerhash);
+ }
+# endif
#endif
+
+ DEBUG(D_acl)
+ {
+ debug_printf("PDKIM [%s] hh computed: ", sig->domain);
+ pdkim_hexprint(headerhash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20:32, 1);
}
+#ifdef RSA_GNUTLS
+ if (ctx->mode == PDKIM_MODE_SIGN)
+ hdata = string_append(hdata, &hdata_alloc, &hdata_size, 1, sig_hdr);
+#endif
+
free(sig_hdr);
/* SIGNING ---------------------------------------------------------------- */
if (ctx->mode == PDKIM_MODE_SIGN)
{
- rsa_context rsa;
+#ifdef RSA_OPENSSL
+ RSA * rsa;
+ uschar * p, * q;
+ int len;
+#elif defined(RSA_GNUTLS)
+ gnutls_x509_privkey_t rsa;
+ gnutls_datum_t k;
+ int rc;
+ size_t sigsize;
+#endif
- rsa_init(&rsa, RSA_PKCS_V15, 0);
+ /* Import private key */
+#ifdef RSA_OPENSSL
- /* Perform private key operation */
- if (rsa_parse_key(&rsa, (unsigned char *)sig->rsa_privkey,
- strlen(sig->rsa_privkey), NULL, 0) != 0)
+ if ( !(p = Ustrstr(sig->rsa_privkey, "-----BEGIN RSA PRIVATE KEY-----"))
+ || !(q = Ustrstr(p+=31, "-----END RSA PRIVATE KEY-----"))
+ )
+ return PDKIM_SIGN_PRIVKEY_WRAP;
+ *q = '\0';
+ if ((len = b64decode(p, &p)) < 0)
+ {
+ DEBUG(D_acl) debug_printf("b64decode failed\n");
+ return PDKIM_SIGN_PRIVKEY_B64D;
+ }
+ if (!(rsa = d2i_RSAPrivateKey(NULL, CUSS &p, len)))
+ {
+ DEBUG(D_acl)
+ {
+ char ssl_errstring[256];
+ ERR_error_string(ERR_get_error(), ssl_errstring);
+ debug_printf("d2i_RSAPrivateKey: %s\n", ssl_errstring);
+ }
return PDKIM_ERR_RSA_PRIVKEY;
+ }
- sig->sigdata_len = mpi_size(&(rsa.N));
- if (!(sig->sigdata = malloc(sig->sigdata_len)))
- return PDKIM_ERR_OOM;
+#elif defined(RSA_GNUTLS)
- if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
- ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
- SIG_RSA_SHA1:SIG_RSA_SHA256),
- 0,
- (unsigned char *)headerhash,
- (unsigned char *)sig->sigdata ) != 0)
+ k.data = sig->rsa_privkey;
+ k.size = strlen(sig->rsa_privkey);
+ if ( (rc = gnutls_x509_privkey_init(&rsa)) != GNUTLS_E_SUCCESS
+ || (rc = gnutls_x509_privkey_import2(rsa, &k,
+ GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS_PLAIN)) != GNUTLS_E_SUCCESS
+ )
+ {
+ DEBUG(D_acl) debug_printf("gnutls_x509_privkey_import2: %s\n",
+ gnutls_strerror(rc));
+ return PDKIM_ERR_RSA_PRIVKEY;
+ }
+
+#endif
+
+
+ /* Allocate mem for signature */
+#ifdef RSA_OPENSSL
+ sig->sigdata = store_get(RSA_size(rsa));
+#elif defined(RSA_GNUTLS)
+ k.data = hdata;
+ k.size = hdata_size;
+ (void) gnutls_x509_privkey_sign_data(rsa,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256,
+ 0, &k, NULL, &sigsize);
+ sig->sigdata = store_get(sig->sigdata_len = sigsize);
+#endif
+
+ /* Do signing */
+#ifdef RSA_OPENSSL
+
+ if (RSA_sign(sig->algo == PDKIM_ALGO_RSA_SHA1 ? NID_sha1 : NID_sha256,
+ CUS headerhash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32,
+ US sig->sigdata, (unsigned int *)&sig->sigdata_len,
+ rsa) != 1)
return PDKIM_ERR_RSA_SIGNING;
+ RSA_free(rsa);
- rsa_free(&rsa);
+#elif defined(RSA_GNUTLS)
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
+ if ((rc = gnutls_x509_privkey_sign_data(rsa,
+ sig->algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256,
+ 0, &k, sig->sigdata, &sigsize)) != GNUTLS_E_SUCCESS
+ )
{
- fprintf(ctx->debug_stream, "PDKIM [%s] b computed: ", sig->domain);
- pdkim_hexprint(ctx->debug_stream, sig->sigdata, sig->sigdata_len, 1);
+ DEBUG(D_acl) debug_printf("gnutls_x509_privkey_sign_data: %s\n",
+ gnutls_strerror(rc));
+ return PDKIM_ERR_RSA_SIGNING;
}
+ gnutls_x509_privkey_deinit(rsa);
+
#endif
+
+ DEBUG(D_acl)
+ {
+ debug_printf( "PDKIM [%s] b computed: ", sig->domain);
+ pdkim_hexprint(sig->sigdata, sig->sigdata_len, 1);
+ }
+
if (!(sig->signature_header = pdkim_create_header(ctx->sig, 1)))
return PDKIM_ERR_OOM;
}
/* VERIFICATION ----------------------------------------------------------- */
else
{
- rsa_context rsa;
+#ifdef RSA_OPENSSL
+ RSA * rsa;
+ const unsigned char * p;
+#elif defined(RSA_GNUTLS)
+ gnutls_pubkey_t rsa;
+ gnutls_datum_t k, s;
+ int rc;
+#endif
char *dns_txt_name, *dns_txt_reply;
- rsa_init(&rsa, RSA_PKCS_V15, 0);
+#ifdef RSA_GNUTLS
+ gnutls_pubkey_init(&rsa);
+#endif
+
+ /* Fetch public key for signing domain, from DNS */
if (!(dns_txt_name = malloc(PDKIM_DNS_TXT_MAX_NAMELEN)))
return PDKIM_ERR_OOM;
goto NEXT_VERIFY;
}
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
+ DEBUG(D_acl)
{
- fprintf(ctx->debug_stream,
- "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- fprintf(ctx->debug_stream, " Raw record: ");
- pdkim_quoteprint(ctx->debug_stream, dns_txt_reply, strlen(dns_txt_reply), 1);
+ debug_printf(
+ "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
+ " Raw record: ");
+ pdkim_quoteprint(dns_txt_reply, strlen(dns_txt_reply), 1);
}
-#endif
if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx, dns_txt_reply)))
{
sig->verify_status = PDKIM_VERIFY_INVALID;
- sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
+ sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- {
- fprintf(ctx->debug_stream, " Error while parsing public key record\n");
- fprintf(ctx->debug_stream,
+ DEBUG(D_acl) debug_printf(
+ " Error while parsing public key record\n"
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
- }
-#endif
goto NEXT_VERIFY;
}
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream,
+ DEBUG(D_acl) debug_printf(
"PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
-#endif
- if (rsa_parse_public_key(&rsa,
- (unsigned char *)sig->pubkey->key,
- sig->pubkey->key_len) != 0)
+ /* Import public key */
+#ifdef RSA_OPENSSL
+
+ p = CUS sig->pubkey->key;
+ if (!(rsa = d2i_RSA_PUBKEY(NULL, &p, (long) sig->pubkey->key_len)))
+
+#elif defined(RSA_GNUTLS)
+
+ k.data = sig->pubkey->key;
+ k.size = sig->pubkey->key_len;
+ if ((rc = gnutls_pubkey_import(rsa, &k, GNUTLS_X509_FMT_DER))
+ != GNUTLS_E_SUCCESS)
+
+#endif
{
+ DEBUG(D_acl)
+ {
+#ifdef RSA_OPENSSL
+ long e;
+ ERR_load_crypto_strings(); /*XXX move to a startup routine */
+ while ((e = ERR_get_error()))
+ debug_printf("Az: %.120s\n", ERR_error_string(e, NULL));
+#elif defined(RSA_GNUTLS)
+ debug_printf("gnutls_pubkey_import: %s\n", gnutls_strerror(rc));
+#endif
+ }
+
sig->verify_status = PDKIM_VERIFY_INVALID;
- sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
+ sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
goto NEXT_VERIFY;
}
/* Check the signature */
- if (rsa_pkcs1_verify(&rsa,
- RSA_PUBLIC,
- ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
- SIG_RSA_SHA1:SIG_RSA_SHA256),
- 0,
- (unsigned char *)headerhash,
- (unsigned char *)sig->sigdata) != 0)
+#ifdef RSA_OPENSSL
+
+ if (RSA_verify(sig->algo == PDKIM_ALGO_RSA_SHA1 ? NID_sha1 : NID_sha256,
+ CUS headerhash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32,
+ US sig->sigdata, (unsigned int)sig->sigdata_len,
+ rsa) != 1)
+
+#elif defined(RSA_GNUTLS)
+
+ k.data = headerhash;
+ k.size = sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32;
+ s.data = sig->sigdata;
+ s.size = sig->sigdata_len;
+ if ((rc = gnutls_pubkey_verify_hash2(rsa,
+ sig->algo == PDKIM_ALGO_RSA_SHA1
+ ? GNUTLS_SIGN_RSA_SHA1 : GNUTLS_SIGN_RSA_SHA256,
+ 0, &k, &s)) < 0)
+
+#endif
{
+#if defined(RSA_GNUTLS)
+ debug_printf("gnutls_pubkey_verify_hash2: %s\n", gnutls_strerror(rc));
+#endif
sig->verify_status = PDKIM_VERIFY_FAIL;
sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
goto NEXT_VERIFY;
NEXT_VERIFY:
-#ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
+ DEBUG(D_acl)
{
- fprintf(ctx->debug_stream, "PDKIM [%s] signature status: %s",
+ debug_printf("PDKIM [%s] signature status: %s",
sig->domain, pdkim_verify_status_str(sig->verify_status));
if (sig->verify_ext_status > 0)
- fprintf(ctx->debug_stream, " (%s)\n",
+ debug_printf(" (%s)\n",
pdkim_verify_ext_status_str(sig->verify_ext_status));
else
- fprintf(ctx->debug_stream, "\n");
+ debug_printf("\n");
}
-#endif
- rsa_free(&rsa);
+#ifdef RSA_GNUTLS
+ gnutls_pubkey_deinit(rsa);
+#endif
free(dns_txt_name);
free(dns_txt_reply);
}
/* -------------------------------------------------------------------------- */
DLLEXPORT pdkim_ctx *
-pdkim_init_verify(int input_mode, int(*dns_txt_callback)(char *, char *))
+pdkim_init_verify(int(*dns_txt_callback)(char *, char *))
{
pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
}
ctx->mode = PDKIM_MODE_VERIFY;
-ctx->input_mode = input_mode;
ctx->dns_txt_callback = dns_txt_callback;
return ctx;
/* -------------------------------------------------------------------------- */
DLLEXPORT pdkim_ctx *
-pdkim_init_sign(int input_mode, char *domain, char *selector, char *rsa_privkey)
+pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo)
{
pdkim_ctx *ctx;
pdkim_signature *sig;
sig->bodylength = -1;
ctx->mode = PDKIM_MODE_SIGN;
-ctx->input_mode = input_mode;
ctx->sig = sig;
ctx->sig->domain = strdup(domain);
ctx->sig->selector = strdup(selector);
ctx->sig->rsa_privkey = strdup(rsa_privkey);
+ctx->sig->algo = algo;
if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey)
goto BAIL;
+#ifdef SHA_OPENSSL
+SHA1_Init (&ctx->sig->sha1_body);
+SHA256_Init(&ctx->sig->sha2_body);
+
+#elif defined(SHA_GNUTLS)
+gnutls_hash_init(&ctx->sig->sha_body,
+ algo == PDKIM_ALGO_RSA_SHA1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256);
+
+#elif defined(SHA_POLARSSL)
if (!(ctx->sig->sha1_body = malloc(sizeof(sha1_context))))
goto BAIL;
sha1_starts(ctx->sig->sha1_body);
goto BAIL;
sha2_starts(ctx->sig->sha2_body, 0);
+#endif
+
return ctx;
BAIL:
return NULL;
}
+
/* -------------------------------------------------------------------------- */
DLLEXPORT int
int canon_headers,
int canon_body,
long bodylength,
- int algo,
unsigned long created,
unsigned long expires)
{
-
if (identity)
if (!(ctx->sig->identity = strdup(identity)))
return PDKIM_ERR_OOM;
ctx->sig->canon_headers = canon_headers;
ctx->sig->canon_body = canon_body;
ctx->sig->bodylength = bodylength;
-ctx->sig->algo = algo;
ctx->sig->created = created;
ctx->sig->expires = expires;
return PDKIM_OK;
}
-/* -------------------------------------------------------------------------- */
-
-#ifdef PDKIM_DEBUG
-DLLEXPORT void
-pdkim_set_debug_stream(pdkim_ctx *ctx, FILE *debug_stream)
-{
-ctx->debug_stream = debug_stream;
-}
-#endif
+#endif /*DISABLE_DKIM*/