1 /*****************************************************************************
2 *  Copyright 2005 Alt-N Technologies, Ltd.
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  This code incorporates intellectual property owned by Yahoo! and licensed
11 *  pursuant to the Yahoo! DomainKeys Patent License Agreement.
12 *
13 *  Unless required by applicable law or agreed to in writing, software
14 *  distributed under the License is distributed on an "AS IS" BASIS,
15 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 *  See the License for the specific language governing permissions and
17 *  limitations under the License.
18 *
19 *****************************************************************************/
20 
21 #ifdef WIN32
22 #define DKIM_CALL	WINAPI
23 #else
24 #define DKIM_CALL
25 #define MAKELONG(a,b) ((long)(((unsigned)(a) & 0xffff) | (((unsigned)(b) & 0xffff) << 16)))
26 #endif
27 
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 // DKIM Body hash versions
34 #define DKIM_BODYHASH_ALLMAN_1	1
35 #define DKIM_BODYHASH_IETF_1	2
36 #define DKIM_BODYHASH_BOTH		DKIM_BODYHASH_ALLMAN_1 | DKIM_BODYHASH_IETF_1
37 
38 // DKIM hash algorithms
39 #define DKIM_HASH_SHA1			1
40 #define DKIM_HASH_SHA256		2
41 #define DKIM_HASH_SHA1_AND_256  DKIM_HASH_SHA1 | DKIM_HASH_SHA256
42 
43 // DKIM canonicalization methods
44 #define DKIM_CANON_SIMPLE		1
45 #define DKIM_CANON_NOWSP		2
46 #define DKIM_CANON_RELAXED		3
47 
48 #define DKIM_SIGN_SIMPLE			MAKELONG(DKIM_CANON_SIMPLE,DKIM_CANON_SIMPLE)
49 #define DKIM_SIGN_SIMPLE_RELAXED	MAKELONG(DKIM_CANON_RELAXED,DKIM_CANON_SIMPLE)
50 #define DKIM_SIGN_RELAXED			MAKELONG(DKIM_CANON_RELAXED,DKIM_CANON_RELAXED)
51 #define DKIM_SIGN_RELAXED_SIMPLE	MAKELONG(DKIM_CANON_SIMPLE,DKIM_CANON_RELAXED)
52 
53 // DKIM Error codes
54 #define DKIM_SUCCESS						0		// operation successful
55 #define DKIM_FAIL							-1		// verify error: message is suspicious
56 #define DKIM_BAD_SYNTAX						-2		// signature error: DKIM-Signature could not parse or has bad tags/values
57 #define DKIM_SIGNATURE_BAD					-3		// signature error: RSA verify failed
58 #define DKIM_SIGNATURE_BAD_BUT_TESTING		-4		// signature error: RSA verify failed but testing
59 #define DKIM_SIGNATURE_EXPIRED				-5		// signature error: x= is old
60 #define DKIM_SELECTOR_INVALID				-6		// signature error: selector doesn't parse or contains invalid values
61 #define DKIM_SELECTOR_GRANULARITY_MISMATCH	-7		// signature error: selector g= doesn't match i=
62 #define DKIM_SELECTOR_KEY_REVOKED			-8		// signature error: selector p= empty
63 #define DKIM_SELECTOR_DOMAIN_NAME_TOO_LONG	-9		// signature error: selector domain name too long to request
64 #define DKIM_SELECTOR_DNS_TEMP_FAILURE		-10		// signature error: temporary dns failure requesting selector
65 #define DKIM_SELECTOR_DNS_PERM_FAILURE		-11		// signature error: permanent dns failure requesting selector
66 #define DKIM_SELECTOR_PUBLIC_KEY_INVALID	-12		// signature error: selector p= value invalid or wrong format
67 #define DKIM_NO_SIGNATURES					-13		// process error, no sigs
68 #define DKIM_NO_VALID_SIGNATURES			-14		// process error, no valid sigs
69 #define DKIM_BODY_HASH_MISMATCH				-15		// sigature verify error: message body does not hash to bh value
70 #define DKIM_SELECTOR_ALGORITHM_MISMATCH	-16		// signature error: selector h= doesn't match signature a=
71 #define DKIM_STAT_INCOMPAT					-17		// signature error: incompatible v=
72 #define DKIM_UNSIGNED_FROM					-18		// signature error: not all message's From headers in signature
73 #define DKIM_OUT_OF_MEMORY					-20		// memory allocation failed
74 #define DKIM_INVALID_CONTEXT				-21		// DKIMContext structure invalid for this operation
75 #define DKIM_NO_SENDER						-22		// signing error: Could not find From: or Sender: header in message
76 #define DKIM_BAD_PRIVATE_KEY				-23		// signing error: Could not parse private key
77 #define DKIM_BUFFER_TOO_SMALL				-24		// signing error: Buffer passed in is not large enough
78 #define DKIM_MAX_ERROR						-25		// set this to 1 greater than the highest error code (but negative)
79 
80 // DKIM_SUCCESS									// verify result: all signatures verified
81 												// signature result: signature verified
82 #define DKIM_FINISHED_BODY					1	// process result: no more message body is needed
83 #define DKIM_PARTIAL_SUCCESS				2	// verify result: at least one but not all signatures verified
84 #define DKIM_NEUTRAL						3	// verify result: no signatures verified but message is not suspicous
85 #define DKIM_SUCCESS_BUT_EXTRA				4	// signature result: signature verified but it did not include all of the body
86 
87 
88 
89 // This function is called once for each header in the message
90 // return 1 to include this header in the signature and 0 to exclude.
91 typedef int (DKIM_CALL *DKIMHEADERCALLBACK)(const char* szHeader);
92 
93 // This function is called to retrieve a TXT record from DNS
94 typedef int (DKIM_CALL *DKIMDNSCALLBACK)(const char* szFQDN, char* szBuffer, int nBufLen );
95 
96 #ifdef _WIN32
97 #include <pshpack1.h>
98 #endif
99 
100 typedef struct DKIMContext_t
101 {
102 	unsigned int reserved1;
103 	unsigned int reserved2;
104 	void*		 reserved3;
105 } DKIMContext;
106 
107 typedef struct DKIMSignOptions_t
108 {
109 	int nCanon;								// canonization
110 	int nIncludeBodyLengthTag;				// 0 = don't include l= tag, 1 = include l= tag
111 	int nIncludeTimeStamp;					// 0 = don't include t= tag, 1 = include t= tag
112 	int nIncludeQueryMethod;				// 0 = don't include q= tag, 1 = include q= tag
113 	char szSelector[80];					// selector - required
114 	char szDomain[256];						// domain - optional - if empty, domain is computed from sender
115 	char szIdentity[256];					// for i= tag, if empty tag will not be included in sig
116 	unsigned long expireTime;				// for x= tag, if 0 tag will not be included in sig
117 	DKIMHEADERCALLBACK pfnHeaderCallback;	// header callback
118 	char szRequiredHeaders[256];			// colon-separated list of headers that must be signed
119 	int nHash;								// use one of the DKIM_HASH_xx constants here
120 											// even if not present in the message
121 	int nIncludeCopiedHeaders;				// 0 = don't include z= tag, 1 = include z= tag
122 	int nIncludeBodyHash;					// use one of the DKIM_BODYHASH_xx constants here
123 } DKIMSignOptions;
124 
125 typedef struct DKIMVerifyOptions_t
126 {
127 	DKIMDNSCALLBACK pfnSelectorCallback;	// selector record callback
128 	DKIMDNSCALLBACK pfnPracticesCallback;	// ADSP record callback
129 	int nHonorBodyLengthTag;				// 0 = ignore l= tag, 1 = use l= tag to limit the amount of body verified
130 	int nCheckPractices;					// 0 = use default (unknown) practices, 1 = request and use author domain signing practices
131 	int nSubjectRequired;					// 0 = subject is required to be signed, 1 = not required
132 	int nSaveCanonicalizedData;				// 0 = canonicalized data is not saved, 1 = canonicalized data is saved
133 	int nAllowUnsignedFromHeaders;			// 0 = From headers not included in the signature are not allowed, 1 = allowed
134 } DKIMVerifyOptions;
135 
136 typedef struct DKIMVerifyDetails_t
137 {
138 	char *szSignature;
139 	char *szSignatureDomain;
140 	char *szIdentityDomain;
141 	char *szCanonicalizedData;
142 	int nResult;
143 } DKIMVerifyDetails;
144 
145 
146 #ifdef _WIN32
147 #include <poppack.h>
148 #endif
149 
150 int DKIM_CALL DKIMSignInit( DKIMContext* pSignContext, DKIMSignOptions* pOptions );
151 int DKIM_CALL DKIMSignProcess( DKIMContext* pSignContext, char* szBuffer, int nBufLength );
152 int DKIM_CALL DKIMSignGetSig( DKIMContext* pSignContext, char* szPrivKey, char* szSignature, int nSigLength );
153 int DKIM_CALL DKIMSignGetSig2( DKIMContext* pSignContext, char* szPrivKey, char** pszSignature );
154 void DKIM_CALL DKIMSignFree( DKIMContext* pSignContext );
155 
156 int DKIM_CALL DKIMVerifyInit( DKIMContext* pVerifyContext, DKIMVerifyOptions* pOptions );
157 int DKIM_CALL DKIMVerifyProcess( DKIMContext* pVerifyContext, char* szBuffer, int nBufLength );
158 int DKIM_CALL DKIMVerifyResults( DKIMContext* pVerifyContext );
159 int DKIM_CALL DKIMVerifyGetDetails( DKIMContext* pVerifyContext, int* nSigCount, DKIMVerifyDetails** pDetails, char* szPractices );
160 void DKIM_CALL DKIMVerifyFree( DKIMContext* pVerifyContext );
161 
162 char *DKIM_CALL DKIMVersion();
163 
164 char *DKIM_CALL DKIMGetErrorString( int ErrorCode );
165 
166 #ifdef __cplusplus
167 }
168 #endif
169