1 /*
2  * oath.h - header file for liboath
3  * Copyright (C) 2009-2016 Simon Josefsson
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  *
20  */
21 
22 #ifndef OATH_H
23 #define OATH_H
24 
25 #ifndef OATHAPI
26 # if defined LIBOATH_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY
27 #  define OATHAPI __attribute__((__visibility__("default")))
28 # elif defined LIBOATH_BUILDING && defined _MSC_VER && ! defined LIBOATH_STATIC
29 #  define OATHAPI __declspec(dllexport)
30 # elif defined _MSC_VER && ! defined LIBOATH_STATIC
31 #  define OATHAPI __declspec(dllimport)
32 # else
33 #  define OATHAPI
34 # endif
35 #endif
36 
37 #include <stdbool.h>		/* For bool. */
38 #include <stdint.h>		/* For uint64_t, SIZE_MAX. */
39 #include <string.h>		/* For size_t.t */
40 #include <time.h>		/* For time_t. */
41 
42 # ifdef __cplusplus
43 extern "C"
44 {
45 # endif
46 
47 /**
48  * OATH_VERSION
49  *
50  * Pre-processor symbol with a string that describe the header file
51  * version number.  Used together with oath_check_version() to verify
52  * header file and run-time library consistency.
53  */
54 #define OATH_VERSION "2.6.2"
55 
56 /**
57  * OATH_VERSION_NUMBER
58  *
59  * Pre-processor symbol with a hexadecimal value describing the header
60  * file version number.  For example, when the header version is 1.2.3
61  * this symbol will have the value 0x01020300.  The last two digits
62  * are only used between public releases, and will otherwise be 00.
63  */
64 #define OATH_VERSION_NUMBER 0x02060200
65 
66 /**
67  * oath_rc:
68  * @OATH_OK: Successful return
69  * @OATH_CRYPTO_ERROR: Internal error in crypto functions
70  * @OATH_INVALID_DIGITS: Unsupported number of OTP digits
71  * @OATH_PRINTF_ERROR: Error from system printf call
72  * @OATH_INVALID_HEX: Hex string is invalid
73  * @OATH_TOO_SMALL_BUFFER: The output buffer is too small
74  * @OATH_INVALID_OTP: The OTP is not valid
75  * @OATH_REPLAYED_OTP: The OTP has been replayed
76  * @OATH_BAD_PASSWORD: The password does not match
77  * @OATH_INVALID_COUNTER: The counter value is corrupt
78  * @OATH_INVALID_TIMESTAMP: The timestamp is corrupt
79  * @OATH_NO_SUCH_FILE: The supplied filename does not exist
80  * @OATH_UNKNOWN_USER: Cannot find information about user
81  * @OATH_FILE_SEEK_ERROR: System error when seeking in file
82  * @OATH_FILE_CREATE_ERROR: System error when creating file
83  * @OATH_FILE_LOCK_ERROR: System error when locking file
84  * @OATH_FILE_RENAME_ERROR: System error when renaming file
85  * @OATH_FILE_UNLINK_ERROR: System error when removing file
86  * @OATH_TIME_ERROR: System error for time manipulation
87  * @OATH_STRCMP_ERROR: A strcmp callback returned an error
88  * @OATH_INVALID_BASE32: Base32 string is invalid
89  * @OATH_BASE32_OVERFLOW: Base32 encoding would overflow
90  * @OATH_MALLOC_ERROR: Memory allocation failed
91  * @OATH_FILE_FLUSH_ERROR: System error when flushing file buffer
92  * @OATH_FILE_SYNC_ERROR: System error when syncing file to disk
93  * @OATH_FILE_CLOSE_ERROR: System error when closing file
94  * @OATH_LAST_ERROR: Meta-error indicating the last error code, for use
95  *   when iterating over all error codes or similar.
96  *
97  * Return codes for OATH functions.  All return codes are negative
98  * except for the successful code %OATH_OK which are guaranteed to be
99  * 0.  Positive values are reserved for non-error return codes.
100  *
101  * Note that the #oath_rc enumeration may be extended at a later date
102  * to include new return codes.
103  */
104 typedef enum
105 {
106   OATH_OK = 0,
107   OATH_CRYPTO_ERROR = -1,
108   OATH_INVALID_DIGITS = -2,
109   OATH_PRINTF_ERROR = -3,
110   OATH_INVALID_HEX = -4,
111   OATH_TOO_SMALL_BUFFER = -5,
112   OATH_INVALID_OTP = -6,
113   OATH_REPLAYED_OTP = -7,
114   OATH_BAD_PASSWORD = -8,
115   OATH_INVALID_COUNTER = -9,
116   OATH_INVALID_TIMESTAMP = -10,
117   OATH_NO_SUCH_FILE = -11,
118   OATH_UNKNOWN_USER = -12,
119   OATH_FILE_SEEK_ERROR = -13,
120   OATH_FILE_CREATE_ERROR = -14,
121   OATH_FILE_LOCK_ERROR = -15,
122   OATH_FILE_RENAME_ERROR = -16,
123   OATH_FILE_UNLINK_ERROR = -17,
124   OATH_TIME_ERROR = -18,
125   OATH_STRCMP_ERROR = -19,
126   OATH_INVALID_BASE32 = -20,
127   OATH_BASE32_OVERFLOW = -21,
128   OATH_MALLOC_ERROR = -22,
129   OATH_FILE_FLUSH_ERROR = -23,
130   OATH_FILE_SYNC_ERROR = -24,
131   OATH_FILE_CLOSE_ERROR = -25,
132   /* When adding anything here, update OATH_LAST_ERROR, errors.c
133      and tests/tst_errors.c. */
134   OATH_LAST_ERROR = -25
135 } oath_rc;
136 
137 /* Global */
138 
139 extern OATHAPI int oath_init (void);
140 extern OATHAPI int oath_done (void);
141 
142 extern OATHAPI const char *oath_check_version (const char *req_version);
143 
144 /* Error handling */
145 
146 extern OATHAPI const char *oath_strerror (int err);
147 extern OATHAPI const char *oath_strerror_name (int err);
148 
149 /* Data encoding */
150 
151 extern OATHAPI int oath_hex2bin (const char *hexstr,
152 				 char *binstr, size_t * binlen);
153 extern OATHAPI void oath_bin2hex (const char *binstr, size_t binlen,
154 				  char *hexstr);
155 
156 extern OATHAPI int oath_base32_decode (const char *in, size_t inlen,
157 				       char **out, size_t *outlen);
158 extern OATHAPI int oath_base32_encode (const char *in, size_t inlen,
159 				       char **out, size_t *outlen);
160 
161 /* HOTP */
162 
163 #define OATH_HOTP_LENGTH(digits, checksum) (digits + (checksum ? 1 : 0))
164 
165 #define OATH_HOTP_DYNAMIC_TRUNCATION SIZE_MAX
166 
167 extern OATHAPI int
168 oath_hotp_generate (const char *secret,
169 		    size_t secret_length,
170 		    uint64_t moving_factor,
171 		    unsigned digits,
172 		    bool add_checksum,
173 		    size_t truncation_offset,
174 		    char *output_otp);
175 
176 
177 extern OATHAPI int
178 oath_hotp_validate (const char *secret,
179 		    size_t secret_length,
180 		    uint64_t start_moving_factor,
181 		    size_t window, const char *otp);
182 
183 /**
184  * oath_validate_strcmp_function:
185  * @handle: caller handle as passed to oath_hotp_validate_callback()
186  * @test_otp: OTP to match against.
187  *
188  * Prototype of strcmp-like function that will be called by
189  * oath_hotp_validate_callback() or oath_totp_validate_callback() to
190  * validate OTPs.
191  *
192  * The function should be similar to strcmp in that it return 0 only
193  * on matches.  It differs by permitting use of negative return codes
194  * as indication of internal failures in the callback.  Positive
195  * values indicate OTP mismatch.
196  *
197  * This callback interface is useful when you cannot compare OTPs
198  * directly using normal strcmp, but instead for example only have a
199  * hashed OTP.  You would then typically pass in the hashed OTP in the
200  * @strcmp_handle and let your implementation of @oath_strcmp hash the
201  * test_otp OTP using the same hash, and then compare the results.
202  *
203  * Return value: 0 if and only if @test_otp is identical to the OTP to
204  *   be validated.  Negative value if an internal failure occurs.
205  *   Positive value if the test_otp simply doesn't match.
206  *
207  * Since: 1.6.0
208  **/
209 typedef int (*oath_validate_strcmp_function) (void *handle,
210 					      const char *test_otp);
211 
212 /* For backwards compatibility with 1.4.x. */
213 #define oath_hotp_validate_strcmp_function oath_validate_strcmp_function
214 
215 extern OATHAPI int
216 oath_hotp_validate_callback (const char *secret,
217 			     size_t secret_length,
218 			     uint64_t start_moving_factor,
219 			     size_t window,
220 			     unsigned digits,
221 			     oath_validate_strcmp_function strcmp_otp,
222 			     void *strcmp_handle);
223 
224 /* TOTP */
225 
226 #define OATH_TOTP_DEFAULT_TIME_STEP_SIZE	30
227 #define OATH_TOTP_DEFAULT_START_TIME		((time_t) 0)
228 
229 /**
230  * oath_totp_flags:
231  * @OATH_TOTP_HMAC_SHA256: Use HMAC-SHA256 instead of HMAC-SHA1.
232  * @OATH_TOTP_HMAC_SHA512: Use HMAC-SHA512 instead of HMAC-SHA1.
233  *
234  * Flags for oath_totp_generate2().
235  *
236  * Since: 2.6.0
237  */
238 typedef enum {
239   OATH_TOTP_HMAC_SHA256 = 1,
240   OATH_TOTP_HMAC_SHA512 = 2
241 } oath_totp_flags;
242 
243 extern OATHAPI int
244 oath_totp_generate (const char *secret,
245 		    size_t secret_length,
246 		    time_t now,
247 		    unsigned time_step_size,
248 		    time_t start_offset,
249 		    unsigned digits, char *output_otp);
250 
251 extern OATHAPI int
252 oath_totp_generate2 (const char *secret,
253 		     size_t secret_length,
254 		     time_t now,
255 		     unsigned time_step_size,
256 		     time_t start_offset,
257 		     unsigned digits,
258 		     int flags,
259 		     char *output_otp);
260 
261 extern OATHAPI int
262 oath_totp_validate (const char *secret,
263 		    size_t secret_length,
264 		    time_t now,
265 		    unsigned time_step_size,
266 		    time_t start_offset,
267 		    size_t window, const char *otp);
268 
269 extern OATHAPI int
270 oath_totp_validate_callback (const char *secret,
271 			     size_t secret_length,
272 			     time_t now,
273 			     unsigned time_step_size,
274 			     time_t start_offset,
275 			     unsigned digits,
276 			     size_t window,
277 			     oath_validate_strcmp_function strcmp_otp,
278 			     void *strcmp_handle);
279 
280 extern OATHAPI int
281 oath_totp_validate2 (const char *secret,
282 		     size_t secret_length,
283 		     time_t now,
284 		     unsigned time_step_size,
285 		     time_t start_offset,
286 		     size_t window,
287 		     int *otp_pos,
288 		     const char *otp);
289 
290 extern OATHAPI int
291 oath_totp_validate2_callback (const char *secret,
292 			      size_t secret_length,
293 			      time_t now,
294 			      unsigned time_step_size,
295 			      time_t start_offset,
296 			      unsigned digits,
297 			      size_t window,
298 			      int *otp_pos,
299 			      oath_validate_strcmp_function strcmp_otp,
300 			      void *strcmp_handle);
301 
302 extern OATHAPI int
303 oath_totp_validate3 (const char *secret,
304 		     size_t secret_length,
305 		     time_t now,
306 		     unsigned time_step_size,
307 		     time_t start_offset,
308 		     size_t window,
309 		     int *otp_pos,
310 		     uint64_t *otp_counter,
311 		     const char *otp);
312 
313 extern OATHAPI int
314 oath_totp_validate3_callback (const char *secret,
315 			      size_t secret_length,
316 			      time_t now,
317 			      unsigned time_step_size,
318 			      time_t start_offset,
319 			      unsigned digits,
320 			      size_t window,
321 			      int *otp_pos,
322 			      uint64_t *otp_counter,
323 			      oath_validate_strcmp_function strcmp_otp,
324 			      void *strcmp_handle);
325 
326 extern OATHAPI int
327 oath_totp_validate4 (const char *secret,
328 		     size_t secret_length,
329 		     time_t now,
330 		     unsigned time_step_size,
331 		     time_t start_offset,
332 		     size_t window,
333 		     int *otp_pos,
334 		     uint64_t *otp_counter,
335 		     int flags,
336 		     const char *otp);
337 
338 extern OATHAPI int
339 oath_totp_validate4_callback (const char *secret,
340 			      size_t secret_length,
341 			      time_t now,
342 			      unsigned time_step_size,
343 			      time_t start_offset,
344 			      unsigned digits,
345 			      size_t window,
346 			      int *otp_pos,
347 			      uint64_t *otp_counter,
348 			      int flags,
349 			      oath_validate_strcmp_function strcmp_otp,
350 			      void *strcmp_handle);
351 
352 /* Usersfile */
353 
354 extern OATHAPI int
355 oath_authenticate_usersfile (const char *usersfile,
356 			     const char *username,
357 			     const char *otp,
358 			     size_t window,
359 			     const char *passwd,
360 			     time_t * last_otp);
361 
362 # ifdef __cplusplus
363 }
364 # endif
365 
366 #endif /* OATH_H */
367