1 /* $Cambridge: exim/src/src/pdkim/pdkim.h,v 1.1.2.7 2009/03/17 16:20:13 tom Exp $ */
4 /* -------------------------------------------------------------------------- */
5 /* Debugging. This can also be enabled/disabled at run-time. I recommend to
9 /* -------------------------------------------------------------------------- */
10 /* Function success / error codes */
13 #define PDKIM_ERR_OOM -100
14 #define PDKIM_ERR_RSA_PRIVKEY -101
15 #define PDKIM_ERR_RSA_SIGNING -102
16 #define PDKIM_ERR_LONG_LINE -103
17 #define PDKIM_ERR_BUFFER_TOO_SMALL -104
19 /* -------------------------------------------------------------------------- */
20 /* Main/Extended verification status */
21 #define PDKIM_VERIFY_NONE 0
22 #define PDKIM_VERIFY_INVALID 1
23 #define PDKIM_VERIFY_FAIL 2
24 #define PDKIM_VERIFY_PASS 3
26 #define PDKIM_VERIFY_FAIL_BODY 1
27 #define PDKIM_VERIFY_FAIL_MESSAGE 2
28 #define PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE 3
29 #define PDKIM_VERIFY_INVALID_BUFFER_SIZE 4
30 #define PDKIM_VERIFY_INVALID_PUBKEY_PARSING 5
32 /* -------------------------------------------------------------------------- */
33 /* Some parameter values */
34 #define PDKIM_QUERYMETHOD_DNS_TXT 0
36 #define PDKIM_ALGO_RSA_SHA256 0
37 #define PDKIM_ALGO_RSA_SHA1 1
39 #define PDKIM_CANON_SIMPLE 0
40 #define PDKIM_CANON_RELAXED 1
42 #define PDKIM_HASH_SHA256 0
43 #define PDKIM_HASH_SHA1 1
45 #define PDKIM_KEYTYPE_RSA 0
47 /* -------------------------------------------------------------------------- */
48 /* Some required forward declarations, please ignore */
49 typedef struct pdkim_stringlist pdkim_stringlist;
50 typedef struct pdkim_str pdkim_str;
51 typedef struct sha1_context sha1_context;
52 typedef struct sha2_context sha2_context;
53 #define HAVE_SHA1_CONTEXT
54 #define HAVE_SHA2_CONTEXT
56 /* -------------------------------------------------------------------------- */
57 /* Public key as (usually) fetched from DNS */
58 typedef struct pdkim_pubkey {
59 char *version; /* v= */
60 char *granularity; /* g= */
62 char *hashes; /* h= */
63 char *keytype; /* k= */
64 char *srvtype; /* s= */
70 int testing; /* t=y */
71 int no_subdomaining; /* t=s */
74 /* -------------------------------------------------------------------------- */
75 /* Signature as it appears in a DKIM-Signature header */
76 typedef struct pdkim_signature {
78 /* Bits stored in a DKIM signature header --------------------------- */
80 /* (v=) The version, as an integer. Currently, always "1" */
83 /* (a=) The signature algorithm. Either PDKIM_ALGO_RSA_SHA256
84 or PDKIM_ALGO_RSA_SHA1 */
87 /* (c=x/) Header canonicalization method. Either PDKIM_CANON_SIMPLE
88 or PDKIM_CANON_RELAXED */
91 /* (c=/x) Body canonicalization method. Either PDKIM_CANON_SIMPLE
92 or PDKIM_CANON_RELAXED */
95 /* (q=) Query Method. Currently, only PDKIM_QUERYMETHOD_DNS_TXT
99 /* (s=) The selector string as given in the signature */
102 /* (d=) The domain as given in the signature */
105 /* (i=) The identity as given in the signature */
108 /* (t=) Timestamp of signature creation */
109 unsigned long created;
111 /* (x=) Timestamp of expiry of signature */
112 unsigned long expires;
114 /* (l=) Amount of hashed body bytes (after canonicalization) */
115 unsigned long bodylength;
117 /* (h=) Colon-separated list of header names that are included in the
124 /* (b=) Raw signature data, along with its length in bytes */
128 /* (bh=) Raw body hash data, along with its length in bytes */
132 /* Folded DKIM-Signature: header. Singing only, NULL for verifying.
133 Ready for insertion into the message. Note: Folded using CRLFTB,
134 but final line terminator is NOT included. Note2: This buffer is
135 free()d when you call pdkim_free_ctx(). */
136 char *signature_header;
138 /* The main verification status. Verification only. One of:
140 PDKIM_VERIFY_NONE Verification was not attempted. This status
143 PDKIM_VERIFY_INVALID There was an error while trying to verify
144 the signature. A more precise description
145 is available in verify_ext_status.
147 PDKIM_VERIFY_FAIL Verification failed because either the body
148 hash did not match, or the signature verification
149 failed. This means the message was modified.
150 Check verify_ext_status for the exact reason.
152 PDKIM_VERIFY_PASS Verification succeeded.
156 /* Extended verification status. Verification only. Depending on the value
157 of verify_status, it can contain:
159 For verify_status == PDKIM_VERIFY_INVALID:
161 PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE
162 Unable to retrieve a public key container.
164 PDKIM_VERIFY_INVALID_BUFFER_SIZE
165 Either the DNS name constructed to retrieve the public key record
166 does not fit into PDKIM_DNS_TXT_MAX_NAMELEN bytes, or the retrieved
167 record is longer than PDKIM_DNS_TXT_MAX_RECLEN bytes.
169 PDKIM_VERIFY_INVALID_PUBKEY_PARSING
170 (Syntax) error while parsing the retrieved public key record.
173 For verify_status == PDKIM_VERIFY_FAIL:
175 PDKIM_VERIFY_FAIL_BODY
176 The calculated body hash does not match the advertised body hash
177 from the bh= tag of the signature.
179 PDKIM_VERIFY_FAIL_MESSAGE
180 RSA verification of the signature (b= tag) failed.
182 int verify_ext_status;
184 /* Pointer to a public key record that was used to verify the signature.
185 See pdkim_pubkey declaration above for more information.
186 Caution: is NULL if signing or if no record was retrieved. */
187 pdkim_pubkey *pubkey;
189 /* Pointer to the next pdkim_signature signature. NULL if signing or if
190 this is the last signature. */
193 /* Properties below this point are used internally only ------------- */
195 /* Per-signature helper variables ----------------------------------- */
196 sha1_context *sha1_body; /* SHA1 block */
197 sha2_context *sha2_body; /* SHA256 block */
198 unsigned long signed_body_bytes; /* How many body bytes we hashed */
199 pdkim_stringlist *headers; /* Raw headers included in the sig */
200 /* Signing specific ------------------------------------------------- */
201 char *rsa_privkey; /* Private RSA key */
202 char *sign_headers; /* To-be-signed header names */
203 /* Verification specific -------------------------------------------- */
204 int headernames_pos; /* Current position in header name list */
205 char *rawsig_no_b_val; /* Original signature header w/o b= tag value. */
209 /* -------------------------------------------------------------------------- */
210 /* Context to keep state between all operations. */
211 #define PDKIM_MODE_SIGN 0
212 #define PDKIM_MODE_VERIFY 1
213 #define PDKIM_INPUT_NORMAL 0
214 #define PDKIM_INPUT_SMTP 1
215 typedef struct pdkim_ctx {
217 /* PDKIM_MODE_VERIFY or PDKIM_MODE_SIGN */
220 /* PDKIM_INPUT_SMTP or PDKIM_INPUT_NORMAL */
223 /* One (signing) or several chained (verification) signatures */
224 pdkim_signature *sig;
226 /* Callback for dns/txt query method (verification only) */
227 int(*dns_txt_callback)(char *, char *);
229 /* Coder's little helpers */
230 pdkim_str *cur_header;
236 int num_buffered_crlf;
240 /* A FILE pointer. When not NULL, debug output will be generated
241 and sent to this stream */
248 /* -------------------------------------------------------------------------- */
249 /* API functions. Please see pdkim-api.txt for documentation / example code. */
252 *pdkim_init_sign (int, char *, char *, char *);
255 *pdkim_init_verify (int, int(*)(char *, char *));
257 int pdkim_set_optional (pdkim_ctx *,
264 int pdkim_feed (pdkim_ctx *, char *, int);
265 int pdkim_feed_finish (pdkim_ctx *, pdkim_signature **);
267 void pdkim_free_ctx (pdkim_ctx *);
270 void pdkim_set_debug_stream (pdkim_ctx *, FILE *);