3f7a2dfb495a6045fc2eaf7e62b4eb0f05b1c91b
[users/jgh/exim.git] / src / src / pdkim / pdkim.h
1 /* $Cambridge: exim/src/src/pdkim/pdkim.h,v 1.1.2.8 2009/03/17 21:11:56 tom Exp $ */
2 /* pdkim.h */
3
4 /* -------------------------------------------------------------------------- */
5 /* Debugging. This can also be enabled/disabled at run-time. I recommend to
6    leave it defined. */
7 #define PDKIM_DEBUG
8
9 /* -------------------------------------------------------------------------- */
10 /* Function success / error codes */
11 #define PDKIM_OK                      0
12 #define PDKIM_FAIL                   -1
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
18
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
25
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
31
32 /* -------------------------------------------------------------------------- */
33 /* Some parameter values */
34 #define PDKIM_QUERYMETHOD_DNS_TXT 0
35
36 #define PDKIM_ALGO_RSA_SHA256     0
37 #define PDKIM_ALGO_RSA_SHA1       1
38
39 #define PDKIM_CANON_SIMPLE        0
40 #define PDKIM_CANON_RELAXED       1
41
42 #define PDKIM_HASH_SHA256         0
43 #define PDKIM_HASH_SHA1           1
44
45 #define PDKIM_KEYTYPE_RSA         0
46
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
55
56 /* -------------------------------------------------------------------------- */
57 /* Public key as (usually) fetched from DNS */
58 typedef struct pdkim_pubkey {
59   char *version;                  /* v=  */
60   char *granularity;              /* g=  */
61
62   char *hashes;                   /* h=  */
63   char *keytype;                  /* k=  */
64   char *srvtype;                  /* s=  */
65   char *notes;                    /* n=  */
66
67   char *key;                      /* p=  */
68   int   key_len;
69
70   int   testing;                  /* t=y */
71   int   no_subdomaining;          /* t=s */
72 } pdkim_pubkey;
73
74 /* -------------------------------------------------------------------------- */
75 /* Signature as it appears in a DKIM-Signature header */
76 typedef struct pdkim_signature {
77
78   /* Bits stored in a DKIM signature header --------------------------- */
79
80   /* (v=) The version, as an integer. Currently, always "1" */
81   int version;
82
83   /* (a=) The signature algorithm. Either PDKIM_ALGO_RSA_SHA256
84      or PDKIM_ALGO_RSA_SHA1 */
85   int algo;
86
87   /* (c=x/) Header canonicalization method. Either PDKIM_CANON_SIMPLE
88      or PDKIM_CANON_RELAXED */
89   int canon_headers;
90
91   /* (c=/x) Body canonicalization method. Either PDKIM_CANON_SIMPLE
92      or PDKIM_CANON_RELAXED */
93   int canon_body;
94
95   /* (q=) Query Method. Currently, only PDKIM_QUERYMETHOD_DNS_TXT
96      is specified */
97   int querymethod;
98
99   /* (s=) The selector string as given in the signature */
100   char *selector;
101
102   /* (d=) The domain as given in the signature */
103   char *domain;
104
105   /* (i=) The identity as given in the signature */
106   char *identity;
107
108   /* (t=) Timestamp of signature creation */
109   unsigned long created;
110
111   /* (x=) Timestamp of expiry of signature */
112   unsigned long expires;
113
114   /* (l=) Amount of hashed body bytes (after canonicalization) */
115   unsigned long bodylength;
116
117   /* (h=) Colon-separated list of header names that are included in the
118      signature */
119   char *headernames;
120
121   /* (z=) */
122   char *copiedheaders;
123
124   /* (b=) Raw signature data, along with its length in bytes */
125   char *sigdata;
126   int   sigdata_len;
127
128   /* (bh=) Raw body hash data, along with its length in bytes */
129   char *bodyhash;
130   int   bodyhash_len;
131
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;
137
138   /* The main verification status. Verification only. One of:
139
140      PDKIM_VERIFY_NONE      Verification was not attempted. This status
141                             should not appear.
142
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.
146
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.
151
152      PDKIM_VERIFY_PASS      Verification succeeded.
153   */
154   int verify_status;
155
156   /* Extended verification status. Verification only. Depending on the value
157      of verify_status, it can contain:
158
159      For verify_status == PDKIM_VERIFY_INVALID:
160
161         PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE
162           Unable to retrieve a public key container.
163
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.
168
169         PDKIM_VERIFY_INVALID_PUBKEY_PARSING
170           (Syntax) error while parsing the retrieved public key record.
171
172
173      For verify_status == PDKIM_VERIFY_FAIL:
174
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.
178
179         PDKIM_VERIFY_FAIL_MESSAGE
180           RSA verification of the signature (b= tag) failed.
181   */
182   int verify_ext_status;
183
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;
188
189   /* Pointer to the next pdkim_signature signature. NULL if signing or if
190      this is the last signature. */
191   void *next;
192
193   /* Properties below this point are used internally only ------------- */
194
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. */
206 } pdkim_signature;
207
208
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 {
216
217   /* PDKIM_MODE_VERIFY or PDKIM_MODE_SIGN */
218   int mode;
219
220   /* PDKIM_INPUT_SMTP or PDKIM_INPUT_NORMAL */
221   int input_mode;
222
223   /* One (signing) or several chained (verification) signatures */
224   pdkim_signature *sig;
225
226   /* Callback for dns/txt query method (verification only) */
227   int(*dns_txt_callback)(char *, char *);
228
229   /* Coder's little helpers */
230   pdkim_str *cur_header;
231   char      *linebuf;
232   int        linebuf_offset;
233   int        seen_lf;
234   int        seen_eod;
235   int        past_headers;
236   int        num_buffered_crlf;
237   int        num_headers;
238
239 #ifdef PDKIM_DEBUG
240   /* A FILE pointer. When not NULL, debug output will be generated
241     and sent to this stream */
242   FILE *debug_stream;
243 #endif
244
245 } pdkim_ctx;
246
247
248 /* -------------------------------------------------------------------------- */
249 /* API functions. Please see pdkim-api.txt for documentation / example code.  */
250
251 pdkim_ctx
252      *pdkim_init_sign         (int, char *, char *, char *);
253
254 pdkim_ctx
255      *pdkim_init_verify       (int, int(*)(char *, char *));
256
257 int   pdkim_set_optional      (pdkim_ctx *,
258                                char *, char *,
259                                int, int,
260                                unsigned long, int,
261                                unsigned long,
262                                unsigned long);
263
264 int   pdkim_feed              (pdkim_ctx *, char *, int);
265 int   pdkim_feed_finish       (pdkim_ctx *, pdkim_signature **);
266
267 void  pdkim_free_ctx          (pdkim_ctx *);
268
269 #ifdef PDKIM_DEBUG
270 void  pdkim_set_debug_stream  (pdkim_ctx *, FILE *);
271 #endif