cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
os_spec.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib OS-specific Support Routines *
4 * Copyright Peter Gutmann 1992-2007 *
5 * *
6 ****************************************************************************/
7 
8 #include <ctype.h>
9 #include <stddef.h> /* For ptrdiff_t */
10 #include <stdio.h>
11 #if defined( INC_ALL )
12  #include "crypt.h"
13 #else
14  #include "crypt.h"
15 #endif /* Compiler-specific includes */
16 
17 /****************************************************************************
18 * *
19 * AMX *
20 * *
21 ****************************************************************************/
22 
23 #if defined( __AMX__ )
24 
25 /* The AMX task-priority function returns the priority via a reference
26  parameter. Because of this we have to provide a wrapper that returns
27  it as a return value */
28 
29 int threadPriority( void )
30  {
31  int priority = 0;
32 
33  cjtkpradjust( cjtkid(), &priority );
34  return( priority );
35  }
36 
37 /****************************************************************************
38 * *
39 * BeOS *
40 * *
41 ****************************************************************************/
42 
43 /* Match a given substring against a string in a case-insensitive manner.
44  If possible we use native calls to handle this since they deal with
45  charset-specific issues such as collating sequences, however a few OSes
46  don't provide this functionality so we have to do it ourselves */
47 
48 #elif defined( __BEOS__ ) || defined( __SYMBIAN32__ )
49 
50 int strnicmp( const char *src, const char *dest, int length )
51  {
52  assert( isReadPtr( src, length ) );
53 
54  while( length-- > 0 )
55  {
56  char srcCh = *src++, destCh = *dest++;
57 
58  /* Need to be careful with toupper() side-effects */
59  srcCh = toUpper( srcCh );
60  destCh = toUpper( destCh );
61 
62  if( srcCh != destCh )
63  return( srcCh - destCh );
64  }
65 
66  return( 0 );
67  }
68 
69 int stricmp( const char *src, const char *dest )
70  {
71  const int length = strlen( src );
72 
73  if( length != strlen( dest ) )
74  return( 1 ); /* Lengths differ */
75  return( strnicmp( src, dest, length ) );
76  }
77 
78 /****************************************************************************
79 * *
80 * uC/OS-II *
81 * *
82 ****************************************************************************/
83 
84 #elif defined( __UCOS__ )
85 
86 #undef BOOLEAN /* See comment in kernel/thread.h */
87 #include <ucos_ii.h>
88 #define BOOLEAN int
89 
90 /* uC/OS-II doesn't have a thread-self function, but allows general task
91  info to be queried. Because of this we provide a wrapper that returns
92  the task ID as its return value */
93 
94 INT8U threadSelf( void )
95  {
96  OS_TCB osTCB;
97 
98  OSTaskQuery( OS_PRIO_SELF, &osTCB );
99  return( osTCB.OSTCBPrio );
100  }
101 
102 /****************************************************************************
103 * *
104 * uITRON *
105 * *
106 ****************************************************************************/
107 
108 #elif defined( __ITRON__ )
109 
110 #include <itron.h>
111 
112 /* The uITRON thread-self function returns the thread ID via a reference
113  parameter since uITRON IDs can be negative and there'd be no way to
114  differentiate a thread ID from an error code. Because of this we have
115  to provide a wrapper that returns it as a return value */
116 
117 ID threadSelf( void )
118  {
119  ID tskid;
120 
121  get_tid( &tskid );
122  return( tskid );
123  }
124 
125 /****************************************************************************
126 * *
127 * IBM Mainframe *
128 * *
129 ****************************************************************************/
130 
131 /* VM/CMS, MVS, and AS/400 systems need to convert characters from ASCII <->
132  EBCDIC before/after they're read/written to external formats, the
133  following functions perform the necessary conversion using the latin-1
134  code tables for systems that don't have etoa/atoe */
135 
136 #elif defined( __MVS__ ) && defined( EBCDIC_CHARS )
137 
138 #include <stdarg.h>
139 
140 #ifndef USE_ETOA
141 
142 /* ISO 8859-1 to IBM Latin-1 Code Page 01047 (EBCDIC) */
143 
144 static const BYTE asciiToEbcdicTbl[] = {
145  0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */
146  0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */
147  0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */
148  0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */
149  0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */
150  0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */
151  0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */
152  0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */
153  0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */
154  0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */
155  0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */
156  0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, /* 58 - 5F */
157  0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */
158  0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */
159  0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */
160  0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */
161  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17, /* 80 - 87 */
162  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */
163  0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */
164  0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */
165  0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */
166  0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC, /* A8 - AF */
167  0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */
168  0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */
169  0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */
170  0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */
171  0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */
172  0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59, /* D8 - DF */
173  0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */
174  0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */
175  0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */
176  0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */
177  };
178 
179 /* IBM Latin-1 Code Page 01047 (EBCDIC) to ISO 8859-1 */
180 
181 static const BYTE ebcdicToAsciiTbl[] = {
182  0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */
183  0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */
184  0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87, /* 10 - 17 */
185  0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */
186  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B, /* 20 - 27 */
187  0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */
188  0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */
189  0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */
190  0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */
191  0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */
192  0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */
193  0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /* 58 - 5F */
194  0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */
195  0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */
196  0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */
197  0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */
198  0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */
199  0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */
200  0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */
201  0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */
202  0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */
203  0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE, /* A8 - AF */
204  0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */
205  0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7, /* B8 - BF */
206  0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */
207  0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */
208  0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */
209  0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */
210  0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */
211  0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */
212  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */
213  0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */
214  };
215 
216 /* Convert a string to/from EBCDIC */
217 
218 int asciiToEbcdic( char *dest, const char *src, const int length )
219  {
220  int i;
221 
222  assert( isReadPtr( src, length ) );
223  assert( isWritePtr( dest, length ) );
224 
225  for( i = 0; i < length; i++ )
226  dest[ i ] = asciiToEbcdicTbl[ ( unsigned int ) src[ i ] ];
227  return( CRYPT_OK );
228  }
229 
230 int ebcdicToAscii( char *dest, const char *src, const int length )
231  {
232  int i;
233 
234  assert( isReadPtr( src, length ) );
235  assert( isWritePtr( dest, length ) );
236 
237  for( i = 0; i < length; i++ )
238  dest[ i ] = ebcdicToAsciiTbl[ ( unsigned int ) src[ i ] ];
239  return( CRYPT_OK );
240  }
241 #else
242 
243 int asciiToEbcdic( char *dest, const char *src, const int length )
244  {
245  assert( isReadPtr( src, length ) );
246  assert( isWritePtr( dest, length ) );
247 
248  if( dest != src )
249  memcpy( dest, src, length );
250  return( return( __atoe_l( dest, length ) < 0 ? \
252  }
253 
254 int ebcdicToAscii( char *dest, const char *src, const int length )
255  {
256  assert( isReadPtr( src, length ) );
257  assert( isWritePtr( dest, length ) );
258 
259  if( dest != src )
260  memcpy( dest, src, length );
261  return( return( __etoa_l( dest, length ) < 0 ? \
263  }
264 #endif /* USE_ETOA */
265 
266 /* Convert a string to EBCDIC via a temporary buffer, used when passing an
267  ASCII string to a system function that requires EBCDIC */
268 
269 char *bufferToEbcdic( char *buffer, const char *string )
270  {
271  strcpy( buffer, string );
272  asciiToEbcdic( buffer, buffer, strlen( string ) );
273  return( buffer );
274  }
275 
276 /* Table for ctype functions that explicitly use the ASCII character set */
277 
278 #define A ASCII_ALPHA
279 #define L ASCII_LOWER
280 #define N ASCII_NUMERIC
281 #define S ASCII_SPACE
282 #define U ASCII_UPPER
283 #define X ASCII_HEX
284 #define AL ( A | L )
285 #define AU ( A | U )
286 #define ANX ( A | N | X )
287 #define AUX ( A | U | X )
288 
289 const BYTE asciiCtypeTbl[ 256 ] = {
290  /* 00 01 02 03 04 05 06 07 */
291  0, 0, 0, 0, 0, 0, 0, 0,
292  /* 08 09 0A 0B 0C 0D 0E 0F */
293  0, 0, 0, 0, 0, 0, 0, 0,
294  /* 10 11 12 13 14 15 16 17 */
295  0, 0, 0, 0, 0, 0, 0, 0,
296  /* 18 19 1A 1B 1C 1D 1E 1F */
297  0, 0, 0, 0, 0, 0, 0, 0,
298  /* ! " # $ % & ' */
299  A, A, A, A, A, A, A, A,
300  /* ( ) * + , - . / */
301  A, A, A, A, A, A, A, A,
302  /* 0 1 2 3 4 5 6 7 */
303  ANX, ANX, ANX, ANX, ANX, ANX, ANX, ANX,
304  /* 8 9 : ; < = > ? */
305  ANX, ANX, A, A, A, A, A, A,
306  /* @ A B C D E F G */
307  A, AUX, AUX, AUX, AUX, AUX, AUX, AU,
308  /* H I J K L M N O */
309  AU, AU, AU, AU, AU, AU, AU, AU,
310  /* P Q R S T U V W */
311  AU, AU, AU, AU, AU, AU, AU, AU,
312  /* X Y Z [ \ ] ^ _ */
313  AU, AU, AU, A, A, A, A, A,
314  /* ` a b c d e f g */
315  A, AL, AL, AL, AL, AL, AL, AL,
316  /* h i j k l m n o */
317  AL, AL, AL, AL, AL, AL, AL, AL,
318  /* p q r s t u v w */
319  AL, AL, AL, AL, AL, AL, AL, AL,
320  /* x y z { | } ~ DL */
321  AL, AL, AL, A, A, A, A, A,
322  /* High-bit-set characters */
323  0
324  };
325 
326 /* stricmp()/strnicmp() versions that explicitly use the ASCII character
327  set. In order for collation to be handled properly, we have to convert
328  to EBCDIC and use the local stricmp()/strnicmp() */
329 
330 int strCompare( const char *src, const char *dest, int length )
331  {
332  BYTE buffer1[ MAX_ATTRIBUTE_SIZE + 8 ];
333  BYTE buffer2[ MAX_ATTRIBUTE_SIZE + 8 ];
334 
335  assert( isReadPtr( src, length ) );
336 
337  if( length > MAX_ATTRIBUTE_SIZE )
338  return( 1 ); /* Invalid length */
339 
340  /* Virtually all strings are 7-bit ASCII, the following optimisation
341  speeds up checking, particularly in cases where we're walking down a
342  list of keywords looking for a match */
343  if( *src < 0x80 && *dest < 0x80 && \
344  toLower( *src ) != toLower( *dest ) )
345  return( 1 ); /* Not equal */
346 
347  /* Convert the strings to EBCDIC and use a native compare */
348  src = bufferToEbcdic( buffer1, src );
349  dest = bufferToEbcdic( buffer2, dest );
350  return( strncasecmp( src, dest, length ) );
351  }
352 
353 int strCompareZ( const char *src, const char *dest )
354  {
355  const int length = strlen( src );
356 
357  if( length != strlen( dest ) )
358  return( 1 ); /* Lengths differ */
359  return( strCompare( src, dest, length ) );
360  }
361 
362 /* sprintf_s() and vsprintf_s() that take ASCII format strings. Since
363  vsprintf_s() does the same thing as sprintf_s(), we map them both to
364  the same function in the os_spec.h header. Unfortunately we have to
365  use vsprintf() to do the actual printing, since MVS doesn't support
366  vsnprintf() */
367 
368 int sPrintf_s( char *buffer, const int bufSize, const char *format, ... )
369  {
370  BYTE formatBuffer[ MAX_ATTRIBUTE_SIZE + 8 ];
371  va_list argPtr;
372  const int formatLen = strlen( format ) - 1;
373 #ifndef NDEBUG
374  int i;
375 #endif /* Debug version */
376  int status;
377 
378 #ifndef NDEBUG
379  /* Make sure that we don't have any string args, which would require
380  their own conversion to EBCDIC */
381  for( i = 0; i < formatLen; i++ )
382  {
383  if( format[ i ] == '%' && format[ i + 1 ] == 's' )
384  {
385  assert( DEBUG_WARN );
386  strlcpy_s( buffer, bufSize,
387  "<<<Unable to format output string>>>" );
388  return( -1 );
389  }
390  }
391 #endif /* Debug version */
392  format = bufferToEbcdic( formatBuffer, format );
393  va_start( argPtr, format );
394  status = vsprintf( buffer, format, argPtr );
395  if( status > 0 )
396  ebcdicToAscii( buffer, buffer, status );
397  va_end( argPtr );
398  return( status );
399  }
400 
401 /****************************************************************************
402 * *
403 * PalmOS *
404 * *
405 ****************************************************************************/
406 
407 #elif defined( __PALMOS__ )
408 
409 #include <CmnErrors.h>
410 #include <CmnLaunchCodes.h>
411 
412 /* The cryptlib entry point, defined in cryptlib.sld */
413 
414 uint32_t cryptlibMain( uint16_t cmd, void *cmdPBP, uint16_t launchFlags )
415  {
416  UNUSED_ARG( cmdPBP );
417  UNUSED_ARG( launchFlags );
418 
419  switch( cmd )
420  {
421  case sysLaunchCmdInitialize:
422  /* Set up the initialisation lock in the kernel */
423  preInit();
424  break;
425 
426  case sysLaunchCmdFinalize:
427  /* Delete the initialisation lock in the kernel */
428  postShutdown();
429  break;
430  }
431 
432  return( errNone );
433  }
434 
435 /****************************************************************************
436 * *
437 * RTEMS *
438 * *
439 ****************************************************************************/
440 
441 #elif defined( __RTEMS__ )
442 
443 /* The RTEMS thread-self function returns the task ID via a reference
444  parameter, because of this we have to provide a wrapper that returns it
445  as a return value. We use RTEMS_SEARCH_ALL_NODES because there isn't
446  any other way to specify the local node, this option always searches the
447  local node first so it has the desired effect */
448 
449 #include <rtems.h>
450 
451 rtems_id threadSelf( void )
452  {
453  rtems_id taskID;
454 
455  rtems_task_ident( RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &taskID );
456  return( taskID );
457  }
458 
459 /****************************************************************************
460 * *
461 * Tandem *
462 * *
463 ****************************************************************************/
464 
465 /* The Tandem mktime() is broken and can't convert dates beyond 2023, if
466  mktime() fails and the year is between then and the epoch try again with
467  a time that it can convert */
468 
469 #elif defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )
470 
471 #undef mktime /* Restore the standard mktime() */
472 
473 time_t my_mktime( struct tm *timeptr )
474  {
475  time_t theTime;
476 
477  theTime = mktime( timeptr );
478  if( theTime < 0 && timeptr->tm_year > 122 && timeptr->tm_year <= 138 )
479  {
480  timeptr->tm_year = 122; /* Try again with a safe year of 2022 */
481  theTime = mktime( timeptr );
482  }
483  return( theTime );
484  }
485 
486 /****************************************************************************
487 * *
488 * Unix *
489 * *
490 ****************************************************************************/
491 
492 #elif defined( __UNIX__ ) && \
493  !( defined( __MVS__ ) || defined( __TANDEM_NSK__ ) || \
494  defined( __TANDEM_OSS__ ) )
495 
496 #include <sys/time.h>
497 
498 /* For performance evaluation purposes we provide the following function,
499  which returns ticks of the 1us timer */
500 
501 long getTickCount( long startTime )
502  {
503  struct timeval tv;
504  long timeLSB, timeDifference;
505 
506  /* Only accurate to about 1us */
507  gettimeofday( &tv, NULL );
508  timeLSB = tv.tv_usec;
509 
510  /* If we're getting an initial time, return an absolute value */
511  if( startTime <= 0 )
512  return( timeLSB );
513 
514  /* We're getting a time difference */
515  if( startTime < timeLSB )
516  timeDifference = timeLSB - startTime;
517  else
518  /* gettimeofday() rolls over at 1M us */
519  timeDifference = ( 1000000L - startTime ) + timeLSB;
520  if( timeDifference <= 0 )
521  {
522  printf( "Error: Time difference = %lX, startTime = %lX, "
523  "endTime = %lX.\n", timeDifference, startTime, timeLSB );
524  return( 1 );
525  }
526  return( timeDifference );
527  }
528 
529 /* SunOS and older Slowaris have broken sprintf() handling. In SunOS 4.x
530  this was documented as returning a pointer to the output data as per the
531  Berkeley original. Under Slowaris the manpage was changed so that it
532  looks like any other sprintf(), but it still returns the pointer to the
533  output buffer in some versions so we use a wrapper that checks at
534  runtime to see what we've got and adjusts its behaviour accordingly. In
535  fact it's much easier to fix than that, since we have to use vsprintf()
536  anyway and this doesn't have the sprintf() problem, this fixes itself
537  simply from the use of the wrapper (unfortunately we can't use
538  vsnprintf() because these older OS versions don't include it yet) */
539 
540 #if defined( sun ) && ( OSVERSION <= 5 )
541 
542 #include <stdarg.h>
543 
544 int fixedSprintf( char *buffer, const int bufSize, const char *format, ... )
545  {
546  va_list argPtr;
547  int length;
548 
549  va_start( argPtr, format );
550  length = vsprintf( buffer, format, argPtr );
551  va_end( argPtr );
552 
553  return( length );
554  }
555 #endif /* Old SunOS */
556 
557 /****************************************************************************
558 * *
559 * Windows *
560 * *
561 ****************************************************************************/
562 
563 #elif defined( __WIN32__ )
564 
565 /* Yielding a thread on an SMP or HT system is a tricky process,
566  particularly on an HT system. On an HT CPU the OS (or at least apps
567  running under the OS) think that there are two independent CPUs present,
568  but it's really just one CPU with partitioning of pipeline slots. So
569  when one thread yields, the only effect is that all of its pipeline slots
570  get marked as available. Since the other thread can't utilise those
571  slots, the first thread immediately reclaims them and continues to run.
572  In addition thread scheduling varies across OS versions, the WinXP
573  scheduler was changed to preferentially schedule threads on idle physical
574  processors rather than an idle logical processor on a physical processor
575  whose other logical processor is (potentially) busy.
576 
577  There isn't really any easy way to fix this since it'd require a sleep
578  that works across all CPUs, however one solution is to make the thread
579  sleep for a nonzero time limit iff it's running on a multi-CPU system.
580  There's a second problem though, which relates to thread priorities. If
581  we're at a higher priority than the other thread then we can call
582  Sleep( 0 ) as much as we like, but the scheduler will never allow the
583  other thread to run since we're a higher-priority runnable thread. As a
584  result, as soon as we release our timeslice the scheduler will restart us
585  again (the Windows scheduler implements a starvation-prevention mechanism
586  via the balance set manager, but this varies across scheduler versions
587  and isn't something that we want to rely on). In theory we could do:
588 
589  x = GetThreadPriority( GetCurrentThread() );
590  SetThreadPriority( GetCurrentThread(), x - 5 );
591  Sleep( 0 ); // Needed to effect priority change
592  <wait loop>
593  SetThreadPriority( GetCurrentThread(), x );
594  Sleep( 0 );
595 
596  however this is somewhat problematic if the caller is also messing with
597  priorities at the same time. In fact it can get downright nasty because
598  the balance set manager will, if a thread has been starved for ~3-4
599  seconds, give it its own priority boost to priority 15 (time-critical) to
600  ensure that it'll be scheduled, with the priority slowly decaying back to
601  the normal level each time that it's scheduled. In addition it'll have
602  its scheduling quantum boosted to 2x the normal duration for a client OS
603  or 4x the normal duration for a server OS.
604 
605  To solve this, we always force our thread to go to sleep (to allow a
606  potentially lower-priority thread to leap in and get some work done) even
607  on a single-processor system, but use a slightly longer wait on an
608  HT/multi-processor system.
609 
610  (Actually this simplified view isn't quite accurate since on a HT system
611  the scheduler executes the top *two* threads on the two logical
612  processors and on a dual-CPU system they're executed on a physical
613  processor. In addition on a HT system a lower-priority thread on one
614  logical processor can compete with a higher-priority thread on the other
615  logical processor since the hardware isn't aware of thread priorities) */
616 
617 void threadYield( void )
618  {
619  static int sleepTime = -1;
620 
621  /* If the sleep time hasn't been determined yet, get it now */
622  if( sleepTime < 0 )
623  {
624  SYSTEM_INFO systemInfo;
625 
626  GetSystemInfo( &systemInfo );
627  sleepTime = ( systemInfo.dwNumberOfProcessors > 1 ) ? 10 : 1;
628  }
629 
630  /* Yield the CPU for this thread */
631  Sleep( sleepTime );
632  }
633 
634 #ifndef NDEBUG
635 
636 /* For performance evaluation purposes we provide the following function,
637  which returns ticks of the 3.579545 MHz hardware timer (see the long
638  comment in rndwin32.c for more details on Win32 timing issues) */
639 
640 long getTickCount( long startTime )
641  {
642  long timeLSB, timeDifference;
643 
644 #ifndef __BORLANDC__
645  LARGE_INTEGER performanceCount;
646 
647  /* Sensitive to context switches */
648  QueryPerformanceCounter( &performanceCount );
649  timeLSB = performanceCount.LowPart;
650 #else
651  FILETIME dummyTime, kernelTime, userTime;
652 
653  /* Only accurate to 10ms, returns constant values in VC++ debugger */
654  GetThreadTimes( GetCurrentThread(), &dummyTime, &dummyTime,
655  &kernelTime, &userTime );
656  timeLSB = userTime.dwLowDateTime;
657 #endif /* BC++ vs. everything else */
658 
659  /* If we're getting an initial time, return an absolute value */
660  if( startTime <= 0 )
661  return( timeLSB );
662 
663  /* We're getting a time difference */
664  if( startTime < timeLSB )
665  timeDifference = timeLSB - startTime;
666  else
667  {
668  /* Windows rolls over at INT_MAX */
669  timeDifference = ( 0xFFFFFFFFUL - startTime ) + 1 + timeLSB;
670  }
671  if( timeDifference <= 0 )
672  {
673  printf( "Error: Time difference = %X, startTime = %X, endTime = %X.\n",
674  timeDifference, startTime, timeLSB );
675  return( 1 );
676  }
677  return( timeDifference );
678  }
679 #endif /* Debug version */
680 
681 /* Borland C++ before 5.50 doesn't have snprintf() so we fake it using
682  sprintf(). Unfortunately these are all va_args functions so we can't
683  just map them using macros but have to provide an explicit wrapper to get
684  rid of the size argument */
685 
686 #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0550 )
687 
688 int bcSnprintf( char *buffer, const int bufSize, const char *format, ... )
689  {
690  va_list argPtr;
691  int length;
692 
693  va_start( argPtr, format );
694  length = vsprintf( buffer, format, argPtr );
695  va_end( argPtr );
696 
697  return( length );
698  }
699 
700 int bcVsnprintf( char *buffer, const int bufSize, const char *format, va_list argPtr )
701  {
702  return( vsprintf( buffer, format, argPtr ) );
703  }
704 #endif /* BC++ before 5.50 */
705 
706 /* Safely load a DLL. This gets quite complicated because different
707  versions of Windows have changed how they search for DLLs to load, and
708  the behaviour of a specific version of Windows can be changed based on
709  registry keys and SetDllDirectory(). Traditionally Windows searched
710  the app directory, the current directory, the system directory, the
711  Windows directory, and the directories in $PATH. Windows XP SP2 added
712  the SafeDllSearchMode registry key, which changes the search order so
713  the current directory is searched towards the end rather than towards
714  the start, however it's (apparently) only set on new installs, on a
715  pre-SP2 install that's been upgraded it's not set. In addition
716  SetDllDirectory() can be used to add a new directory to the start of
717  the search order, or to revert to the default search order if it's
718  been changed previously.
719 
720  None of these options are terribly useful if we want a DLL to either
721  be loaded from the system directory or not at all. To handle this we
722  build an absolute load path and prepend it to the name of the DLL
723  being loaded */
724 
725 #ifndef CSIDL_SYSTEM
726  #define CSIDL_SYSTEM 0x25 /* 'Windows/System32' */
727 #endif /* !CSIDL_SYSTEM */
728 #ifndef SHGFP_TYPE_CURRENT
729  #define SHGFP_TYPE_CURRENT 0
730 #endif /* !SHGFP_TYPE_CURRENT */
731 
732 HMODULE WINAPI loadExistingLibrary( IN_STRING LPCTSTR lpFileName )
733  {
734  HANDLE hFile;
735 
736  /* Determine whether the DLL is present and accessible */
737  hFile = CreateFile( lpFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
738  FILE_ATTRIBUTE_NORMAL, NULL );
739  if( hFile == INVALID_HANDLE_VALUE )
740  return( NULL );
741  CloseHandle( hFile );
742 
743  return( LoadLibrary( lpFileName ) );
744  }
745 
746 HMODULE WINAPI loadFromSystemDirectory( IN_STRING LPCTSTR lpFileName )
747  {
748  char path[ MAX_PATH + 8 ];
749  const int fileNameLength = strlen( lpFileName ) + 1;
750  int pathLength;
751 
752  /* Get the path to a DLL in the system directory */
753  pathLength = \
754  GetSystemDirectory( path, MAX_PATH - ( fileNameLength + 8 ) );
755  if( pathLength < 1 || pathLength > MAX_PATH - ( fileNameLength + 8 ) )
756  return( NULL );
757  path[ pathLength++ ] = '\\';
758  memcpy( path + pathLength, lpFileName, fileNameLength );
759 
760  return( loadExistingLibrary( path ) );
761  }
762 
763 HMODULE WINAPI SafeLoadLibrary( IN_STRING LPCTSTR lpFileName )
764  {
765  typedef HRESULT ( WINAPI *SHGETFOLDERPATH )( HWND hwndOwner,
766  int nFolder, HANDLE hToken,
767  DWORD dwFlags, LPTSTR lpszPath );
768  typedef struct {
769  const char *dllName; const int dllNameLen;
770  } DLL_NAME_INFO;
771  static const DLL_NAME_INFO dllNameInfoTbl[] = {
772  { "Crypt32.dll", 11 }, { "ComCtl32.dll", 12 },
773  { "dnsapi.dll", 10 }, { "Mpr.dll", 7 },
774  { "NetAPI32.dll", 12 }, { "ODBC32.dll", 10 },
775  { "SetupAPI.dll", 12 }, { "SHFolder.dll", 12 },
776  { "Shell32.dll", 11 }, { "WinHTTP.dll", 11 },
777  { "wldap32.dll", 11 }, { "ws2_32.dll", 10 },
778  { "wsock32.dll", 11 },
779  { NULL, 0 }, { NULL, 0 }
780  };
781  SHGETFOLDERPATH pSHGetFolderPath;
782  HINSTANCE hShell32;
783  char path[ MAX_PATH + 8 ];
784  const int fileNameLength = strlen( lpFileName ) + 1;
785  int pathLength, i;
786  BOOLEAN gotPath = FALSE;
787 
788  /* If it's Win98 or NT4, just call LoadLibrary directly. In theory
789  we could try a few further workarounds (see io/file.c) but in
790  practice bending over backwards to fix search path issues under
791  Win98, which doesn't have ACLs to protect the files in the system
792  directory anyway, isn't going to achieve much */
793  if( getSysVar( SYSVAR_OSMAJOR ) <= 4 )
794  return( LoadLibrary( lpFileName ) );
795 
796  /* If it's already an absolute path, don't try and override it */
797  if( lpFileName[ 0 ] == '/' || \
798  ( fileNameLength > 3 && isAlpha( lpFileName[ 0 ] ) && \
799  lpFileName[ 1 ] == ':' && lpFileName[ 2 ] == '/' ) )
800  return( loadExistingLibrary( lpFileName ) );
801 
802  /* If it's a well-known DLL, load it from the system directory */
803  for( i = 0; dllNameInfoTbl[ i ].dllName != NULL && \
804  i < FAILSAFE_ARRAYSIZE( dllNameInfoTbl, DLL_NAME_INFO ); i++ )
805  {
806  if( dllNameInfoTbl[ i ].dllNameLen == fileNameLength - 1 && \
807  !strCompare( dllNameInfoTbl[ i ].dllName, lpFileName,
808  fileNameLength - 1 ) )
809  {
810  /* It's a standard system DLL, load it from the system
811  directory */
812  return( loadFromSystemDirectory( lpFileName ) );
813  }
814  }
815  ENSURES_N( i < FAILSAFE_ARRAYSIZE( dllNameInfoTbl, DLL_NAME_INFO ) );
816 
817  /* It's a system new enough to support SHGetFolderPath(), get the path
818  to the system directory. Unfortunately at this point we're in a
819  catch-22, in order to resolve SHGetFolderPath() we need to call
820  Shell32.dll and if an attacker uses that as the injection point then
821  they can give us a SHGetFolderPath() that'll do whatever they want.
822  There's no real way to fix this because we have to load Shell32 at
823  some point, either explicitly here or on program load, and since we
824  can't control the load path at either point we can't control what's
825  actually being loaded. In addition DLLs typically recursively load
826  more DLLs so even if we can control the path of the DLL that we load
827  directly we can't influence the paths over which further DLLs get
828  loaded. So unfortunately the best that we can do is make the
829  attacker work a little harder rather than providing a full fix */
830  hShell32 = loadFromSystemDirectory( "Shell32.dll" );
831  if( hShell32 != NULL )
832  {
833  pSHGetFolderPath = ( SHGETFOLDERPATH ) \
834  GetProcAddress( hShell32, "SHGetFolderPathA" );
835  if( pSHGetFolderPath != NULL && \
836  pSHGetFolderPath( NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT,
837  path ) == S_OK )
838  gotPath = TRUE;
839  FreeLibrary( hShell32 );
840  }
841  if( !gotPath )
842  {
843  /* If for some reason we couldn't get the path to the Windows system
844  directory this means that there's something drastically wrong,
845  don't try and go any further */
846  return( NULL );
847  }
848  pathLength = strlen( path );
849  if( pathLength < 3 || pathLength + 1 + fileNameLength > MAX_PATH )
850  {
851  /* Under WinNT and Win2K the LocalSystem account doesn't have its
852  own profile so SHGetFolderPath() will report success but return a
853  zero-length path if we're running as a service. To detect this
854  we have to check for a valid-looking path as well as performing a
855  general check on the return status.
856 
857  In effect prepending a zero-length path to the DLL name just
858  turns the call into a standard LoadLibrary() call, but we make
859  the action explicit here. Unfortunately this reintroduces the
860  security hole that we were trying to fix, and what's worse it's
861  for the LocalSystem account (sigh). */
862  return( LoadLibrary( lpFileName ) );
863  }
864  path[ pathLength++ ] = '\\';
865  memcpy( path + pathLength, lpFileName, fileNameLength );
866 
867  return( loadExistingLibrary( path ) );
868  }
869 
870 /* Windows NT/2000/XP/Vista support ACL-based access control mechanisms for
871  system objects so when we create objects such as files and threads we
872  give them an ACL that allows only the creator access. The following
873  functions return the security info needed when creating objects. The
874  interface for this has changed in every major OS release, although it
875  never got any better, just differently ugly. The following code uses the
876  original NT 3.1 interface, which works for all OS versions */
877 
878 /* The size of the buffer for ACLs and the user token */
879 
880 #define ACL_BUFFER_SIZE 1024
881 #define TOKEN_BUFFER_SIZE 256
882 
883 /* A composite structure to contain the various ACL structures. This is
884  required because ACL handling is a complex, multistage operation that
885  requires first creating an ACL and security descriptor to contain it,
886  adding an access control entry (ACE) to the ACL, adding the ACL as the
887  DACL of the security descriptor, and finally, wrapping the security
888  descriptor up in a security attributes structure that can be passed to
889  an object-creation function.
890 
891  The handling of the TOKEN_INFO is extraordinarily ugly because although
892  the TOKEN_USER struct as defined is only 8 bytes long, Windoze allocates
893  an extra 24 bytes after the end of the struct into which it stuffs data
894  that the SID pointer in the TOKEN_USER struct points to. This means that
895  we can't statically allocate memory of the size of the TOKEN_USER struct
896  but have to make it a pointer into a larger buffer that can contain the
897  additional invisible data tacked onto the end */
898 
899 typedef struct {
900  SECURITY_ATTRIBUTES sa;
901  SECURITY_DESCRIPTOR pSecurityDescriptor;
902  PACL pAcl;
903  PTOKEN_USER pTokenUser;
904  BYTE aclBuffer[ ACL_BUFFER_SIZE + 8 ];
905  BYTE tokenBuffer[ TOKEN_BUFFER_SIZE + 8 ];
906  } SECURITY_INFO;
907 
908 /* Initialise an ACL allowing only the creator access and return it to the
909  caller as an opaque value */
910 
911 CHECK_RETVAL_PTR \
912 void *initACLInfo( const int access )
913  {
914  SECURITY_INFO *securityInfo;
915  HANDLE hToken = INVALID_HANDLE_VALUE; /* See comment below */
916  BOOLEAN tokenOK = FALSE;
917 
918  /* Win95/98/ME don't have any security, return null security info */
919  if( getSysVar( SYSVAR_ISWIN95 ) )
920  return( NULL );
921 
922  /* Allocate and initialise the composite security info structure */
923  if( ( securityInfo = \
924  clAlloc( "initACLInfo", sizeof( SECURITY_INFO ) ) ) == NULL )
925  return( NULL );
926  memset( securityInfo, 0, sizeof( SECURITY_INFO ) );
927  securityInfo->pAcl = ( PACL ) securityInfo->aclBuffer;
928  securityInfo->pTokenUser = ( PTOKEN_USER ) securityInfo->tokenBuffer;
929 
930  /* Get the security token for this thread. First we try for the thread
931  token (which it typically only has when impersonating), if we don't
932  get that we use the token associated with the process. We also
933  initialise the hToken (above) even though it shouldn't be necessary
934  because Windows tries to read its contents, which indicates there
935  might be problems if it happens to start out with the wrong value */
936  if( OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken ) || \
937  OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
938  {
939  DWORD cbTokenUser;
940 
941  tokenOK = GetTokenInformation( hToken, TokenUser,
942  securityInfo->pTokenUser,
943  TOKEN_BUFFER_SIZE, &cbTokenUser );
944  CloseHandle( hToken );
945  }
946  if( !tokenOK )
947  {
948  clFree( "initACLInfo", securityInfo );
949  return( NULL );
950  }
951 
952  /* Set a security descriptor owned by the current user */
953  if( !InitializeSecurityDescriptor( &securityInfo->pSecurityDescriptor,
954  SECURITY_DESCRIPTOR_REVISION ) || \
955  !SetSecurityDescriptorOwner( &securityInfo->pSecurityDescriptor,
956  securityInfo->pTokenUser->User.Sid,
957  FALSE ) )
958  {
959  clFree( "initACLInfo", securityInfo );
960  return( NULL );
961  }
962 
963  /* Set up the discretionary access control list (DACL) with one access
964  control entry (ACE) for the current user */
965  if( !InitializeAcl( securityInfo->pAcl, ACL_BUFFER_SIZE,
966  ACL_REVISION ) || \
967  !AddAccessAllowedAce( securityInfo->pAcl, ACL_REVISION, access,
968  securityInfo->pTokenUser->User.Sid ) )
969  {
970  clFree( "initACLInfo", securityInfo );
971  return( NULL );
972  }
973 
974  /* Bind the DACL to the security descriptor */
975  if( !SetSecurityDescriptorDacl( &securityInfo->pSecurityDescriptor, TRUE,
976  securityInfo->pAcl, FALSE ) )
977  {
978  clFree( "initACLInfo", securityInfo );
979  return( NULL );
980  }
981 
982  assert( IsValidSecurityDescriptor( &securityInfo->pSecurityDescriptor ) );
983 
984  /* Finally, set up the security attributes structure */
985  securityInfo->sa.nLength = sizeof( SECURITY_ATTRIBUTES );
986  securityInfo->sa.bInheritHandle = FALSE;
987  securityInfo->sa.lpSecurityDescriptor = &securityInfo->pSecurityDescriptor;
988 
989  return( securityInfo );
990  }
991 
992 STDC_NONNULL_ARG( ( 1 ) ) \
993 void freeACLInfo( INOUT TYPECAST( SECURITY_INFO * ) void *securityInfoPtr )
994  {
995  SECURITY_INFO *securityInfo = ( SECURITY_INFO * ) securityInfoPtr;
996 
997  assert( securityInfoPtr == NULL || \
998  isWritePtr( securityInfoPtr, sizeof( SECURITY_INFO ) ) );
999 
1000  if( securityInfo == NULL )
1001  return;
1002  clFree( "freeACLInfo", securityInfo );
1003  }
1004 
1005 /* Extract the security info needed in Win32 API calls from the collection of
1006  security data that we set up earlier */
1007 
1008 STDC_NONNULL_ARG( ( 1 ) ) \
1009 void *getACLInfo( INOUT TYPECAST( SECURITY_INFO * ) void *securityInfoPtr )
1010  {
1011  SECURITY_INFO *securityInfo = ( SECURITY_INFO * ) securityInfoPtr;
1012 
1013  assert( securityInfo == NULL || \
1014  isWritePtr( securityInfo, sizeof( SECURITY_INFO ) ) );
1015 
1016  return( ( securityInfo == NULL ) ? NULL : &securityInfo->sa );
1017  }
1018 
1019 /* The DLL entry point. In theory we could also call:
1020 
1021  HeapSetInformation( GetProcessHeap(),
1022  HeapEnableTerminationOnCorruption, NULL, 0 );
1023 
1024  but this would have to be dynamically linked since it's only available
1025  for Vista and newer OSes, and it could also cause problems when cryptlib
1026  is linked with buggy applications that rely on the resilience of the heap
1027  manager in order to function since running the app with cryptlib will
1028  cause it to crash through no fault of cryptlib's. Since cryptlib is
1029  checked with Bounds Checker, Purify, and Valgrind, which are far more
1030  rigorous than the checking performed by the heap manager, there doesn't
1031  seem to be much advantage in doing this, but significant disadvantages
1032  if users' application bugs are caught by it */
1033 
1034 #if !( defined( NT_DRIVER ) || defined( STATIC_LIB ) )
1035 
1036 BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
1037  {
1038  static DWORD dwPlatform = ( DWORD ) CRYPT_ERROR;
1039 
1040  UNUSED_ARG( hinstDLL );
1041  UNUSED_ARG( lpvReserved );
1042 
1043  switch( fdwReason )
1044  {
1045  case DLL_PROCESS_ATTACH:
1046  /* Disable thread-attach notifications, which we don't do
1047  anything with and therefore don't need */
1048  DisableThreadLibraryCalls( hinstDLL );
1049 
1050  /* Set up the initialisation lock in the kernel */
1051  preInit();
1052  break;
1053 
1054  case DLL_PROCESS_DETACH:
1055  /* Delete the initialisation lock in the kernel */
1056  postShutdown();
1057  break;
1058 
1059  case DLL_THREAD_ATTACH:
1060  case DLL_THREAD_DETACH:
1061  break;
1062  }
1063 
1064  return( TRUE );
1065  }
1066 
1067 /* Idiot-proofing. Yes, there really are people who'll try and register a
1068  straight DLL */
1069 
1070 #define MB_OK 0x00000000L
1071 #define MB_ICONQUESTION 0x00000020L
1072 
1073 int WINAPI MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption,
1074  UINT uType );
1075 
1076 #ifndef _WIN64
1077  #pragma comment( linker, "/export:DllRegisterServer=_DllRegisterServer@0,PRIVATE" )
1078 #endif /* Win64 */
1079 
1080 STDAPI DllRegisterServer( void )
1081  {
1082  MessageBoxA( NULL, "Why are you trying to register the cryptlib DLL?\n"
1083  "It's just a standard Windows DLL, there's nothing\nto be "
1084  "registered.", "ESO Error",
1085  MB_ICONQUESTION | MB_OK );
1086  return( E_NOINTERFACE );
1087  }
1088 #endif /* !( NT_DRIVER || STATIC_LIB ) */
1089 
1090 /* Borland's archaic compilers don't recognise DllMain() but still use the
1091  OS/2-era DllEntryPoint(), so we have to alias it to DllMain() in order
1092  for things to be initialised properly */
1093 
1094 #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 )
1095 
1096 BOOL WINAPI DllEntryPoint( HINSTANCE hinstDLL, DWORD fdwReason, \
1097  LPVOID lpvReserved )
1098  {
1099  return( DllMain( hinstDLL, fdwReason, lpvReserved ) );
1100  }
1101 #endif /* BC++ */
1102 
1103 #elif defined( __WIN16__ )
1104 
1105 /* WinMain() and WEP() under Win16 are intended for DLL initialisation,
1106  however it isn't possible to reliably do anything terribly useful in these
1107  routines. The reason for this is that the WinMain/WEP functions are
1108  called by the windows module loader, which has a very limited workspace
1109  and can cause peculiar behaviour for some functions (allocating/freeing
1110  memory and loading other modules from these routines is unreliable), the
1111  order in which WinMain() and WEP() will be called for a set of DLL's is
1112  unpredictable (sometimes WEP doesn't seem to be called at all), and they
1113  can't be tracked by a standard debugger. This is why MS have
1114  xxxRegisterxxx() and xxxUnregisterxxx() functions in their DLL's.
1115 
1116  Under Win16 on a Win32 system this isn't a problem because the module
1117  loader has been rewritten to work properly, but it isn't possible to get
1118  reliable performance under pure Win16, so the DLL entry/exit routines here
1119  do almost nothing, with the real work being done in cryptInit()/
1120  cryptEnd() */
1121 
1122 HWND hInst;
1123 
1124 int CALLBACK LibMain( HINSTANCE hInstance, WORD wDataSeg, WORD wHeapSize, \
1125  LPSTR lpszCmdLine )
1126  {
1127  /* Remember the proc instance for later */
1128  hInst = hInstance;
1129 
1130  return( TRUE );
1131  }
1132 
1133 int CALLBACK WEP( int nSystemExit )
1134  {
1135  switch( nSystemExit )
1136  {
1137  case WEP_SYSTEM_EXIT:
1138  /* System is shutting down */
1139  break;
1140 
1141  case WEP_FREE_DLL:
1142  /* DLL reference count = 0, DLL-only shutdown */
1143  break;
1144  }
1145 
1146  return( TRUE );
1147  }
1148 
1149 /* Check whether we're running inside a VM, which is a potential risk for
1150  cryptovariables. It gets quite tricky to detect the various VMs so for
1151  now the only one that we detect is the most widespread one, VMware */
1152 
1153 #if defined( __WIN32__ ) && !defined( NO_ASM )
1154 
1155 BOOLEAN isRunningInVM( void )
1156  {
1157  unsigned int magicValue, version;
1158 
1159  __try {
1160  __asm {
1161  push eax
1162  push ebx
1163  push ecx
1164  push edx
1165 
1166  /* Check for VMware via the VMware guest-to-host communications
1167  channel */
1168  mov eax, 'VMXh' /* VMware magic value 0x564D5868 */
1169  xor ebx, ebx /* Clear parameters register */
1170  mov ecx, 0Ah /* Get-version command */
1171  mov dx, 'VX' /* VMware I/O port 0x5658 */
1172  in eax, dx /* Perform VMware call */
1173  mov magicValue, ebx /* VMware magic value */
1174  mov version, ecx /* VMware version */
1175 
1176  pop edx
1177  pop ecx
1178  pop ebx
1179  pop eax
1180  }
1181  } __except (EXCEPTION_EXECUTE_HANDLER) {}
1182 
1183  return( magicValue == 'VMXh' ) ? TRUE : FALSE );
1184  }
1185 #else
1186 
1187 BOOLEAN isRunningInVM( void )
1188  {
1189  return( FALSE );
1190  }
1191 #endif /* __WIN32__ && !NO_ASM */
1192 
1193 /****************************************************************************
1194 * *
1195 * Windows CE *
1196 * *
1197 ****************************************************************************/
1198 
1199 #elif defined( __WINCE__ )
1200 
1201 /* Windows CE doesn't provide ANSI standard time functions (although it'd be
1202  relatively easy to do so, and they are in fact provided in MFC), so we
1203  have to provide our own */
1204 
1205 CHECK_RETVAL \
1206 static LARGE_INTEGER *getTimeOffset( void )
1207  {
1208  static LARGE_INTEGER timeOffset = { 0 };
1209 
1210  /* Get the difference between the ANSI/ISO C time epoch and the Windows
1211  time epoch if we haven't already done so (we could also hardcode this
1212  in as 116444736000000000LL) */
1213  if( timeOffset.QuadPart == 0 )
1214  {
1215  SYSTEMTIME ofsSystemTime;
1216  FILETIME ofsFileTime;
1217 
1218  memset( &ofsSystemTime, 0, sizeof( SYSTEMTIME ) );
1219  ofsSystemTime.wYear = 1970;
1220  ofsSystemTime.wMonth = 1;
1221  ofsSystemTime.wDay = 1;
1222  SystemTimeToFileTime( &ofsSystemTime, &ofsFileTime );
1223  timeOffset.HighPart = ofsFileTime.dwHighDateTime;
1224  timeOffset.LowPart = ofsFileTime.dwLowDateTime;
1225  }
1226 
1227  return( &timeOffset );
1228  }
1229 
1230 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1231 static time_t fileTimeToTimeT( const FILETIME *fileTime )
1232  {
1233  const LARGE_INTEGER *timeOffset = getTimeOffset();
1234  LARGE_INTEGER largeInteger;
1235 
1236  /* Convert a Windows FILETIME to a time_t by dividing by
1237  10,000,000 (to go from 100ns ticks to 1s ticks) */
1238  largeInteger.HighPart = fileTime->dwHighDateTime;
1239  largeInteger.LowPart = fileTime->dwLowDateTime;
1240  largeInteger.QuadPart = ( largeInteger.QuadPart - \
1241  timeOffset->QuadPart ) / 10000000L;
1242  if( sizeof( time_t ) == 4 && \
1243  largeInteger.QuadPart > 0x80000000UL )
1244  {
1245  /* time_t is 32 bits but the converted time is larger than a 32-bit
1246  signed value, indicate that we couldn't convert it. In theory
1247  we could check for largeInteger.HighPart == 0 and perform a
1248  second check to see if time_t is unsigned, but it's unlikely that
1249  this change would be made to the VC++ runtime time_t since it'd
1250  break too many existing apps */
1251  return( -1 );
1252  }
1253  return( ( time_t ) largeInteger.QuadPart );
1254  }
1255 
1256 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1257 static void timeTToFileTime( FILETIME *fileTime, const time_t timeT )
1258  {
1259  const LARGE_INTEGER *timeOffset = getTimeOffset();
1260  LARGE_INTEGER largeInteger = { timeT };
1261 
1262  /* Convert a time_t to a Windows FILETIME by multiplying by
1263  10,000,000 (to go from 1s ticks to 100ns ticks) */
1264  largeInteger.QuadPart = ( largeInteger.QuadPart * 10000000L ) + \
1265  timeOffset->QuadPart;
1266  fileTime->dwHighDateTime = largeInteger.HighPart;
1267  fileTime->dwLowDateTime = largeInteger.LowPart;
1268  }
1269 
1270 time_t time( time_t *timePtr )
1271  {
1272  FILETIME fileTime;
1273 #ifdef __WINCE__
1274  SYSTEMTIME systemTime;
1275 #endif /* __WINCE__ */
1276 
1277  assert( timePtr == NULL );
1278 
1279  /* Get the time via GetSystemTimeAsFileTime(). Windows CE doesn't have
1280  the unified call so we have to assemble it from discrete calls */
1281 #ifdef __WINCE__
1282  GetSystemTime( &systemTime );
1283  SystemTimeToFileTime( &systemTime, &fileTime );
1284 #else
1285  GetSystemTimeAsFileTime( &fileTime );
1286 #endif /* Win32 vs. WinCE */
1287 
1288  return( fileTimeToTimeT( &fileTime ) );
1289  }
1290 
1291 time_t mktime( struct tm *tmStruct )
1292  {
1293  SYSTEMTIME systemTime;
1294  FILETIME fileTime;
1295 
1296  assert( isWritePtr( tmStruct, sizeof( struct tm ) ) );
1297 
1298  /* Use SystemTimeToFileTime() as a mktime() substitute. The input time
1299  seems to be treated as local time, so we have to convert it to GMT
1300  before we return it */
1301  memset( &systemTime, 0, sizeof( SYSTEMTIME ) );
1302  systemTime.wYear = tmStruct->tm_year + 1900;
1303  systemTime.wMonth = tmStruct->tm_mon + 1;
1304  systemTime.wDay = tmStruct->tm_mday;
1305  systemTime.wHour = tmStruct->tm_hour;
1306  systemTime.wMinute = tmStruct->tm_min;
1307  systemTime.wSecond = tmStruct->tm_sec;
1308  SystemTimeToFileTime( &systemTime, &fileTime );
1309  LocalFileTimeToFileTime( &fileTime, &fileTime );
1310 
1311  return( fileTimeToTimeT( &fileTime ) );
1312  }
1313 
1314 struct tm *gmtime( const time_t *timePtr )
1315  {
1316  static struct tm tmStruct;
1317  SYSTEMTIME systemTime;
1318  FILETIME fileTime;
1319 
1320  assert( isReadPtr( timePtr, sizeof( time_t ) ) );
1321 
1322  /* Use FileTimeToSystemTime() as a gmtime() substitute. Note that this
1323  function, like its original ANSI/ISO C counterpart, is not thread-
1324  safe */
1325  timeTToFileTime( &fileTime, *timePtr );
1326  FileTimeToSystemTime( &fileTime, &systemTime );
1327  memset( &tmStruct, 0, sizeof( struct tm ) );
1328  tmStruct.tm_year = systemTime.wYear - 1900;
1329  tmStruct.tm_mon = systemTime.wMonth - 1;
1330  tmStruct.tm_mday = systemTime.wDay;
1331  tmStruct.tm_hour = systemTime.wHour;
1332  tmStruct.tm_min = systemTime.wMinute;
1333  tmStruct.tm_sec = systemTime.wSecond;
1334 
1335  return( &tmStruct );
1336  }
1337 
1338 /* When running in debug mode we provide a debugging printf() that sends its
1339  output to the debug console. This is normally done via a macro in a
1340  header file that remaps the debug-output macros to the appropriate
1341  function, but WinCE's NKDbgPrintfW() requires widechar strings that
1342  complicate the macros so we provide a function that performs the
1343  conversion before outputting the text */
1344 
1345 #if !defined( NDEBUG )
1346 
1347 int debugPrintf( const char *format, ... )
1348  {
1349  va_list argPtr;
1350  char buffer[ 1024 ];
1351  wchar_t wcBuffer[ 1024 ];
1352  int length, status;
1353 
1354  va_start( argPtr, format );
1355  length = vsprintf( buffer, format, argPtr );
1356  va_end( argPtr );
1357  status = asciiToUnicode( wcBuffer, 1024, buffer, length );
1358  if( cryptStatusOK( status ) )
1359  NKDbgPrintfW( L"%s", wcBuffer );
1360  return( length );
1361  }
1362 #endif /* Debug build */
1363 
1364 /* Windows CE systems need to convert characters from ASCII <-> Unicode
1365  before/after they're read/written to external formats, the following
1366  functions perform the necessary conversion.
1367 
1368  winnls.h was already included via the global include of windows.h, however
1369  it isn't needed for any other part of cryptlib so it was disabled via
1370  NONLS. Since winnls.h is now locked out, we have to un-define the guards
1371  used earlier to get it included */
1372 
1373 #undef _WINNLS_
1374 #undef NONLS
1375 #include <winnls.h>
1376 
1377 int asciiToUnicode( wchar_t *dest, const int destMaxLen,
1378  const char *src, const int length )
1379  {
1380  int status;
1381 
1382  assert( isReadPtr( src, length ) );
1383  assert( isWritePtr( dest, destMaxLen ) );
1384 
1385  /* Note that this function doens't terminate the string if the output is
1386  filled, so it's essential that the caller check the return value to
1387  ensure that they're getting a well-formed string */
1388  status = MultiByteToWideChar( GetACP(), 0, src, destMaxLen, dest,
1389  length );
1390  return( status <= 0 ? CRYPT_ERROR_BADDATA : status * sizeof( wchar_t ) );
1391  }
1392 
1393 int unicodeToAscii( char *dest, const int destMaxLen,
1394  const wchar_t *src, const int length )
1395  {
1396  size_t destLen;
1397  int status;
1398 
1399  assert( isReadPtr( src, length ) );
1400  assert( isWritePtr( dest, destMaxLen ) );
1401 
1402  /* Convert the string, overriding the system default char '?', which
1403  causes problems if the output is used as a filename. This function
1404  has stupid semantics in that instead of returning the number of bytes
1405  written to the output it returns the number of bytes specified as
1406  available in the output buffer, zero-filling the rest (in addition as
1407  for MultiByteToWideChar() it won't terminate the string if the output
1408  is filled). Because there's no way to tell how long the resulting
1409  string actually is we have to use wcstombs() instead, which is
1410  unfortunate because there's nothing that we can do with the maxLength
1411  parameter */
1412 #if 0
1413  status = WideCharToMultiByte( GetACP(), 0, src, length, dest,
1414  length * sizeof( wchar_t ), "_", NULL );
1415  return( ( status <= 0 ) ? CRYPT_ERROR_BADDATA : wcslen( dest ) );
1416 #else
1417  status = wcstombs_s( &destLen, dest, destMaxLen, src,
1418  length * sizeof( wchar_t ) );
1419  return( ( status <= 0 ) ? CRYPT_ERROR_BADDATA : status );
1420 #endif
1421  }
1422 
1423 BOOL WINAPI DllMain( HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved )
1424  {
1425  UNUSED_ARG( hinstDLL );
1426  UNUSED_ARG( lpvReserved );
1427 
1428  switch( dwReason )
1429  {
1430  case DLL_PROCESS_ATTACH:
1431  /* Disable thread-attach notifications, which we don't do
1432  anything with and therefore don't need */
1433  DisableThreadLibraryCalls( hinstDLL );
1434 
1435  /* Set up the initialisation lock in the kernel */
1436  preInit();
1437  break;
1438 
1439  case DLL_PROCESS_DETACH:
1440  /* Delete the initialisation lock in the kernel */
1441  postShutdown();
1442  break;
1443 
1444  case DLL_THREAD_ATTACH:
1445  case DLL_THREAD_DETACH:
1446  break;
1447  }
1448 
1449  return( TRUE );
1450  }
1451 #endif /* OS-specific support */
1452 
1453 /****************************************************************************
1454 * *
1455 * Minimal Safe String Function Support *
1456 * *
1457 ****************************************************************************/
1458 
1459 #ifdef NO_NATIVE_STRLCPY
1460 
1461 /* Copy and concatenate a string, truncating it if necessary to fit the
1462  destination buffer. Unfortunately the TR 24731 functions don't do this,
1463  while the OpenBSD safe-string functions do (but don't implement any of
1464  the rest of the TR 24731 functionality). Because the idiot maintainer
1465  of glibc objects to these functions (even Microsoft recognise their
1466  utility with the _TRUNCATE semantics for strcpy_s/strcat_s), everyone has
1467  to manually implement them in their code, as we do here. Note that these
1468  aren't completely identical to the OpenBSD functions, in order to fit the
1469  TR 24731 pattern we make the length the second paramter, and give them a
1470  TR 24731-like _s suffix to make them distinct from the standard OpenBSD
1471  ones (a macro in os_spec.h is sufficient to map this to the proper
1472  functions where they're available in libc) */
1473 
1474 int strlcpy_s( char *dest, const int destLen, const char *src )
1475  {
1476  int i;
1477 
1478  assert( isWritePtr( dest, destLen ) );
1479  assert( isReadPtr( src, 1 ) );
1480 
1481  /* Copy as much as we can of the source string onto the end of the
1482  destination string */
1483  for( i = 0; i < destLen - 1 && *src != '\0'; i++ )
1484  dest[ i ] = *src++;
1485  dest[ i ] = '\0';
1486 
1487  return( 1 );
1488  }
1489 
1490 int strlcat_s( char *dest, const int destLen, const char *src )
1491  {
1492  int i;
1493 
1494  assert( isWritePtr( dest, destLen ) );
1495 
1496  /* See how long the existing destination string is */
1497  for( i = 0; i < destLen && dest[ i ] != '\0'; i++ );
1498  if( i >= destLen )
1499  {
1500  DEBUG_DIAG(( "Overflow in strlcat_s" ));
1501  assert( DEBUG_WARN );
1502  dest[ destLen - 1 ] = '\0';
1503 
1504  return( 1 );
1505  }
1506 
1507  /* Copy as much as we can of the source string onto the end of the
1508  destination string */
1509  while( i < destLen - 1 && *src != '\0' )
1510  dest[ i++ ] = *src++;
1511  dest[ i ] = '\0';
1512 
1513  return( 1 );
1514  }
1515 #endif /* NO_NATIVE_STRLCPY */
1516 
1517 /****************************************************************************
1518 * *
1519 * SysVars Support *
1520 * *
1521 ****************************************************************************/
1522 
1523 #if defined( __WIN32__ ) && !defined( _M_X64 ) && !defined( NO_ASM )
1524 
1525 CHECK_RETVAL \
1526 static int getHWInfo( void )
1527  {
1528  BOOLEAN hasAdvFeatures = 0;
1529  char vendorID[ 12 + 8 ];
1530  unsigned long processorID, featureFlags;
1531  int sysCaps = 0;
1532 
1533  /* Check whether the CPU supports extended features like CPUID and
1534  RDTSC, and get any info that we need related to this. There is an
1535  IsProcessorFeaturePresent() function, but all that this provides is
1536  an indication of the availability of rdtsc (alongside some stuff that
1537  we don't care about, like MMX and 3DNow). Since we still need to
1538  check for the presence of other features, we do the whole thing
1539  ourselves */
1540  __asm {
1541  /* Detect the CPU type */
1542  pushfd
1543  pop eax /* Get EFLAGS in eax */
1544  mov ebx, eax /* Save a copy for later */
1545  xor eax, 0x200000 /* Toggle the CPUID bit */
1546  push eax
1547  popfd /* Update EFLAGS */
1548  pushfd
1549  pop eax /* Get updated EFLAGS back in eax */
1550  push ebx
1551  popfd /* Restore original EFLAGS */
1552  xor eax, ebx /* Check if we could toggle CPUID bit */
1553  jz noCPUID /* Nope, we can't do anything further */
1554  mov [hasAdvFeatures], 1 /* Remember that we have CPUID */
1555  mov [sysCaps], HWCAP_FLAG_RDTSC /* Remember that we have RDTSC */
1556 
1557  /* We have CPUID, see what we've got */
1558  xor ecx, ecx
1559  xor edx, edx /* Tell VC++ that ECX, EDX will be trashed */
1560  xor eax, eax /* CPUID function 0: Get vendor ID */
1561  cpuid
1562  mov dword ptr [vendorID], ebx
1563  mov dword ptr [vendorID+4], edx
1564  mov dword ptr [vendorID+8], ecx /* Save vendor ID string */
1565  mov eax, 1 /* CPUID function 1: Get processor info */
1566  cpuid
1567  mov [processorID], eax /* Save processor ID */
1568  mov [featureFlags], ecx /* Save processor feature info */
1569  noCPUID:
1570  }
1571 
1572  /* If there's no CPUID support, there are no special HW capabilities
1573  available */
1574  if( !hasAdvFeatures )
1575  return( HWCAP_FLAG_NONE );
1576 
1577  /* If there's a vendor ID present, check for vendor-specific special
1578  features */
1579  if( !memcmp( vendorID, "CentaurHauls", 12 ) )
1580  {
1581  __asm {
1582  xor ebx, ebx
1583  xor ecx, ecx /* Tell VC++ that EBX, ECX will be trashed */
1584  mov eax, 0xC0000000 /* Centaur extended CPUID info */
1585  cpuid
1586  cmp eax, 0xC0000001 /* Need at least release 2 ext.feature set */
1587  jb endCheck /* No extended info available */
1588  mov eax, 0xC0000001 /* Centaur extended feature flags */
1589  cpuid
1590  mov eax, edx /* Work with saved copy of feature flags */
1591  and eax, 01100b
1592  cmp eax, 01100b /* Check for RNG present + enabled flags */
1593  jz noRNG /* No, RNG not present or enabled */
1594  or [sysCaps], HWCAP_FLAG_XSTORE /* Remember that we have a HW RNG */
1595  noRNG:
1596  mov eax, edx
1597  and eax, 011000000b
1598  cmp eax, 011000000b /* Check for ACE present + enabled flags */
1599  jz noACE /* No, ACE not present or enabled */
1600  or [sysCaps], HWCAP_FLAG_XCRYPT /* Remember that we have HW AES */
1601  noACE:
1602  mov eax, edx
1603  and eax, 0110000000000b
1604  cmp eax, 0110000000000b /* Check for PHE present + enabled flags */
1605  jz noPHE /* No, PHE not present or enabled */
1606  or [sysCaps], HWCAP_FLAG_XSHA /* Remember that we have HW SHA-1/SHA-2 */
1607  noPHE:
1608  mov eax, edx
1609  and eax, 011000000000000b
1610  cmp eax, 011000000000000b /* Check for PMM present + enabled flags */
1611  jz endCheck /* No, PMM not present or enabled */
1612  or [sysCaps], HWCAP_FLAG_MONTMUL /* Remember that we have HW bignum */
1613  endCheck:
1614  }
1615  }
1616  if( !memcmp( vendorID, "AuthenticAMD", 12 ) )
1617  {
1618  /* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */
1619  if( ( processorID & 0x05A0 ) == 0x05A0 )
1620  sysCaps |= HWCAP_FLAG_TRNG;
1621  }
1622  if( !memcmp( vendorID, "GenuineIntel", 12 ) )
1623  {
1624  /* Check for hardware AES support */
1625  if( featureFlags & ( 1 << 25 ) )
1626  sysCaps |= HWCAP_FLAG_AES;
1627 
1628  /* Check for the return of a hardware RNG */
1629  if( featureFlags & ( 1 << 30 ) )
1630  sysCaps |= HWCAP_FLAG_RDRAND;
1631  }
1632 
1633  return( sysCaps );
1634  }
1635 
1636 #elif defined( __WIN32__ ) && defined( _M_X64 )
1637 
1638 /* 64-bit VC++ doesn't allow inline asm, but does provide the __cpuid()
1639  builtin to perform the operation above. We don't guard this with the
1640  NO_ASM check because it's not (technically) done with inline asm,
1641  although it's a bit unclear whether an intrinsic qualifies as asm or
1642  C */
1643 
1644 #pragma intrinsic( __cpuid )
1645 
1646 typedef struct { unsigned int eax, ebx, ecx, edx; } CPUID_INFO;
1647 
1648 STDC_NONNULL_ARG( ( 1 ) ) \
1649 static void cpuID( OUT CPUID_INFO *result, const int type )
1650  {
1651  int intResult[ 4 ]; /* That's what the function prototype says */
1652 
1653  /* Clear return value */
1654  memset( result, 0, sizeof( CPUID_INFO ) );
1655 
1656  /* Get the CPUID data and copy it back to the caller */
1657  __cpuid( intResult, type );
1658  result->eax = intResult[ 0 ];
1659  result->ebx = intResult[ 1 ];
1660  result->ecx = intResult[ 2 ];
1661  result->edx = intResult[ 3 ];
1662  }
1663 
1664 CHECK_RETVAL \
1665 static int getHWInfo( void )
1666  {
1667  CPUID_INFO cpuidInfo;
1668  char vendorID[ 12 + 8 ];
1669  int *vendorIDptr = ( int * ) vendorID;
1670  unsigned long processorID, featureFlags;
1671  int sysCaps = HWCAP_FLAG_RDTSC; /* x86-64 always has RDTSC */
1672 
1673  /* Get any CPU info that we need. There is an
1674  IsProcessorFeaturePresent() function, but all that this provides is
1675  an indication of the availability of rdtsc (alongside some stuff that
1676  we don't care about, like MMX and 3DNow). Since we still need to
1677  check for the presence of other features, we do the whole thing
1678  ourselves */
1679  cpuID( &cpuidInfo, 0 );
1680  vendorIDptr[ 0 ] = cpuidInfo.ebx;
1681  vendorIDptr[ 1 ] = cpuidInfo.edx;
1682  vendorIDptr[ 2 ] = cpuidInfo.ecx;
1683  cpuID( &cpuidInfo, 1 );
1684  processorID = cpuidInfo.eax;
1685  featureFlags = cpuidInfo.ecx;
1686 
1687  /* Check for vendor-specific special features */
1688  if( !memcmp( vendorID, "CentaurHauls", 12 ) )
1689  {
1690  /* Get the Centaur extended CPUID info and check whether the feature-
1691  flags read capability is present. VIA only announced their 64-
1692  bit CPUs in mid-2010 and availability is limited so it's
1693  uncertain whether this code will ever be exercised, but we provide
1694  it anyway for compatibility with the 32-bit equivalent */
1695  cpuID( &cpuidInfo, 0xC0000000 );
1696  if( cpuidInfo.eax >= 0xC0000001 )
1697  {
1698  /* Get the Centaur extended feature flags */
1699  cpuID( &cpuidInfo, 0xC0000000 );
1700  if( ( cpuidInfo.edx & 0x000C ) == 0x000C )
1701  sysCaps |= HWCAP_FLAG_XSTORE;
1702  if( ( cpuidInfo.edx & 0x00C0 ) == 0x00C0 )
1703  sysCaps |= HWCAP_FLAG_XCRYPT;
1704  if( ( cpuidInfo.edx & 0x0C00 ) == 0x0C00 )
1705  sysCaps |= HWCAP_FLAG_XSHA;
1706  if( ( cpuidInfo.edx & 0x3000 ) == 0x3000 )
1707  sysCaps |= HWCAP_FLAG_MONTMUL;
1708  }
1709  }
1710  if( !memcmp( vendorID, "AuthenticAMD", 12 ) )
1711  {
1712  /* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */
1713  if( ( processorID & 0x05A0 ) == 0x05A0 )
1714  sysCaps |= HWCAP_FLAG_TRNG;
1715  }
1716  if( !memcmp( vendorID, "GenuineIntel", 12 ) )
1717  {
1718  /* Check for hardware AES support */
1719  if( featureFlags & ( 1 << 25 ) )
1720  sysCaps |= HWCAP_FLAG_AES;
1721 
1722  /* Check for the return of a hardware RNG */
1723  if( featureFlags & ( 1 << 30 ) )
1724  sysCaps |= HWCAP_FLAG_RDRAND;
1725  }
1726 
1727  return( sysCaps );
1728  }
1729 
1730 #elif defined( __GNUC__ ) && defined( __i386__ ) && !defined( NO_ASM )
1731 
1732 #if HWCAP_FLAG_RDTSC != 0x01
1733  #error Need to sync HWCAP_FLAG_RDTSC with equivalent asm definition
1734 #endif /* HWCAP_FLAG_RDTSC */
1735 
1736 CHECK_RETVAL \
1737 static int getHWInfo( void )
1738  {
1739  char vendorID[ 12 + 8 ];
1740  unsigned long processorID, featureFlags;
1741  int hasAdvFeatures = 0, sysCaps = 0;
1742 
1743  /* Check whether the CPU supports extended features like CPUID and
1744  RDTSC, and get any info that we need related to this. The use of ebx
1745  is a bit problematic because gcc (via the IA32 ABI) uses ebx to store
1746  the address of the global offset table and gets rather upset if it
1747  gets changed, so we have to save/restore it around the cpuid call.
1748  We have to be particularly careful here because ebx is used
1749  implicitly in references to sysCaps (which is a static int), so we
1750  save it as close to the cpuid instruction as possible and restore it
1751  immediately afterwards, away from any memory-referencing instructions
1752  that implicitly use ebx */
1753  asm volatile( "pushf\n\t"
1754  "popl %%eax\n\t"
1755  "movl %%eax, %%ecx\n\t"
1756  "xorl $0x200000, %%eax\n\t"
1757  "pushl %%eax\n\t"
1758  "popf\n\t"
1759  "pushf\n\t"
1760  "popl %%eax\n\t"
1761  "pushl %%ecx\n\t"
1762  "popf\n\t"
1763  "xorl %%ecx, %%eax\n\t"
1764  "jz noCPUID\n\t"
1765  "movl $1, %[hasAdvFeatures]\n\t"/* hasAdvFeatures = TRUE */
1766  "movl %[HW_FLAG_RDTSC], %[sysCaps]\n\t" /* sysCaps = HWCAP_FLAG_RDTSC */
1767  "pushl %%ebx\n\t" /* Save PIC register */
1768  "xorl %%eax, %%eax\n\t" /* CPUID function 0: Get vendor ID */
1769  "cpuid\n\t"
1770  "leal %2, %%eax\n\t"
1771  "movl %%ebx, (%%eax)\n\t"
1772  "movl %%edx, 4(%%eax)\n\t"
1773  "movl %%ecx, 8(%%eax)\n\t"
1774  "movl $1, %%eax\n\t" /* CPUID function 1: Get processor info */
1775  "cpuid\n\t"
1776  "leal %3, %%ebx\n\t"
1777  "movl %%eax, (%%ebx)\n\t" /* processorID */
1778  "leal %4, %%ebx\n\t"
1779  "movl %%ecx, (%%ebx)\n\t" /* featureFlags */
1780  "popl %%ebx\n" /* Restore PIC register */
1781  "noCPUID:\n\n"
1782 #if 0 /* See comment in tools/ccopts.sh for why this is disabled */
1783  ".section .note.GNU-stack, \"\", @progbits; .previous\n"
1784  /* Mark the stack as non-executable. This is
1785  undocumented outside of mailing-list postings
1786  and a bit hit-and-miss, but having at least
1787  one of these in included asm code doesn't
1788  hurt */
1789 #endif /* 0 */
1790  : [hasAdvFeatures] "=m"(hasAdvFeatures),/* Output */
1791  [sysCaps] "=m"(sysCaps),
1792  [vendorID] "=m"(vendorID),
1793  [processorID] "=m"(processorID),
1794  [featureFlags] "=m"(featureFlags)
1795  : [HW_FLAG_RDTSC] "i"(HWCAP_FLAG_RDTSC)/* Input */
1796  : "%eax", "%ecx", "%edx" /* Registers clobbered */
1797  );
1798 
1799  /* If there's no CPUID support, there are no special HW capabilities
1800  available */
1801  if( !hasAdvFeatures )
1802  return( HWCAP_FLAG_NONE );
1803 
1804  /* If there's a vendor ID present, check for vendor-specific special
1805  features. Again, we have to be extremely careful with ebx */
1806  if( !memcmp( vendorID, "CentaurHauls", 12 ) )
1807  {
1808  asm volatile( "pushl %%ebx\n\t" /* Save PIC register */
1809  "movl $0xC0000000, %%eax\n\t"
1810  "cpuid\n\t"
1811  "popl %%ebx\n\t" /* Restore PIC register */
1812  "cmpl $0xC0000001, %%eax\n\t"
1813  "jb endCheck\n\t"
1814  "pushl %%ebx\n\t" /* Re-save PIC register */
1815  "movl $0xC0000001, %%eax\n\t"
1816  "cpuid\n\t"
1817  "popl %%ebx\n\t" /* Re-restore PIC register */
1818  "movl %%edx, %%eax\n\t"
1819  "andl $0xC, %%edx\n\t"
1820  "cmpl $0xC, %%edx\n\t"
1821  "jz noRNG\n\t"
1822  "orl %[HW_FLAG_XSTORE], %[sysCaps]\n" /* HWCAP_FLAG_XSTORE */
1823  "noRNG:\n\t"
1824  "movl %%edx, %%eax\n\t"
1825  "andl $0xC0, %%eax\n\t"
1826  "cmpl $0xC0, %%eax\n\t"
1827  "jz noACE\n\t"
1828  "orl %[HW_FLAG_XCRYPT], %[sysCaps]\n" /* HWCAP_FLAG_XCRYPT */
1829  "noACE:\n\t"
1830  "movl %%edx, %%eax\n\t"
1831  "andl $0xC00, %%eax\n\t"
1832  "cmpl $0xC00, %%eax\n\t"
1833  "jz noPHE\n\t"
1834  "orl %[HW_FLAG_XSHA], %[sysCaps]\n" /* HWCAP_FLAG_XSHA */
1835  "noPHE:\n\t"
1836  "movl %%edx, %%eax\n\t"
1837  "andl $0x3000, %%eax\n\t"
1838  "cmpl $0x3000, %%eax\n\t"
1839  "jz endCheck\n\t"
1840  "orl %[HW_FLAG_MONTMUL], %[sysCaps]\n" /* HWCAP_FLAG_MONTMUL */
1841  "endCheck:\n\n"
1842  : [sysCaps] "=m"(sysCaps) /* Output */
1843  : [HW_FLAG_XSTORE] "i"(HWCAP_FLAG_XSTORE),/* Input */
1844  [HW_FLAG_XCRYPT] "i"(HWCAP_FLAG_XCRYPT),
1845  [HW_FLAG_XSHA] "i"(HWCAP_FLAG_XSHA),
1846  [HW_FLAG_MONTMUL] "i"(HWCAP_FLAG_MONTMUL)
1847  : "%eax", "%ecx", "%edx" /* Registers clobbered */
1848  );
1849  }
1850  if( !memcmp( vendorID, "AuthenticAMD", 12 ) )
1851  {
1852  /* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */
1853  if( ( processorID & 0x05A0 ) == 0x05A0 )
1854  sysCaps |= HWCAP_FLAG_TRNG;
1855  }
1856  if( !memcmp( vendorID, "GenuineIntel", 12 ) )
1857  {
1858  /* Check for hardware AES support */
1859  if( featureFlags & ( 1 << 25 ) )
1860  sysCaps |= HWCAP_FLAG_AES;
1861 
1862  /* Check for the return of a hardware RNG */
1863  if( featureFlags & ( 1 << 30 ) )
1864  sysCaps |= HWCAP_FLAG_RDRAND;
1865  }
1866 
1867  return( sysCaps );
1868  }
1869 
1870 #elif defined( __GNUC__ ) && ( defined( __arm ) || defined( __arm__ ) ) && \
1871  !defined( NO_ASM ) && 0 /* See comment below */
1872 
1873 CHECK_RETVAL \
1874 static int getHWInfo( void )
1875  {
1876  int processorID;
1877 
1878  /* Get the ARM CPU type information. Unfortunately this instruction
1879  (and indeed virtually all of the very useful CP15 registers) are
1880  inaccessible from user mode so it's not safe to perform any of these
1881  operations. If you're running an embedded OS that runs natively in
1882  supervisor mode then you can try enabling this function to check
1883  whether you have access to the other CP15 registers and their
1884  information about hardware capabilities */
1885  asm volatile (
1886  "mrc p15, 0, r0, c0, c0, 0\n\t"
1887  "str r0, %0\n"
1888  : "=m"(processorID)
1889  :
1890  : "cc", "r0");
1891 
1892  return( HWCAP_FLAG_NONE );
1893  }
1894 #else
1895 
1896 CHECK_RETVAL \
1897 static int getHWInfo( void )
1898  {
1899  return( HWCAP_FLAG_NONE );
1900  }
1901 #endif /* OS-specific support */
1902 
1903 /* Initialise OS-specific constants. This is a bit ugly because the values
1904  are often specific to one cryptlib module but there's no (clean) way to
1905  perform any complex per-module initialisation so we have to know about
1906  all of the module-specific sysVar requirements here */
1907 
1908 #define MAX_SYSVARS 8
1909 
1910 static int sysVars[ MAX_SYSVARS ];
1911 
1912 #if ( defined( __WIN32__ ) || defined( __WINCE__ ) )
1913 
1914 int initSysVars( void )
1915  {
1916  OSVERSIONINFO osvi = { sizeof( OSVERSIONINFO ) };
1917  SYSTEM_INFO systemInfo;
1918 
1919  static_assert( SYSVAR_LAST < MAX_SYSVARS, "System variable value" );
1920 
1921  /* Reset the system variable information */
1922  memset( sysVars, 0, MAX_SYSVARS );
1923 
1924  /* Figure out which version of Windows we're running under */
1925  if( !GetVersionEx( &osvi ) )
1926  {
1927  /* If for any reason the call fails, just use the most likely
1928  values */
1929  osvi.dwMajorVersion = 5; /* Win2K and higher */
1930  osvi.dwPlatformId = VER_PLATFORM_WIN32_NT;
1931  }
1932  sysVars[ SYSVAR_OSMAJOR ] = osvi.dwMajorVersion;
1933  sysVars[ SYSVAR_OSMINOR ] = osvi.dwMinorVersion;
1934  sysVars[ SYSVAR_ISWIN95 ] = \
1935  ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) ? \
1936  TRUE : FALSE;
1937 
1938  /* Check for Win32s just in case someone ever tries to load cryptlib under
1939  it */
1940  if( osvi.dwPlatformId == VER_PLATFORM_WIN32s )
1941  {
1942  DEBUG_DIAG(( "Win32s detected" ));
1943  assert( DEBUG_WARN );
1944  return( CRYPT_ERROR_NOTAVAIL );
1945  }
1946 
1947  /* Get the system page size */
1948  GetSystemInfo( &systemInfo );
1949  sysVars[ SYSVAR_PAGESIZE ] = systemInfo.dwPageSize;
1950 
1951  /* Get system hardware capabilities */
1952  sysVars[ SYSVAR_HWCAP ] = getHWInfo();
1953 
1954  return( CRYPT_OK );
1955  }
1956 
1957 #elif defined( __UNIX__ )
1958 
1959 #include <unistd.h>
1960 
1961 int initSysVars( void )
1962  {
1963  static_assert( SYSVAR_LAST < MAX_SYSVARS, "System variable value" );
1964 
1965  /* Reset the system variable information */
1966  memset( sysVars, 0, MAX_SYSVARS );
1967 
1968  /* Get the system page size */
1969 #if defined( _CRAY ) || defined( __hpux ) || defined( _M_XENIX ) || \
1970  defined( __aux )
1971  #if defined( _SC_PAGESIZE )
1972  sysVars[ SYSVAR_PAGESIZE ] = sysconf( _SC_PAGESIZE );
1973  #elif defined( _SC_PAGE_SIZE )
1974  sysVars[ SYSVAR_PAGESIZE ] = sysconf( _SC_PAGE_SIZE );
1975  #else
1976  sysVars[ SYSVAR_PAGESIZE ] = 4096; /* Close enough for most systems */
1977  #endif /* Systems without getpagesize() */
1978 #else
1979  sysVars[ SYSVAR_PAGESIZE ] = getpagesize();
1980 #endif /* Unix variant-specific brokenness */
1981  if( sysVars[ SYSVAR_PAGESIZE ] < 1024 )
1982  {
1983  DEBUG_DIAG(( "System reports page size < 1024" ));
1984  assert( DEBUG_WARN );
1985 
1986  /* Suspiciously small reported page size, just assume a sensible
1987  value */
1988  sysVars[ SYSVAR_PAGESIZE ] = 4096;
1989  }
1990 
1991  /* Get system hardware capabilities */
1992  sysVars[ SYSVAR_HWCAP ] = getHWInfo();
1993 
1994 #if defined( __IBMC__ ) || defined( __IBMCPP__ )
1995  /* VisualAge C++ doesn't set the TZ correctly */
1996  tzset();
1997 #endif /* VisualAge C++ */
1998 
1999  return( CRYPT_OK );
2000  }
2001 
2002 #else
2003 
2004 int initSysVars( void )
2005  {
2006  /* Reset the system variable information */
2007  memset( sysVars, 0, MAX_SYSVARS );
2008 
2009  /* Get system hardware capabilities */
2010  sysVars[ SYSVAR_HWCAP ] = getHWInfo();
2011 
2012  return( CRYPT_OK );
2013  }
2014 #endif /* OS-specific support */
2015 
2016 int getSysVar( const SYSVAR_TYPE type )
2017  {
2018  REQUIRES( type > SYSVAR_NONE && type < SYSVAR_LAST );
2019 
2020  return( sysVars[ type ] );
2021  }
2022 
2023 /****************************************************************************
2024 * *
2025 * Miscellaneous System-specific Support Functions *
2026 * *
2027 ****************************************************************************/
2028 
2029 /* Align a pointer to a given boundary. This gets quite complicated because
2030  the only pointer arithmetic that's normally allowed is addition and
2031  subtraction, but to align to a boundary we need to be able to perform
2032  bitwise operations. First we convert the pointer to a char pointer so
2033  that we can perform normal maths on it, and then we round in the usual
2034  manner used by roundUp(). Because we have to do pointer-casting and
2035  version we can't use roundUp() directly but have to build our own version
2036  here */
2037 
2038 #if defined( __WIN32__ ) || defined( __WIN64__ )
2039  #define intptr_t INT_PTR
2040 #elif defined( __ECOS__ )
2041  #define intptr_t unsigned int
2042 #elif defined( __GNUC__ ) && ( __GNUC__ >= 3 )
2043  #include <stdint.h>
2044 #elif defined( SYSTEM_64BIT )
2045  #define intptr_t long long
2046 #else
2047  #define intptr_t int
2048 #endif /* OS-specific pointer <-> int-type equivalents */
2049 
2050 void *ptr_align( const void *ptr, const int units )
2051  {
2052  assert( isReadPtr( ptr, 1 ) );
2053  assert( units > 0 && units < MAX_INTLENGTH_SHORT );
2054 
2055  return( ( void * ) ( ( char * ) ptr + ( -( ( intptr_t )( ptr ) ) & ( units - 1 ) ) ) );
2056  }
2057 
2058 /* Determine the difference between two pointers, with some sanity
2059  checking. This assumes the pointers are fairly close in location,
2060  used to determine whether pointers that were potentially relocated
2061  at some point via ptr_align() have moved */
2062 
2063 int ptr_diff( const void *ptr1, const void *ptr2 )
2064  {
2065  ptrdiff_t diff;
2066 
2067  assert( isReadPtr( ptr1, 1 ) );
2068  assert( isReadPtr( ptr2, 1 ) );
2069  assert( ptr1 >= ptr2 );
2070 
2071  diff = ( const BYTE * ) ptr1 - ( const BYTE * ) ptr2;
2072  if( diff < 0 )
2073  diff = -diff;
2074  if( diff > MAX_INTLENGTH )
2075  return( -1 );
2076 
2077  return( ( int ) diff );
2078  }